內核代碼爲Linux Kernel:3.4.x 必備知識ldd3第十四章linux設備模型
driver_register跟蹤:紅色爲主線 藍色爲標註
/**
*struct device_driver - The basic device driver structure
*@name: Name of the device driver.
*@bus: The bus which the device of thisdriver belongs to.
*@owner: The module owner.
*@mod_name: Used for built-in modules.
*@suppress_bind_attrs: Disables bind/unbind via sysfs.
*@of_match_table: The open firmware table.
*@probe: Called to query the existenceof a specific device,
* whether this driver can work with it,and bind the driver
* to a specific device.
*@remove: Called when the device isremoved from the system to
* unbind a device from this driver.
*@shutdown: Called at shut-down timeto quiesce the device.
*@suspend: Called to put the device to sleepmode. Usually to a
* low power state.
*@resume: Called to bring a device fromsleep mode.
*@groups: Default attributes that getcreated by the driver core
* automatically.
*@pm: Power management operations ofthe device which matched
* this driver.
*@p: Driver core's private data,no one other than the driver
* core can touch this.
*
*The device driver-model tracks all of the drivers known to the system.
*The main reason for this tracking is to enable the driver core to match
* updrivers with new devices. Once drivers are known objects within the
*system, however, a number of other things become possible. Device drivers
*can export information and configuration variables that are independent
* ofany specific device.
*/
struct device_driver {
constchar *name;
structbus_type *bus;
structmodule *owner;
constchar *mod_name; /* used for built-in modules */
boolsuppress_bind_attrs; /* disablesbind/unbind via sysfs */
conststruct of_device_id *of_match_table;
int(*probe) (struct device *dev);
int(*remove) (struct device *dev);
void(*shutdown) (struct device *dev);
int(*suspend) (struct device *dev, pm_message_t state);
int(*resume) (struct device *dev);
conststruct attribute_group **groups;
conststruct dev_pm_ops *pm;
structdriver_private *p;
};
/**
*driver_register - register driver with bus
*@drv: driver to register
*
* Wepass off most of the work to the bus_add_driver() call,
*since most of the things we have to do deal with the bus
*structures.
*/
int driver_register(struct device_driver*drv)
{
intret;
structdevice_driver *other;
BUG_ON(!drv->bus->p); //p不存在斷言並輸出信息;其實這個主要是判斷bus是否存在 詳見標註一
if((drv->bus->probe && drv->probe) ||
(drv->bus->remove &&drv->remove) ||
(drv->bus->shutdown &&drv->shutdown)) //driver和driver所屬bus的probe、remove、shutdown一組存在則提示更新;主要是判斷驅動跟驅動的總線是否有衝突的函數註冊,給出警告信息
printk(KERN_WARNING"Driver '%s' needs updating - please use "
"bus_typemethods\n", drv->name);
other= driver_find(drv->name, drv->bus); //在bus上以name找driver;存在說明已經註冊 退出返回EBUSY詳見標註二
if(other) {
printk(KERN_ERR"Error: Driver '%s' is already registered, "
"aborting...\n",drv->name);
return-EBUSY;
}
ret= bus_add_driver(drv); //向bus添加driver 成功返回0
if(ret)
returnret;
ret= driver_add_groups(drv, drv->groups); //如果grop不爲空的話,將在驅動文件夾下創建以group名字的子文件夾,然後在子文件夾下添加group的屬性文件
if(ret)
bus_remove_driver(drv); //出錯從bus上刪除driver
returnret;
}
標註一:
BUG_ON原型爲
#define BUG_ON(condition) do { if(unlikely(condition)) BUG(); } while(0)
#define BUG()do { \
printk("kernelBUG at %s:%d!\n", __FILE__, __LINE__); \
panic("BUG!");\
} while (0)
標註一end
標註二:
struct device_driver *driver_find(constchar *name, struct bus_type *bus)
{
structkobject *k = kset_find_obj(bus->p->drivers_kset, name); //在bus的驅動集合裏尋找同名的驅動
structdriver_private *priv;
if(k) {
/*Drop reference added by kset_find_obj() */
kobject_put(k); //如果找到減小引用計數
priv= to_driver(k); //通過kobject轉換成driver_private,返回相應的驅動
returnpriv->driver;
}
returnNULL;
}
標註二end
int bus_add_driver(structdevice_driver *drv)
{
structbus_type *bus;
structdriver_private *priv;
interror = 0;
bus= bus_get(drv->bus); //找到該drv所屬的bus,其實就是增加該bus->p->subsys->kobject->kref的引用計數
if(!bus)
return-EINVAL;
pr_debug("bus:'%s': add driver %s\n", bus->name, drv->name);
priv= kzalloc(sizeof(*priv), GFP_KERNEL); //分配driver_private結構
if(!priv) {
error= -ENOMEM;
gotoout_put_bus;
}
klist_init(&priv->klist_devices,NULL, NULL); //初始化priv->klist_devices
priv->driver= drv; //將該drv賦值給priv->driver
drv->p= priv; //而drv的drv->p又等於priv
priv->kobj.kset= bus->p->drivers_kset; //指向bus的drvier容器
error= kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,
"%s", drv->name); //驅動的kobject初始化和添加dir到sysfs中,詳見標註三
if(error)
gotoout_unregister;
klist_add_tail(&priv->knode_bus,&bus->p->klist_drivers); //初始化busnode鏈表並添加klist_driver到末尾
if(drv->bus->p->drivers_autoprobe) { //drivers_autoprobe其值爲1;bus註冊的時候設定
error= driver_attach(drv);
if(error)
gotoout_unregister;
}
module_add_driver(drv->owner,drv); //添加drv的module 標註六
error= driver_create_file(drv, &driver_attr_uevent); //在sysfs的目錄下創建文件uevent屬性文件,見標註七
if(error) {
printk(KERN_ERR"%s: uevent attr (%s) failed\n",
__func__,drv->name);
}
error= driver_add_attrs(bus, drv); //給driver添加bus上的所有屬性
if(error) {
/*How the hell do we get out of this pickle? Give up */
printk(KERN_ERR"%s: driver_add_attrs(%s) failed\n",
__func__,drv->name);
}
if(!drv->suppress_bind_attrs) {
error= add_bind_files(drv); //添加綁定文件,driver_attr_bind 和 driver_attr_unbind見標註七
if(error) {
/*Ditto */
printk(KERN_ERR"%s: add_bind_files(%s) failed\n",
__func__,drv->name);
}
}
kobject_uevent(&priv->kobj,KOBJ_ADD); //產生一個KOBJ_ADD uevent
return0;
out_unregister:
kobject_put(&priv->kobj);
kfree(drv->p);
drv->p= NULL;
out_put_bus:
bus_put(bus);
returnerror;
}
標註三:
int kobject_init_and_add(struct kobject*kobj, struct kobj_type *ktype,
struct kobject *parent, const char *fmt, ...)
{
va_listargs;
intretval;
kobject_init(kobj,ktype); //初始化kobject
va_start(args,fmt); //動態可變參數的使用
retval= kobject_add_varg(kobj, parent, fmt, args); //函數包含的操作kobject_set_name_vargs(kobj, fmt, vargs)設置kobject和 kobject_add_internal(kobj)
va_end(args);
returnretval;
}
static intkobject_add_varg(struct kobject *kobj, struct kobject *parent,
constchar *fmt, va_list vargs)
{
intretval;
retval= kobject_set_name_vargs(kobj, fmt, vargs); //主要是將vargs按照fmt格式給kobject起個名字,從調用關係知道vargs是drv->name,也就是驅動的名字
if(retval) {
printk(KERN_ERR"kobject: can not set name properly!\n");
returnretval;
}
kobj->parent= parent;
returnkobject_add_internal(kobj);
}
static intkobject_add_internal(struct kobject *kobj) //這個函數主要設置drvier的kobject和bus之間的層次關係,然後在sysfs中建立該驅動的文件夾
{
interror = 0;
structkobject *parent;
if(!kobj)
return-ENOENT;
if(!kobj->name || !kobj->name[0]) {
WARN(1,"kobject: (%p): attempted to be registered with empty "
"name!\n", kobj);
return-EINVAL;
}
parent= kobject_get(kobj->parent); //得到父節點,從上面知道parent是NULL
/*join kset if set, use it as parent if we do not already have one */
if(kobj->kset) { //kset不爲空
if(!parent) //parent爲空
parent= kobject_get(&kobj->kset->kobj);
kobj_kset_join(kobj);
kobj->parent= parent;
/*如果kset不爲空,而parent爲空(這裏這個條件一定成立的,因爲kset=bus->p->drivers_kset,parent=NULL),
則該kobj->parent指向kobj->kset->kobj,而且將kobj加入到kobj->kset的list中,也就是driver放入bus的kset列表中,也就是bus是driver的容器,實際上bus同時還是device的容器,當然bus本身實質上也是個kobject,所以理解kset這個容器的概念至關重要,它是構成了sysfs的層次結構關係*/
}
pr_debug("kobject:'%s' (%p): %s: parent: '%s', set: '%s'\n",
kobject_name(kobj), kobj, __func__,
parent ? kobject_name(parent) :"<NULL>",
kobj->kset ?kobject_name(&kobj->kset->kobj) : "<NULL>");
error= create_dir(kobj); //建立該驅動的文件夾
if(error) {
kobj_kset_leave(kobj);
kobject_put(parent);
kobj->parent= NULL;
/*be noisy on error issues */
if(error == -EEXIST)
WARN(1,"%s failed for %s with "
"-EEXIST, don't try to registerthings with "
"the same name in the samedirectory.\n",
__func__, kobject_name(kobj));
else
WARN(1,"%s failed for %s (error: %d parent: %s)\n",
__func__, kobject_name(kobj), error,
parent ? kobject_name(parent) :"'none'");
}else
kobj->state_in_sysfs= 1;
returnerror;
}
標註三end
int driver_attach(structdevice_driver *drv)
{
returnbus_for_each_dev(drv->bus, NULL, drv,__driver_attach);
}
intbus_for_each_dev(struct bus_type *bus, struct device *start,
void *data,int (*fn)(struct device *, void *))
{
structklist_iter i;
structdevice *dev;
interror = 0;
if(!bus)
return-EINVAL;
klist_iter_init_node(&bus->p->klist_devices,&i,
(start ? &start->p->knode_bus :NULL)); //將bus中的已註冊的device列表放到迭代器中,方便索引
while((dev = next_device(&i)) && !error) //將驅動逐個地與列表中每一個的device匹配,可能一個驅動匹配好幾個設備
error= fn(dev, data); //這個fn就是上面傳下來的__driver_attach
klist_iter_exit(&i);
returnerror;
}
static int__driver_attach(struct device *dev, void *data)
{
structdevice_driver *drv = data;
/*
* Lock device and try to bind to it. We dropthe error
* here and always return 0, because we need tokeep trying
* to bind to devices and some drivers willreturn an error
* simply if it didn't support the device.
*
* driver_probe_device() will spit a warning ifthere
* is an error.
*/
if(!driver_match_device(drv, dev)) //driver嘗試與device匹配 詳見標註四
return0;
if(dev->parent) /* Needed for USB */
device_lock(dev->parent);
device_lock(dev);
if(!dev->driver) //如果設備沒有指定driver
driver_probe_device(drv,dev); //那麼需要初始化匹配到的這個設備attempt to bind device & driver together 詳見標註五
device_unlock(dev);
if(dev->parent)
device_unlock(dev->parent);
return0;
}
標註四:
static inline intdriver_match_device(struct device_driver *drv,
struct device *dev)
{
returndrv->bus->match ? drv->bus->match(dev, drv) : 1;
}
這裏看bus的總線的match函數是否已經註冊,如果沒註冊則直接返回1直接成功,如果註冊,則調用註冊的匹配函數。match通常實現爲首先掃描driver支持的id設備表,如果爲NULL就用名字進行匹配
以i2c總線爲例:
structbus_type i2c_bus_type = {
.name = "i2c",
.dev_attrs = i2c_dev_attrs,
.match = i2c_device_match,
...
};
static int i2c_device_match(struct device *dev, struct device_driver *drv)
{
struct i2c_client *client = to_i2c_client(dev);
struct i2c_driver *driver = to_i2c_driver(drv);
/* match on an id table if there is one */
if (driver->id_table)
return i2c_match_id(driver->id_table, client) != NULL;//只匹配id的名字和client的名字,跟驅動的名字沒有關係,注意這裏的client是設備轉換過來,而不是設備的本身
return 0;
}
轉而調用i2c_match_id();
static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,
const struct i2c_client *client)
{
while (id->name[0]) {
if (strcmp(client->name, id->name) == 0) //匹配設備client名字和id_table中的名字
return id;
id++;
}
return NULL;
}
所以i2c總線根據設備client名字和id_table中的名字進行匹配的。如果匹配了,則返回id值,在i2c_device_match中則返回真。也就是bus的match函數將會返回真。那將會進入driver_probe_device()。
4-2-1-1-2,driver_probe_device()
int driver_probe_device(struct device_driver *drv, struct device *dev)
{
int ret = 0;
if (!device_is_registered(dev)) //首先判斷這個device是否已經註冊
return -ENODEV;
pr_debug("bus: '%s': %s: matched device %s with driver %s\n",
drv->bus->name, __func__, dev_name(dev), drv->name);
ret = really_probe(dev, drv); //轉而調用really_probe()
return ret;
}
4-2-1-1-2-1,really_probe()
static atomic_t probe_count = ATOMIC_INIT(0); //記錄probe數目
static DECLARE_WAIT_QUEUE_HEAD(probe_waitqueue); //probe隊列
static int really_probe(struct device *dev, struct device_driver *drv)
{
int ret = 0;
atomic_inc(&probe_count); //原子增加計數
pr_debug("bus: '%s': %s: probing driver %s with device %s\n",
drv->bus->name, __func__, drv->name, dev_name(dev));
WARN_ON(!list_empty(&dev->devres_head));
dev->driver = drv; //把驅動賦值給dev->drvier
if (driver_sysfs_add(dev)) { //主要是添加driver和dev之間的連接文件,見4-2-1-1-2-1-1分析
printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",
__func__, dev_name(dev));
goto probe_failed;
}
if (dev->bus->probe) { //如果bus的probe註冊將執行,否則執行driver的probe,這也是函數開始時檢測的原因!
ret = dev->bus->probe(dev);
if (ret)
goto probe_failed;
} else if (drv->probe) {
ret = drv->probe(dev);
if (ret)
goto probe_failed;
}
driver_bound(dev); //driver綁定dev,見4-2-1-1-2-1-2分析
ret = 1;
pr_debug("bus: '%s': %s: bound device %s to driver %s\n",
drv->bus->name, __func__, dev_name(dev), drv->name);
goto done;
probe_failed:
devres_release_all(dev);
driver_sysfs_remove(dev);
dev->driver = NULL;
if (ret != -ENODEV && ret != -ENXIO) {
/* driver matched but the probe failed */
printk(KERN_WARNING
"%s: probe of %s failed with error %d\n",
drv->name, dev_name(dev), ret);
}
/*
* Ignore errors returned by ->probe so that the next driver can try
* its luck.
*/
ret = 0;
done:
atomic_dec(&probe_count);
wake_up(&probe_waitqueue);
return ret;
}
4-2-1-1-2-1-1,driver_sysfs_add
static int driver_sysfs_add(struct device *dev)
{
int ret;
ret = sysfs_create_link(&dev->driver->p->kobj, &dev->kobj,
kobject_name(&dev->kobj)); //在driver目錄下添加以dev->kobj名字的連接文件,連接到device
if (ret == 0) {
ret = sysfs_create_link(&dev->kobj, &dev->driver->p->kobj,
"driver"); //同樣在device目錄下添加‘driver’爲名字的連接文件連接到drvier
if (ret)
sysfs_remove_link(&dev->driver->p->kobj,
kobject_name(&dev->kobj));
}
return ret;
}
4-2-1-1-2-1-2,driver_bound()
static void driver_bound(struct device *dev)
{
if (klist_node_attached(&dev->p->knode_driver)) { //查看是否已經綁定
printk(KERN_WARNING "%s: device %s already bound\n",
__func__, kobject_name(&dev->kobj));
return;
}
pr_debug("driver: '%s': %s: bound to device '%s'\n", dev_name(dev),
__func__, dev->driver->name);
if (dev->bus)
blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
BUS_NOTIFY_BOUND_DRIVER, dev); //調用註冊bus通知鏈上的所有函數
klist_add_tail(&dev->p->knode_driver,&dev->driver->p->klist_devices); //將設備的驅動node添加到diver的klist_devices中.
}
標註四end
標註五:
intdriver_probe_device(struct device_driver *drv, struct device *dev)
{
int ret = 0;
if (!device_is_registered(dev))
return -ENODEV;
pr_debug("bus: '%s': %s: matched device %s with driver%s\n",
drv->bus->name, __func__, dev_name(dev),drv->name);
pm_runtime_get_noresume(dev);
pm_runtime_barrier(dev);
ret = really_probe(dev, drv);
pm_runtime_put_sync(dev);
return ret;
}
static inline int device_is_registered(structdevice *dev)
{
returndev->kobj.state_in_sysfs; // 在sysfs中表示已經註冊
}
static int really_probe(structdevice *dev, struct device_driver *drv)
{
intret = 0;
atomic_inc(&probe_count);
pr_debug("bus:'%s': %s: probing driver %s with device %s\n",
drv->bus->name, __func__, drv->name,dev_name(dev));
WARN_ON(!list_empty(&dev->devres_head));
dev->driver= drv; // device的driver初始化成該driver
/*If using pinctrl, bind pins now before probing */
ret= pinctrl_bind_pins(dev);
if(ret)
gotoprobe_failed;
if(driver_sysfs_add(dev)) {
printk(KERN_ERR"%s: driver_sysfs_add(%s) failed\n",
__func__,dev_name(dev));
gotoprobe_failed;
}
//利用probe初始化設備
if(dev->bus->probe) { //如果bus的probe存在就用bus的
ret= dev->bus->probe(dev);
if(ret)
gotoprobe_failed;
}else if (drv->probe) { //如果bus的不存在driver的存在再用driver的
ret= drv->probe(dev);
if(ret)
gotoprobe_failed;
}
driver_bound(dev); //調用driver_bound進行綁定
ret= 1;
pr_debug("bus:'%s': %s: bound device %s to driver %s\n",
drv->bus->name, __func__, dev_name(dev),drv->name);
gotodone;
probe_failed:
devres_release_all(dev);
driver_sysfs_remove(dev);
dev->driver= NULL;
if(ret == -EPROBE_DEFER) {
/*Driver requested deferred probing */
dev_info(dev,"Driver %s requests probe deferral\n", drv->name);
driver_deferred_probe_add(dev);
}else if (ret != -ENODEV && ret != -ENXIO) {
/*driver matched but the probe failed */
printk(KERN_WARNING
"%s: probe of %s failed with error%d\n",
drv->name, dev_name(dev), ret);
}else {
pr_debug("%s:probe of %s rejects match %d\n",
drv->name, dev_name(dev), ret);
}
/*
* Ignore errors returned by ->probe so thatthe next driver can try
* its luck.
*/
ret= 0;
done:
atomic_dec(&probe_count);
wake_up(&probe_waitqueue);
returnret;
}
static void driver_bound(structdevice *dev)
{
if(klist_node_attached(&dev->p->knode_driver)) { //判斷是否已經綁定
printk(KERN_WARNING"%s: device %s already bound\n",
__func__,kobject_name(&dev->kobj));
return;
}
pr_debug("driver:'%s': %s: bound to device '%s'\n", dev_name(dev),
__func__, dev->driver->name);
klist_add_tail(&dev->p->knode_driver,&dev->driver->p->klist_devices); //將設備添加到driver的鏈表
/*
* Make sure the device is no longer in one ofthe deferred lists and
* kick off retrying all pending devices
*/
driver_deferred_probe_del(dev);
driver_deferred_probe_trigger();
if(dev->bus)
blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
BUS_NOTIFY_BOUND_DRIVER, dev);
}
標註五end
標註六:
void module_add_driver(struct module *mod,struct device_driver *drv)
{
char*driver_name;
intno_warn;
structmodule_kobject *mk = NULL;
if(!drv)
return;
if(mod) //一般情況下爲THIS_MODULE
mk= &mod->mkobj;
elseif (drv->mod_name) { //如果沒模塊,則檢查驅動的模塊名
structkobject *mkobj;
/*Lookup built-in module entry in /sys/modules */
mkobj= kset_find_obj(module_kset, drv->mod_name); //根據驅動模塊的名字去module_kset集合中找
if(mkobj) {
mk= container_of(mkobj, struct module_kobject, kobj); //用container_of方法通過kobj轉換成module_kobject
/*remember our module structure */
drv->p->mkobj= mk; //賦值給驅動的mkobj
/*kset_find_obj took a reference */
kobject_put(mkobj);
}
}
if(!mk) //mk如果爲null則返回
return;
/*Don't check return codes; these calls are idempotent */
no_warn= sysfs_create_link(&drv->p->kobj, &mk->kobj,"module"); //在驅動文件夾下創建名爲‘module’的鏈接文件,鏈接到module文件夾
driver_name= make_driver_name(drv); //生成driver_name,給module用
if(driver_name) {
module_create_drivers_dir(mk); //在具體的module文件夾下創建driver目錄
no_warn= sysfs_create_link(mk->drivers_dir, &drv->p->kobj,
driver_name); //在上面創建的driver目錄下,生成一個名爲driver_name指定的鏈接文件,鏈接到驅動的文件夾
kfree(driver_name);
}
}
static char *make_driver_name(structdevice_driver *drv) //這個函數的功能就是生成一個名字,這個有bus和驅動的名字組成
{
char*driver_name;
driver_name= kasprintf(GFP_KERNEL, "%s:%s", drv->bus->name, drv->name); 申請內存並將bus的名字和驅動的名字組成一塊,中間加一個冒號
if(!driver_name)
returnNULL;
returndriver_name;
}
標註六end
標註七:
/**
*driver_create_file - create sysfs file for driver.
*@drv: driver.
*@attr: driver attribute descriptor.
*/
int driver_create_file(struct device_driver*drv,
const struct driver_attribute *attr)
{
interror;
if(drv)
error= sysfs_create_file(&drv->p->kobj, &attr->attr);
else
error= -EINVAL;
returnerror;
}
static int driver_add_attrs(struct bus_type*bus, struct device_driver *drv)
{
interror = 0;
inti;
if(bus->drv_attrs) {
for(i = 0; attr_name(bus->drv_attrs[i]); i++) {
error= driver_create_file(drv, &bus->drv_attrs[i]);
if(error)
gotoerr;
}
}
done:
returnerror;
err:
while(--i >= 0)
driver_remove_file(drv,&bus->drv_attrs[i]);
gotodone;
}
static int __must_checkadd_bind_files(struct device_driver *drv)
{
intret;
ret= driver_create_file(drv, &driver_attr_unbind);
if(ret == 0) {
ret= driver_create_file(drv, &driver_attr_bind);
if(ret)
driver_remove_file(drv,&driver_attr_unbind);
}
returnret;
}
標註七end
總結一下,driver的註冊,主要涉及將自身掛接到bus的driver鏈表,並將匹配到的設備加入自己的device鏈表,並且將匹配到的device的driver成員初始化爲該driver,私有屬性的driver節點也掛到driver的設備鏈表下,其中匹配函數是利用利用bus的match函數,該函數通常判斷如果driver有id表,就查表匹配,如果沒有就用driver和device名字匹配。當匹配成功後如果自動初始化標誌允許則調用初始化函數probe,bus的probe優先級始終高於driver的。另外注意一點driver是沒有總的起始端點的,driver不是可具體描述的事物。