Commit 06d2fe15 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'driver-core-3.6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core

Pull driver core merge from Greg Kroah-Hartman:
 "Here is the big driver core update for 3.7-rc1.

  A number of firmware_class.c updates (as you saw a month or so ago),
  and some hyper-v updates and some printk fixes as well.  All patches
  that are outside of the drivers/base area have been acked by the
  respective maintainers, and have all been in the linux-next tree for a
  while.

  Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>"

* tag 'driver-core-3.6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: (95 commits)
  memory: tegra{20,30}-mc: Fix reading incorrect register in mc_readl()
  device.h: Add missing inline to #ifndef CONFIG_PRINTK dev_vprintk_emit
  memory: emif: Add ifdef CONFIG_DEBUG_FS guard for emif_debugfs_[init|exit]
  Documentation: Fixes some translation error in Documentation/zh_CN/gpio.txt
  Documentation: Remove 3 byte redundant code at the head of the Documentation/zh_CN/arm/booting
  Documentation: Chinese translation of Documentation/video4linux/omap3isp.txt
  device and dynamic_debug: Use dev_vprintk_emit and dev_printk_emit
  dev: Add dev_vprintk_emit and dev_printk_emit
  netdev_printk/netif_printk: Remove a superfluous logging colon
  netdev_printk/dynamic_netdev_dbg: Directly call printk_emit
  dev_dbg/dynamic_debug: Update to use printk_emit, optimize stack
  driver-core: Shut up dev_dbg_reatelimited() without DEBUG
  tools/hv: Parse /etc/os-release
  tools/hv: Check for read/write errors
  tools/hv: Fix exit() error code
  tools/hv: Fix file handle leak
  Tools: hv: Implement the KVP verb - KVP_OP_GET_IP_INFO
  Tools: hv: Rename the function kvp_get_ip_address()
  Tools: hv: Implement the KVP verb - KVP_OP_SET_IP_INFO
  Tools: hv: Add an example script to configure an interface
  ...
parents 3aebd34b e0f21e6d
......@@ -13,7 +13,7 @@ Description:
accessory cables have such capability. For example,
the 30-pin port of Nuri board (/arch/arm/mach-exynos)
may have both HDMI and Charger attached, or analog audio,
video, and USB cables attached simulteneously.
video, and USB cables attached simultaneously.
If there are cables mutually exclusive with each other,
such binary relations may be expressed with extcon_dev's
......@@ -35,7 +35,7 @@ Description:
The /sys/class/extcon/.../state shows and stores the cable
attach/detach information of the corresponding extcon object.
If the extcon object has an optional callback "show_state"
defined, the showing function is overriden with the optional
defined, the showing function is overridden with the optional
callback.
If the default callback for showing function is used, the
......@@ -46,19 +46,19 @@ Description:
TA=1
EAR_JACK=0
#
In this example, the extcon device have USB_OTG and TA
In this example, the extcon device has USB_OTG and TA
cables attached and HDMI and EAR_JACK cables detached.
In order to update the state of an extcon device, enter a hex
state number starting with 0x.
echo 0xHEX > state
state number starting with 0x:
# echo 0xHEX > state
This updates the whole state of the extcon dev.
This updates the whole state of the extcon device.
Inputs of all the methods are required to meet the
mutually_exclusive contidions if they exist.
mutually_exclusive conditions if they exist.
It is recommended to use this "global" state interface if
you need to enter the value atomically. The later state
you need to set the value atomically. The later state
interface associated with each cable cannot update
multiple cable states of an extcon device simultaneously.
......@@ -73,7 +73,7 @@ What: /sys/class/extcon/.../cable.x/state
Date: February 2012
Contact: MyungJoo Ham <myungjoo.ham@samsung.com>
Description:
The /sys/class/extcon/.../cable.x/name shows and stores the
The /sys/class/extcon/.../cable.x/state shows and stores the
state of cable "x" (integer between 0 and 31) of an extcon
device. The state value is either 0 (detached) or 1
(attached).
......@@ -83,8 +83,8 @@ Date: December 2011
Contact: MyungJoo Ham <myungjoo.ham@samsung.com>
Description:
Shows the relations of mutually exclusiveness. For example,
if the mutually_exclusive array of extcon_dev is
{0x3, 0x5, 0xC, 0x0}, the, the output is:
if the mutually_exclusive array of extcon device is
{0x3, 0x5, 0xC, 0x0}, then the output is:
# ls mutually_exclusive/
0x3
0x5
......
......@@ -15,8 +15,8 @@ Debugfs is typically mounted with a command like:
mount -t debugfs none /sys/kernel/debug
(Or an equivalent /etc/fstab line).
The debugfs root directory is accessible by anyone by default. To
restrict access to the tree the "uid", "gid" and "mode" mount
The debugfs root directory is accessible only to the root user by
default. To change access to the tree the "uid", "gid" and "mode" mount
options can be used.
Note that the debugfs API is exported GPL-only to modules.
......
......@@ -284,9 +284,11 @@ instead, it is associated with the ktype. So let us introduce struct
kobj_type:
struct kobj_type {
void (*release)(struct kobject *);
void (*release)(struct kobject *kobj);
const struct sysfs_ops *sysfs_ops;
struct attribute **default_attrs;
struct attribute **default_attrs;
const struct kobj_ns_type_operations *(*child_ns_type)(struct kobject *kobj);
const void *(*namespace)(struct kobject *kobj);
};
This structure is used to describe a particular type of kobject (or, more
......
Chinese translated version of Documentation/arm/Booting
If you have any comment or update to the content, please contact the
original document maintainer directly. However, if you have a problem
communicating in English you can also ask the Chinese maintainer for
help. Contact the Chinese maintainer if this translation is outdated
or if there is a problem with the translation.
Maintainer: Russell King <linux@arm.linux.org.uk>
Chinese maintainer: Fu Wei <tekkamanninja@gmail.com>
---------------------------------------------------------------------
Documentation/arm/Booting 的中文翻译
如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文
交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻
译存在问题,请联系中文版维护者。
英文版维护者: Russell King <linux@arm.linux.org.uk>
中文版维护者: 傅炜 Fu Wei <tekkamanninja@gmail.com>
中文版翻译者: 傅炜 Fu Wei <tekkamanninja@gmail.com>
中文版校译者: 傅炜 Fu Wei <tekkamanninja@gmail.com>
以下为正文
---------------------------------------------------------------------
启动 ARM Linux
==============
作者:Russell King
日期:2002年5月18日
以下文档适用于 2.4.18-rmk6 及以上版本。
为了启动 ARM Linux,你需要一个引导装载程序(boot loader),
它是一个在主内核启动前运行的一个小程序。引导装载程序需要初始化各种
设备,并最终调用 Linux 内核,将信息传递给内核。
从本质上讲,引导装载程序应提供(至少)以下功能:
1、设置和初始化 RAM。
2、初始化一个串口。
3、检测机器的类型(machine type)。
4、设置内核标签列表(tagged list)。
5、调用内核映像。
1、设置和初始化 RAM
-------------------
现有的引导加载程序: 强制
新开发的引导加载程序: 强制
引导装载程序应该找到并初始化系统中所有内核用于保持系统变量数据的 RAM。
这个操作的执行是设备依赖的。(它可能使用内部算法来自动定位和计算所有
RAM,或可能使用对这个设备已知的 RAM 信息,还可能使用任何引导装载程序
设计者想到的匹配方法。)
2、初始化一个串口
-----------------------------
现有的引导加载程序: 可选、建议
新开发的引导加载程序: 可选、建议
引导加载程序应该初始化并使能一个目标板上的串口。这允许内核串口驱动
自动检测哪个串口用于内核控制台。(一般用于调试或与目标板通信。)
作为替代方案,引导加载程序也可以通过标签列表传递相关的'console='
选项给内核以指定某个串口,而串口数据格式的选项在以下文档中描述:
Documentation/kernel-parameters.txt。
3、检测机器类型
--------------------------
现有的引导加载程序: 可选
新开发的引导加载程序: 强制
引导加载程序应该通过某些方式检测自身所处的机器类型。这是一个硬件
代码或通过查看所连接的硬件用某些算法得到,这些超出了本文档的范围。
引导加载程序最终必须能提供一个 MACH_TYPE_xxx 值给内核。
(详见 linux/arch/arm/tools/mach-types )。
4、设置启动数据
------------------
现有的引导加载程序: 可选、强烈建议
新开发的引导加载程序: 强制
引导加载程序必须提供标签列表或者 dtb 映像以传递配置数据给内核。启动
数据的物理地址通过寄存器 r2 传递给内核。
4a、设置内核标签列表
--------------------------------
bootloader 必须创建和初始化内核标签列表。一个有效的标签列表以
ATAG_CORE 标签开始,并以 ATAG_NONE 标签结束。ATAG_CORE 标签可以是
空的,也可以是非空。一个空 ATAG_CORE 标签其 size 域设置为
‘2’(0x00000002)。ATAG_NONE 标签的 size 域必须设置为零。
在列表中可以保存任意数量的标签。对于一个重复的标签是追加到之前标签
所携带的信息之后,还是会覆盖原来的信息,是未定义的。某些标签的行为
是前者,其他是后者。
bootloader 必须传递一个系统内存的位置和最小值,以及根文件系统位置。
因此,最小的标签列表如下所示:
+-----------+
基地址 -> | ATAG_CORE | |
+-----------+ |
| ATAG_MEM | | 地址增长方向
+-----------+ |
| ATAG_NONE | |
+-----------+ v
标签列表应该保存在系统的 RAM 中。
标签列表必须置于内核自解压和 initrd'bootp' 程序都不会覆盖的内存区。
建议放在 RAM 的头 16KiB 中。
4b、设置设备树
-------------------------
bootloader 必须以 64bit 地址对齐的形式加载一个设备树映像(dtb)到系统
RAM 中,并用启动数据初始化它。dtb 格式在文档
Documentation/devicetree/booting-without-of.txt 中。内核将会在
dtb 物理地址处查找 dtb 魔数值(0xd00dfeed),以确定 dtb 是否已经代替
标签列表被传递进来。
bootloader 必须传递一个系统内存的位置和最小值,以及根文件系统位置。
dtb 必须置于内核自解压不会覆盖的内存区。建议将其放置于 RAM 的头 16KiB
中。但是不可将其放置于“0”物理地址处,因为内核认为:r2 中为 0,意味着
没有标签列表和 dtb 传递过来。
5、调用内核映像
---------------------------
现有的引导加载程序: 强制
新开发的引导加载程序: 强制
调用内核映像 zImage 有两个选择。如果 zImge 保存在 flash 中,且是为了
在 flash 中直接运行而被正确链接的。这样引导加载程序就可以在 flash 中
直接调用 zImage。
zImage 也可以被放在系统 RAM(任意位置)中被调用。注意:内核使用映像
基地址的前 16KB RAM 空间来保存页表。建议将映像置于 RAM 的 32KB 处。
对于以上任意一种情况,都必须符合以下启动状态:
- 停止所有 DMA 设备,这样内存数据就不会因为虚假网络包或磁盘数据而被破坏。
这可能可以节省你许多的调试时间。
- CPU 寄存器配置
r0 = 0,
r1 = (在上面 3 中获取的)机器类型码。
r2 = 标签列表在系统 RAM 中的物理地址,或
设备树块(dtb)在系统 RAM 中的物理地址
- CPU 模式
所有形式的中断必须被禁止 (IRQs 和 FIQs)
CPU 必须处于 SVC 模式。(对于 Angel 调试有特例存在)
- 缓存,MMUs
MMU 必须关闭。
指令缓存开启或关闭都可以。
数据缓存必须关闭。
- 引导加载程序应该通过直接跳转到内核映像的第一条指令来调用内核映像。
对于支持 ARM 指令集的 CPU,跳入内核入口时必须处在 ARM 状态,即使
对于 Thumb-2 内核也是如此。
对于仅支持 Thumb 指令集的 CPU,比如 Cortex-M 系列的 CPU,跳入
内核入口时必须处于 Thumb 状态。
Chinese translated version of Documentation/basic_profiling
If you have any comment or update to the content, please post to LKML directly.
However, if you have problem communicating in English you can also ask the
Chinese maintainer for help. Contact the Chinese maintainer, if this
translation is outdated or there is problem with translation.
Chinese maintainer: Liang Xie <xieliang@xiaomi.com>
---------------------------------------------------------------------
Documentation/basic_profiling的中文翻译
如果想评论或更新本文的内容,请直接发信到LKML。如果你使用英文交流有困难的话,也可
以向中文版维护者求助。如果本翻译更新不及时或者翻译存在问题,请联系中文版维护者。
中文版维护者: 谢良 Liang Xie <xieliang007@gmail.com>
中文版翻译者: 谢良 Liang Xie <xieliang007@gmail.com>
中文版校译者:
以下为正文
---------------------------------------------------------------------
下面这些说明指令都是非常基础的,如果你想进一步了解请阅读相关专业文档:)
请不要再在本文档增加新的内容,但可以修复文档中的错误:)(mbligh@aracnet.com)
感谢John Levon,Dave Hansen等在撰写时的帮助
<test> 用于表示要测量的目标
请先确保您已经有正确的System.map / vmlinux配置!
对于linux系统来说,配置vmlinuz最容易的方法可能就是使用“make install”,然后修改
/sbin/installkernel将vmlinux拷贝到/boot目录,而System.map通常是默认安装好的
Readprofile
-----------
2.6系列内核需要版本相对较新的readprofile,比如util-linux 2.12a中包含的,可以从:
http://www.kernel.org/pub/linux/utils/util-linux/ 下载
大部分linux发行版已经包含了.
启用readprofile需要在kernel启动命令行增加”profile=2“
clear readprofile -r
<test>
dump output readprofile -m /boot/System.map > captured_profile
Oprofile
--------
从http://oprofile.sourceforge.net/获取源代码(请参考Changes以获取匹配的版本)
在kernel启动命令行增加“idle=poll”
配置CONFIG_PROFILING=y和CONFIG_OPROFILE=y然后重启进入新kernel
./configure --with-kernel-support
make install
想得到好的测量结果,请确保启用了本地APIC特性。如果opreport显示有0Hz CPU,
说明APIC特性没有开启。另外注意idle=poll选项可能有损性能。
One time setup:
opcontrol --setup --vmlinux=/boot/vmlinux
clear opcontrol --reset
start opcontrol --start
<test>
stop opcontrol --stop
dump output opreport > output_file
如果只看kernel相关的报告结果,请运行命令 opreport -l /boot/vmlinux > output_file
通过reset选项可以清理过期统计数据,相当于重启的效果。
Chinese translated version of Documentation/filesystems/sysfs.txt
If you have any comment or update to the content, please contact the
original document maintainer directly. However, if you have a problem
communicating in English you can also ask the Chinese maintainer for
help. Contact the Chinese maintainer if this translation is outdated
or if there is a problem with the translation.
Maintainer: Patrick Mochel <mochel@osdl.org>
Mike Murphy <mamurph@cs.clemson.edu>
Chinese maintainer: Fu Wei <tekkamanninja@gmail.com>
---------------------------------------------------------------------
Documentation/filesystems/sysfs.txt 的中文翻译
如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文
交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻
译存在问题,请联系中文版维护者。
英文版维护者: Patrick Mochel <mochel@osdl.org>
Mike Murphy <mamurph@cs.clemson.edu>
中文版维护者: 傅炜 Fu Wei <tekkamanninja@gmail.com>
中文版翻译者: 傅炜 Fu Wei <tekkamanninja@gmail.com>
中文版校译者: 傅炜 Fu Wei <tekkamanninja@gmail.com>
以下为正文
---------------------------------------------------------------------
sysfs - 用于导出内核对象(kobject)的文件系统
Patrick Mochel <mochel@osdl.org>
Mike Murphy <mamurph@cs.clemson.edu>
修订: 16 August 2011
原始版本: 10 January 2003
sysfs 简介:
~~~~~~~~~~
sysfs 是一个最初基于 ramfs 且位于内存的文件系统。它提供导出内核
数据结构及其属性,以及它们之间的关联到用户空间的方法。
sysfs 始终与 kobject 的底层结构紧密相关。请阅读
Documentation/kobject.txt 文档以获得更多关于 kobject 接口的
信息。
使用 sysfs
~~~~~~~~~~~
只要内核配置中定义了 CONFIG_SYSFS ,sysfs 总是被编译进内核。你可
通过以下命令挂载它:
mount -t sysfs sysfs /sys
创建目录
~~~~~~~~
任何 kobject 在系统中注册,就会有一个目录在 sysfs 中被创建。这个
目录是作为该 kobject 的父对象所在目录的子目录创建的,以准确地传递
内核的对象层次到用户空间。sysfs 中的顶层目录代表着内核对象层次的
共同祖先;例如:某些对象属于某个子系统。
Sysfs 在与其目录关联的 sysfs_dirent 对象中内部保存一个指向实现
目录的 kobject 的指针。以前,这个 kobject 指针被 sysfs 直接用于
kobject 文件打开和关闭的引用计数。而现在的 sysfs 实现中,kobject
引用计数只能通过 sysfs_schedule_callback() 函数直接修改。
属性
~~~~
kobject 的属性可在文件系统中以普通文件的形式导出。Sysfs 为属性定义
了面向文件 I/O 操作的方法,以提供对内核属性的读写。
属性应为 ASCII 码文本文件。以一个文件只存储一个属性值为宜。但一个
文件只包含一个属性值可能影响效率,所以一个包含相同数据类型的属性值
数组也被广泛地接受。
混合类型、表达多行数据以及一些怪异的数据格式会遭到强烈反对。这样做是
很丢脸的,而且其代码会在未通知作者的情况下被重写。
一个简单的属性结构定义如下:
struct attribute {
char * name;
struct module *owner;
umode_t mode;
};
int sysfs_create_file(struct kobject * kobj, const struct attribute * attr);
void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr);
一个单独的属性结构并不包含读写其属性值的方法。子系统最好为增删特定
对象类型的属性定义自己的属性结构体和封装函数。
例如:驱动程序模型定义的 device_attribute 结构体如下:
struct device_attribute {
struct attribute attr;
ssize_t (*show)(struct device *dev, struct device_attribute *attr,
char *buf);
ssize_t (*store)(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count);
};
int device_create_file(struct device *, const struct device_attribute *);
void device_remove_file(struct device *, const struct device_attribute *);
为了定义设备属性,同时定义了一下辅助宏:
#define DEVICE_ATTR(_name, _mode, _show, _store) \
struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)
例如:声明
static DEVICE_ATTR(foo, S_IWUSR | S_IRUGO, show_foo, store_foo);
等同于如下代码:
static struct device_attribute dev_attr_foo = {
.attr = {
.name = "foo",
.mode = S_IWUSR | S_IRUGO,
.show = show_foo,
.store = store_foo,
},
};
子系统特有的回调函数
~~~~~~~~~~~~~~~~~~~
当一个子系统定义一个新的属性类型时,必须实现一系列的 sysfs 操作,
以帮助读写调用实现属性所有者的显示和储存方法。
struct sysfs_ops {
ssize_t (*show)(struct kobject *, struct attribute *, char *);
ssize_t (*store)(struct kobject *, struct attribute *, const char *, size_t);
};
[子系统应已经定义了一个 struct kobj_type 结构体作为这个类型的
描述符,并在此保存 sysfs_ops 的指针。更多的信息参见 kobject 的
文档]
sysfs 会为这个类型调用适当的方法。当一个文件被读写时,这个方法会
将一般的kobject 和 attribute 结构体指针转换为适当的指针类型后
调用相关联的函数。
示例:
#define to_dev(obj) container_of(obj, struct device, kobj)
#define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr)
static ssize_t dev_attr_show(struct kobject *kobj, struct attribute *attr,
char *buf)
{
struct device_attribute *dev_attr = to_dev_attr(attr);
struct device *dev = to_dev(kobj);
ssize_t ret = -EIO;
if (dev_attr->show)
ret = dev_attr->show(dev, dev_attr, buf);
if (ret >= (ssize_t)PAGE_SIZE) {
print_symbol("dev_attr_show: %s returned bad count\n",
(unsigned long)dev_attr->show);
}
return ret;
}
读写属性数据
~~~~~~~~~~~~
在声明属性时,必须指定 show() 或 store() 方法,以实现属性的
读或写。这些方法的类型应该和以下的设备属性定义一样简单。
ssize_t (*show)(struct device *dev, struct device_attribute *attr, char *buf);
ssize_t (*store)(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count);
也就是说,他们应只以一个处理对象、一个属性和一个缓冲指针作为参数。
sysfs 会分配一个大小为 (PAGE_SIZE) 的缓冲区并传递给这个方法。
Sysfs 将会为每次读写操作调用一次这个方法。这使得这些方法在执行时
会出现以下的行为:
- 在读方面(read(2)),show() 方法应该填充整个缓冲区。回想属性
应只导出了一个属性值或是一个同类型属性值的数组,所以这个代价将
不会不太高。
这使得用户空间可以局部地读和任意的向前搜索整个文件。如果用户空间
向后搜索到零或使用‘0’偏移执行一个pread(2)操作,show()方法将
再次被调用,以重新填充缓存。
- 在写方面(write(2)),sysfs 希望在第一次写操作时得到整个缓冲区。
之后 Sysfs 传递整个缓冲区给 store() 方法。
当要写 sysfs 文件时,用户空间进程应首先读取整个文件,修该想要
改变的值,然后回写整个缓冲区。
在读写属性值时,属性方法的执行应操作相同的缓冲区。
注记:
- 写操作导致的 show() 方法重载,会忽略当前文件位置。
- 缓冲区应总是 PAGE_SIZE 大小。对于i386,这个值为4096。
- show() 方法应该返回写入缓冲区的字节数,也就是 snprintf()的
返回值。
- show() 应始终使用 snprintf()。
- store() 应返回缓冲区的已用字节数。如果整个缓存都已填满,只需返回
count 参数。
- show() 或 store() 可以返回错误值。当得到一个非法值,必须返回一个
错误值。
- 一个传递给方法的对象将会通过 sysfs 调用对象内嵌的引用计数固定在
内存中。尽管如此,对象代表的物理实体(如设备)可能已不存在。如有必要,
应该实现一个检测机制。
一个简单的(未经实验证实的)设备属性实现如下:
static ssize_t show_name(struct device *dev, struct device_attribute *attr,
char *buf)
{
return scnprintf(buf, PAGE_SIZE, "%s\n", dev->name);
}
static ssize_t store_name(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
snprintf(dev->name, sizeof(dev->name), "%.*s",
(int)min(count, sizeof(dev->name) - 1), buf);
return count;
}
static DEVICE_ATTR(name, S_IRUGO, show_name, store_name);
(注意:真正的实现不允许用户空间设置设备名。)
顶层目录布局
~~~~~~~~~~~~
sysfs 目录的安排显示了内核数据结构之间的关系。
顶层 sysfs 目录如下:
block/
bus/
class/
dev/
devices/
firmware/
net/
fs/
devices/ 包含了一个设备树的文件系统表示。他直接映射了内部的内核
设备树,反映了设备的层次结构。
bus/ 包含了内核中各种总线类型的平面目录布局。每个总线目录包含两个
子目录:
devices/
drivers/
devices/ 包含了系统中出现的每个设备的符号链接,他们指向 root/ 下的
设备目录。
drivers/ 包含了每个已为特定总线上的设备而挂载的驱动程序的目录(这里
假定驱动没有跨越多个总线类型)。
fs/ 包含了一个为文件系统设立的目录。现在每个想要导出属性的文件系统必须
在 fs/ 下创建自己的层次结构(参见Documentation/filesystems/fuse.txt)。
dev/ 包含两个子目录: char/ 和 block/。在这两个子目录中,有以
<major>:<minor> 格式命名的符号链接。这些符号链接指向 sysfs 目录
中相应的设备。/sys/dev 提供一个通过一个 stat(2) 操作结果,查找
设备 sysfs 接口快捷的方法。
更多有关 driver-model 的特性信息可以在 Documentation/driver-model/
中找到。
TODO: 完成这一节。
当前接口
~~~~~~~~