You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge tag 'driver-core-3.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core
Pull driver core updates from Greg Kroah-Hartman: "Here's the large driver core updates for 3.8-rc1. The biggest thing here is the various __dev* marking removals. This is going to be a pain for the merge with different subsystem trees, I know, but all of the patches included here have been ACKed by their various subsystem maintainers, as they wanted them to go through here. If this is too much of a pain, I can pull all of them out of this tree and just send you one with the other fixes/updates and then, after 3.8-rc1 is out, do the rest of the removals to ensure we catch them all, it's up to you. The merges should all be trivial, and Stephen has been doing them all in linux-next for a few weeks now quite easily. Other than the __dev* marking removals, there's nothing major here, some firmware loading updates and other minor things in the driver core. All of these have (much to Stephen's annoyance), been in linux-next for a while. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>" Fixed up trivial conflicts in drivers/gpio/gpio-{em,stmpe}.c due to gpio update. * tag 'driver-core-3.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: (93 commits) modpost.c: Stop checking __dev* section mismatches init.h: Remove __dev* sections from the kernel acpi: remove use of __devinit PCI: Remove __dev* markings PCI: Always build setup-bus when PCI is enabled PCI: Move pci_uevent into pci-driver.c PCI: Remove CONFIG_HOTPLUG ifdefs unicore32/PCI: Remove CONFIG_HOTPLUG ifdefs sh/PCI: Remove CONFIG_HOTPLUG ifdefs powerpc/PCI: Remove CONFIG_HOTPLUG ifdefs mips/PCI: Remove CONFIG_HOTPLUG ifdefs microblaze/PCI: Remove CONFIG_HOTPLUG ifdefs dma: remove use of __devinit dma: remove use of __devexit_p firewire: remove use of __devinitdata firewire: remove use of __devinit leds: remove use of __devexit leds: remove use of __devinit leds: remove use of __devexit_p mmc: remove use of __devexit ...
This commit is contained in:
@@ -22,12 +22,17 @@
|
||||
- calls request_firmware(&fw_entry, $FIRMWARE, device)
|
||||
- kernel searchs the fimware image with name $FIRMWARE directly
|
||||
in the below search path of root filesystem:
|
||||
User customized search path by module parameter 'path'[1]
|
||||
"/lib/firmware/updates/" UTS_RELEASE,
|
||||
"/lib/firmware/updates",
|
||||
"/lib/firmware/" UTS_RELEASE,
|
||||
"/lib/firmware"
|
||||
- If found, goto 7), else goto 2)
|
||||
|
||||
[1], the 'path' is a string parameter which length should be less
|
||||
than 256, user should pass 'firmware_class.path=$CUSTOMIZED_PATH'
|
||||
if firmware_class is built in kernel(the general situation)
|
||||
|
||||
2), userspace:
|
||||
- /sys/class/firmware/xxx/{loading,data} appear.
|
||||
- hotplug gets called with a firmware identifier in $FIRMWARE
|
||||
@@ -114,3 +119,10 @@
|
||||
on the setup, so I think that the choice on what firmware to make
|
||||
persistent should be left to userspace.
|
||||
|
||||
about firmware cache:
|
||||
--------------------
|
||||
After firmware cache mechanism is introduced during system sleep,
|
||||
request_firmware can be called safely inside device's suspend and
|
||||
resume callback, and callers need't cache the firmware by
|
||||
themselves any more for dealing with firmware loss during system
|
||||
resume.
|
||||
|
||||
@@ -0,0 +1,284 @@
|
||||
Chinese translated version of Documentation/arm/kernel_user_helpers.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: Nicolas Pitre <nicolas.pitre@linaro.org>
|
||||
Dave Martin <dave.martin@linaro.org>
|
||||
Chinese maintainer: Fu Wei <tekkamanninja@gmail.com>
|
||||
---------------------------------------------------------------------
|
||||
Documentation/arm/kernel_user_helpers.txt 的中文翻译
|
||||
|
||||
如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文
|
||||
交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻
|
||||
译存在问题,请联系中文版维护者。
|
||||
英文版维护者: Nicolas Pitre <nicolas.pitre@linaro.org>
|
||||
Dave Martin <dave.martin@linaro.org>
|
||||
中文版维护者: 傅炜 Fu Wei <tekkamanninja@gmail.com>
|
||||
中文版翻译者: 傅炜 Fu Wei <tekkamanninja@gmail.com>
|
||||
中文版校译者: 宋冬生 Dongsheng Song <dongshneg.song@gmail.com>
|
||||
傅炜 Fu Wei <tekkamanninja@gmail.com>
|
||||
|
||||
|
||||
以下为正文
|
||||
---------------------------------------------------------------------
|
||||
内核提供的用户空间辅助代码
|
||||
=========================
|
||||
|
||||
在内核内存空间的固定地址处,有一个由内核提供并可从用户空间访问的代码
|
||||
段。它用于向用户空间提供因在许多 ARM CPU 中未实现的特性和/或指令而需
|
||||
内核提供帮助的某些操作。这些代码直接在用户模式下执行的想法是为了获得
|
||||
最佳效率,但那些与内核计数器联系过于紧密的部分,则被留给了用户库实现。
|
||||
事实上,此代码甚至可能因不同的 CPU 而异,这取决于其可用的指令集或它
|
||||
是否为 SMP 系统。换句话说,内核保留在不作出警告的情况下根据需要更改
|
||||
这些代码的权利。只有本文档描述的入口及其结果是保证稳定的。
|
||||
|
||||
这与完全成熟的 VDSO 实现不同(但两者并不冲突),尽管如此,VDSO 可阻止
|
||||
某些通过常量高效跳转到那些代码段的汇编技巧。且由于那些代码段在返回用户
|
||||
代码前仅使用少量的代码周期,则一个 VDSO 间接远程调用将会在这些简单的
|
||||
操作上增加一个可测量的开销。
|
||||
|
||||
在对那些拥有原生支持的新型处理器进行代码优化时,仅在已为其他操作使用
|
||||
了类似的新增指令,而导致二进制结果已与早期 ARM 处理器不兼容的情况下,
|
||||
用户空间才应绕过这些辅助代码,并在内联函数中实现这些操作(无论是通过
|
||||
编译器在代码中直接放置,还是作为库函数调用实现的一部分)。也就是说,
|
||||
如果你编译的代码不会为了其他目的使用新指令,则不要仅为了避免使用这些
|
||||
内核辅助代码,导致二进制程序无法在早期处理器上运行。
|
||||
|
||||
新的辅助代码可能随着时间的推移而增加,所以新内核中的某些辅助代码在旧
|
||||
内核中可能不存在。因此,程序必须在对任何辅助代码调用假设是安全之前,
|
||||
检测 __kuser_helper_version 的值(见下文)。理想情况下,这种检测应该
|
||||
只在进程启动时执行一次;如果内核版本不支持所需辅助代码,则该进程可尽早
|
||||
中止执行。
|
||||
|
||||
kuser_helper_version
|
||||
--------------------
|
||||
|
||||
位置: 0xffff0ffc
|
||||
|
||||
参考声明:
|
||||
|
||||
extern int32_t __kuser_helper_version;
|
||||
|
||||
定义:
|
||||
|
||||
这个区域包含了当前运行内核实现的辅助代码版本号。用户空间可以通过读
|
||||
取此版本号以确定特定的辅助代码是否存在。
|
||||
|
||||
使用范例:
|
||||
|
||||
#define __kuser_helper_version (*(int32_t *)0xffff0ffc)
|
||||
|
||||
void check_kuser_version(void)
|
||||
{
|
||||
if (__kuser_helper_version < 2) {
|
||||
fprintf(stderr, "can't do atomic operations, kernel too old\n");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
注意:
|
||||
|
||||
用户空间可以假设这个域的值不会在任何单个进程的生存期内改变。也就
|
||||
是说,这个域可以仅在库的初始化阶段或进程启动阶段读取一次。
|
||||
|
||||
kuser_get_tls
|
||||
-------------
|
||||
|
||||
位置: 0xffff0fe0
|
||||
|
||||
参考原型:
|
||||
|
||||
void * __kuser_get_tls(void);
|
||||
|
||||
输入:
|
||||
|
||||
lr = 返回地址
|
||||
|
||||
输出:
|
||||
|
||||
r0 = TLS 值
|
||||
|
||||
被篡改的寄存器:
|
||||
|
||||
无
|
||||
|
||||
定义:
|
||||
|
||||
获取之前通过 __ARM_NR_set_tls 系统调用设置的 TLS 值。
|
||||
|
||||
使用范例:
|
||||
|
||||
typedef void * (__kuser_get_tls_t)(void);
|
||||
#define __kuser_get_tls (*(__kuser_get_tls_t *)0xffff0fe0)
|
||||
|
||||
void foo()
|
||||
{
|
||||
void *tls = __kuser_get_tls();
|
||||
printf("TLS = %p\n", tls);
|
||||
}
|
||||
|
||||
注意:
|
||||
|
||||
- 仅在 __kuser_helper_version >= 1 时,此辅助代码存在
|
||||
(从内核版本 2.6.12 开始)。
|
||||
|
||||
kuser_cmpxchg
|
||||
-------------
|
||||
|
||||
位置: 0xffff0fc0
|
||||
|
||||
参考原型:
|
||||
|
||||
int __kuser_cmpxchg(int32_t oldval, int32_t newval, volatile int32_t *ptr);
|
||||
|
||||
输入:
|
||||
|
||||
r0 = oldval
|
||||
r1 = newval
|
||||
r2 = ptr
|
||||
lr = 返回地址
|
||||
|
||||
输出:
|
||||
|
||||
r0 = 成功代码 (零或非零)
|
||||
C flag = 如果 r0 == 0 则置 1,如果 r0 != 0 则清零。
|
||||
|
||||
被篡改的寄存器:
|
||||
|
||||
r3, ip, flags
|
||||
|
||||
定义:
|
||||
|
||||
仅在 *ptr 为 oldval 时原子保存 newval 于 *ptr 中。
|
||||
如果 *ptr 被改变,则返回值为零,否则为非零值。
|
||||
如果 *ptr 被改变,则 C flag 也会被置 1,以实现调用代码中的汇编
|
||||
优化。
|
||||
|
||||
使用范例:
|
||||
|
||||
typedef int (__kuser_cmpxchg_t)(int oldval, int newval, volatile int *ptr);
|
||||
#define __kuser_cmpxchg (*(__kuser_cmpxchg_t *)0xffff0fc0)
|
||||
|
||||
int atomic_add(volatile int *ptr, int val)
|
||||
{
|
||||
int old, new;
|
||||
|
||||
do {
|
||||
old = *ptr;
|
||||
new = old + val;
|
||||
} while(__kuser_cmpxchg(old, new, ptr));
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
注意:
|
||||
|
||||
- 这个例程已根据需要包含了内存屏障。
|
||||
|
||||
- 仅在 __kuser_helper_version >= 2 时,此辅助代码存在
|
||||
(从内核版本 2.6.12 开始)。
|
||||
|
||||
kuser_memory_barrier
|
||||
--------------------
|
||||
|
||||
位置: 0xffff0fa0
|
||||
|
||||
参考原型:
|
||||
|
||||
void __kuser_memory_barrier(void);
|
||||
|
||||
输入:
|
||||
|
||||
lr = 返回地址
|
||||
|
||||
输出:
|
||||
|
||||
无
|
||||
|
||||
被篡改的寄存器:
|
||||
|
||||
无
|
||||
|
||||
定义:
|
||||
|
||||
应用于任何需要内存屏障以防止手动数据修改带来的一致性问题,以及
|
||||
__kuser_cmpxchg 中。
|
||||
|
||||
使用范例:
|
||||
|
||||
typedef void (__kuser_dmb_t)(void);
|
||||
#define __kuser_dmb (*(__kuser_dmb_t *)0xffff0fa0)
|
||||
|
||||
注意:
|
||||
|
||||
- 仅在 __kuser_helper_version >= 3 时,此辅助代码存在
|
||||
(从内核版本 2.6.15 开始)。
|
||||
|
||||
kuser_cmpxchg64
|
||||
---------------
|
||||
|
||||
位置: 0xffff0f60
|
||||
|
||||
参考原型:
|
||||
|
||||
int __kuser_cmpxchg64(const int64_t *oldval,
|
||||
const int64_t *newval,
|
||||
volatile int64_t *ptr);
|
||||
|
||||
输入:
|
||||
|
||||
r0 = 指向 oldval
|
||||
r1 = 指向 newval
|
||||
r2 = 指向目标值
|
||||
lr = 返回地址
|
||||
|
||||
输出:
|
||||
|
||||
r0 = 成功代码 (零或非零)
|
||||
C flag = 如果 r0 == 0 则置 1,如果 r0 != 0 则清零。
|
||||
|
||||
被篡改的寄存器:
|
||||
|
||||
r3, lr, flags
|
||||
|
||||
定义:
|
||||
|
||||
仅在 *ptr 等于 *oldval 指向的 64 位值时,原子保存 *newval
|
||||
指向的 64 位值于 *ptr 中。如果 *ptr 被改变,则返回值为零,
|
||||
否则为非零值。
|
||||
|
||||
如果 *ptr 被改变,则 C flag 也会被置 1,以实现调用代码中的汇编
|
||||
优化。
|
||||
|
||||
使用范例:
|
||||
|
||||
typedef int (__kuser_cmpxchg64_t)(const int64_t *oldval,
|
||||
const int64_t *newval,
|
||||
volatile int64_t *ptr);
|
||||
#define __kuser_cmpxchg64 (*(__kuser_cmpxchg64_t *)0xffff0f60)
|
||||
|
||||
int64_t atomic_add64(volatile int64_t *ptr, int64_t val)
|
||||
{
|
||||
int64_t old, new;
|
||||
|
||||
do {
|
||||
old = *ptr;
|
||||
new = old + val;
|
||||
} while(__kuser_cmpxchg64(&old, &new, ptr));
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
注意:
|
||||
|
||||
- 这个例程已根据需要包含了内存屏障。
|
||||
|
||||
- 由于这个过程的代码长度(此辅助代码跨越 2 个常规的 kuser “槽”),
|
||||
因此 0xffff0f80 不被作为有效的入口点。
|
||||
|
||||
- 仅在 __kuser_helper_version >= 5 时,此辅助代码存在
|
||||
(从内核版本 3.1 开始)。
|
||||
@@ -47,21 +47,21 @@ AArch64 Linux 内存布局:
|
||||
-----------------------------------------------------------------------
|
||||
0000000000000000 0000007fffffffff 512GB 用户空间
|
||||
|
||||
ffffff8000000000 ffffffbbfffcffff ~240GB vmalloc
|
||||
ffffff8000000000 ffffffbbfffeffff ~240GB vmalloc
|
||||
|
||||
ffffffbbfffd0000 ffffffbcfffdffff 64KB [防护页]
|
||||
|
||||
ffffffbbfffe0000 ffffffbcfffeffff 64KB PCI I/O 空间
|
||||
|
||||
ffffffbbffff0000 ffffffbcffffffff 64KB [防护页]
|
||||
ffffffbbffff0000 ffffffbbffffffff 64KB [防护页]
|
||||
|
||||
ffffffbc00000000 ffffffbdffffffff 8GB vmemmap
|
||||
|
||||
ffffffbe00000000 ffffffbffbffffff ~8GB [防护页,未来用于 vmmemap]
|
||||
ffffffbe00000000 ffffffbffbbfffff ~8GB [防护页,未来用于 vmmemap]
|
||||
|
||||
ffffffbffbe00000 ffffffbffbe0ffff 64KB PCI I/O 空间
|
||||
|
||||
ffffffbbffff0000 ffffffbcffffffff ~2MB [防护页]
|
||||
|
||||
ffffffbffc000000 ffffffbfffffffff 64MB 模块
|
||||
|
||||
ffffffc000000000 ffffffffffffffff 256GB 内存空间
|
||||
ffffffc000000000 ffffffffffffffff 256GB 内核逻辑内存映射
|
||||
|
||||
|
||||
4KB 页大小的转换表查找:
|
||||
|
||||
@@ -1346,8 +1346,6 @@ void __init pcibios_resource_survey(void)
|
||||
pci_assign_unassigned_resources();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HOTPLUG
|
||||
|
||||
/* This is used by the PCI hotplug driver to allocate resource
|
||||
* of newly plugged busses. We can try to consolidate with the
|
||||
* rest of the code later, for now, keep it as-is as our main
|
||||
@@ -1407,8 +1405,6 @@ void pcibios_finish_adding_to_bus(struct pci_bus *bus)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pcibios_finish_adding_to_bus);
|
||||
|
||||
#endif /* CONFIG_HOTPLUG */
|
||||
|
||||
int pcibios_enable_device(struct pci_dev *dev, int mask)
|
||||
{
|
||||
return pci_enable_resources(dev, mask);
|
||||
|
||||
@@ -313,10 +313,8 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HOTPLUG
|
||||
EXPORT_SYMBOL(PCIBIOS_MIN_IO);
|
||||
EXPORT_SYMBOL(PCIBIOS_MIN_MEM);
|
||||
#endif
|
||||
|
||||
int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
|
||||
enum pci_mmap_state mmap_state, int write_combine)
|
||||
|
||||
@@ -1428,8 +1428,6 @@ void __init pcibios_resource_survey(void)
|
||||
ppc_md.pcibios_fixup();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HOTPLUG
|
||||
|
||||
/* This is used by the PCI hotplug driver to allocate resource
|
||||
* of newly plugged busses. We can try to consolidate with the
|
||||
* rest of the code later, for now, keep it as-is as our main
|
||||
@@ -1488,8 +1486,6 @@ void pcibios_finish_adding_to_bus(struct pci_bus *bus)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pcibios_finish_adding_to_bus);
|
||||
|
||||
#endif /* CONFIG_HOTPLUG */
|
||||
|
||||
int pcibios_enable_device(struct pci_dev *dev, int mask)
|
||||
{
|
||||
if (ppc_md.pcibios_enable_device_hook)
|
||||
|
||||
@@ -74,8 +74,6 @@ static int __init pcibios_init(void)
|
||||
|
||||
subsys_initcall(pcibios_init);
|
||||
|
||||
#ifdef CONFIG_HOTPLUG
|
||||
|
||||
int pcibios_unmap_io_space(struct pci_bus *bus)
|
||||
{
|
||||
struct pci_controller *hose;
|
||||
@@ -124,8 +122,6 @@ int pcibios_unmap_io_space(struct pci_bus *bus)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pcibios_unmap_io_space);
|
||||
|
||||
#endif /* CONFIG_HOTPLUG */
|
||||
|
||||
static int __devinit pcibios_map_phb_io_space(struct pci_controller *hose)
|
||||
{
|
||||
struct vm_struct *area;
|
||||
|
||||
@@ -319,7 +319,5 @@ EXPORT_SYMBOL(pci_iounmap);
|
||||
|
||||
#endif /* CONFIG_GENERIC_IOMAP */
|
||||
|
||||
#ifdef CONFIG_HOTPLUG
|
||||
EXPORT_SYMBOL(PCIBIOS_MIN_IO);
|
||||
EXPORT_SYMBOL(PCIBIOS_MIN_MEM);
|
||||
#endif
|
||||
|
||||
@@ -250,9 +250,7 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus)
|
||||
printk(KERN_INFO "PCI: bus%d: Fast back to back transfers %sabled\n",
|
||||
bus->number, (features & PCI_COMMAND_FAST_BACK) ? "en" : "dis");
|
||||
}
|
||||
#ifdef CONFIG_HOTPLUG
|
||||
EXPORT_SYMBOL(pcibios_fixup_bus);
|
||||
#endif
|
||||
|
||||
static int __init pci_common_init(void)
|
||||
{
|
||||
|
||||
@@ -901,7 +901,7 @@ static unsigned long ghes_esource_prealloc_size(
|
||||
return prealloc_size;
|
||||
}
|
||||
|
||||
static int __devinit ghes_probe(struct platform_device *ghes_dev)
|
||||
static int ghes_probe(struct platform_device *ghes_dev)
|
||||
{
|
||||
struct acpi_hest_generic *generic;
|
||||
struct ghes *ghes = NULL;
|
||||
|
||||
+1
-1
@@ -61,7 +61,7 @@ static void acpi_hed_notify(struct acpi_device *device, u32 event)
|
||||
blocking_notifier_call_chain(&acpi_hed_notify_list, 0, NULL);
|
||||
}
|
||||
|
||||
static int __devinit acpi_hed_add(struct acpi_device *device)
|
||||
static int acpi_hed_add(struct acpi_device *device)
|
||||
{
|
||||
/* Only one hardware error device */
|
||||
if (hed_handle)
|
||||
|
||||
@@ -445,7 +445,7 @@ out:
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_pci_osc_control_set);
|
||||
|
||||
static int __devinit acpi_pci_root_add(struct acpi_device *device)
|
||||
static int acpi_pci_root_add(struct acpi_device *device)
|
||||
{
|
||||
unsigned long long segment, bus;
|
||||
acpi_status status;
|
||||
|
||||
@@ -57,7 +57,7 @@ config DEVTMPFS_MOUNT
|
||||
on the rootfs is completely empty.
|
||||
|
||||
config STANDALONE
|
||||
bool "Select only drivers that don't need compile-time external firmware" if EXPERIMENTAL
|
||||
bool "Select only drivers that don't need compile-time external firmware"
|
||||
default y
|
||||
help
|
||||
Select this option if you don't have magic firmware for drivers that
|
||||
@@ -185,7 +185,6 @@ config DMA_SHARED_BUFFER
|
||||
bool
|
||||
default n
|
||||
select ANON_INODES
|
||||
depends on EXPERIMENTAL
|
||||
help
|
||||
This option enables the framework for buffer-sharing between
|
||||
multiple drivers. A buffer is associated with a file using driver
|
||||
@@ -193,8 +192,8 @@ config DMA_SHARED_BUFFER
|
||||
driver.
|
||||
|
||||
config CMA
|
||||
bool "Contiguous Memory Allocator (EXPERIMENTAL)"
|
||||
depends on HAVE_DMA_CONTIGUOUS && HAVE_MEMBLOCK && EXPERIMENTAL
|
||||
bool "Contiguous Memory Allocator"
|
||||
depends on HAVE_DMA_CONTIGUOUS && HAVE_MEMBLOCK
|
||||
select MIGRATION
|
||||
select MEMORY_ISOLATION
|
||||
help
|
||||
|
||||
@@ -158,7 +158,7 @@ attribute_container_add_device(struct device *dev,
|
||||
|
||||
ic = kzalloc(sizeof(*ic), GFP_KERNEL);
|
||||
if (!ic) {
|
||||
dev_printk(KERN_ERR, dev, "failed to allocate class container\n");
|
||||
dev_err(dev, "failed to allocate class container\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -164,8 +164,6 @@ static const struct kset_uevent_ops bus_uevent_ops = {
|
||||
|
||||
static struct kset *bus_kset;
|
||||
|
||||
|
||||
#ifdef CONFIG_HOTPLUG
|
||||
/* Manually detach a device from its associated driver. */
|
||||
static ssize_t driver_unbind(struct device_driver *drv,
|
||||
const char *buf, size_t count)
|
||||
@@ -252,7 +250,6 @@ static ssize_t store_drivers_probe(struct bus_type *bus,
|
||||
return -EINVAL;
|
||||
return count;
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct device *next_device(struct klist_iter *i)
|
||||
{
|
||||
@@ -618,11 +615,6 @@ static void driver_remove_attrs(struct bus_type *bus,
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HOTPLUG
|
||||
/*
|
||||
* Thanks to drivers making their tables __devinit, we can't allow manual
|
||||
* bind and unbind from userspace unless CONFIG_HOTPLUG is enabled.
|
||||
*/
|
||||
static int __must_check add_bind_files(struct device_driver *drv)
|
||||
{
|
||||
int ret;
|
||||
@@ -666,12 +658,6 @@ static void remove_probe_files(struct bus_type *bus)
|
||||
bus_remove_file(bus, &bus_attr_drivers_autoprobe);
|
||||
bus_remove_file(bus, &bus_attr_drivers_probe);
|
||||
}
|
||||
#else
|
||||
static inline int add_bind_files(struct device_driver *drv) { return 0; }
|
||||
static inline void remove_bind_files(struct device_driver *drv) {}
|
||||
static inline int add_probe_files(struct bus_type *bus) { return 0; }
|
||||
static inline void remove_probe_files(struct bus_type *bus) {}
|
||||
#endif
|
||||
|
||||
static ssize_t driver_uevent_store(struct device_driver *drv,
|
||||
const char *buf, size_t count)
|
||||
|
||||
+5
-3
@@ -1399,7 +1399,7 @@ struct root_device {
|
||||
struct module *owner;
|
||||
};
|
||||
|
||||
inline struct root_device *to_root_device(struct device *d)
|
||||
static inline struct root_device *to_root_device(struct device *d)
|
||||
{
|
||||
return container_of(d, struct root_device, dev);
|
||||
}
|
||||
@@ -1840,10 +1840,12 @@ void device_shutdown(void)
|
||||
pm_runtime_barrier(dev);
|
||||
|
||||
if (dev->bus && dev->bus->shutdown) {
|
||||
dev_dbg(dev, "shutdown\n");
|
||||
if (initcall_debug)
|
||||
dev_info(dev, "shutdown\n");
|
||||
dev->bus->shutdown(dev);
|
||||
} else if (dev->driver && dev->driver->shutdown) {
|
||||
dev_dbg(dev, "shutdown\n");
|
||||
if (initcall_debug)
|
||||
dev_info(dev, "shutdown\n");
|
||||
dev->driver->shutdown(dev);
|
||||
}
|
||||
|
||||
|
||||
@@ -50,8 +50,8 @@ static void devres_log(struct device *dev, struct devres_node *node,
|
||||
const char *op)
|
||||
{
|
||||
if (unlikely(log_devres))
|
||||
dev_printk(KERN_ERR, dev, "DEVRES %3s %p %s (%lu bytes)\n",
|
||||
op, node, node->name, (unsigned long)node->size);
|
||||
dev_err(dev, "DEVRES %3s %p %s (%lu bytes)\n",
|
||||
op, node, node->name, (unsigned long)node->size);
|
||||
}
|
||||
#else /* CONFIG_DEBUG_DEVRES */
|
||||
#define set_node_dbginfo(node, n, s) do {} while (0)
|
||||
|
||||
@@ -143,7 +143,7 @@ struct fw_cache_entry {
|
||||
};
|
||||
|
||||
struct firmware_priv {
|
||||
struct timer_list timeout;
|
||||
struct delayed_work timeout_work;
|
||||
bool nowait;
|
||||
struct device dev;
|
||||
struct firmware_buf *buf;
|
||||
@@ -246,7 +246,6 @@ static void __fw_free_buf(struct kref *ref)
|
||||
__func__, buf->fw_id, buf, buf->data,
|
||||
(unsigned int)buf->size);
|
||||
|
||||
spin_lock(&fwc->lock);
|
||||
list_del(&buf->list);
|
||||
spin_unlock(&fwc->lock);
|
||||
|
||||
@@ -263,19 +262,32 @@ static void __fw_free_buf(struct kref *ref)
|
||||
|
||||
static void fw_free_buf(struct firmware_buf *buf)
|
||||
{
|
||||
kref_put(&buf->ref, __fw_free_buf);
|
||||
struct firmware_cache *fwc = buf->fwc;
|
||||
spin_lock(&fwc->lock);
|
||||
if (!kref_put(&buf->ref, __fw_free_buf))
|
||||
spin_unlock(&fwc->lock);
|
||||
}
|
||||
|
||||
/* direct firmware loading support */
|
||||
static const char *fw_path[] = {
|
||||
static char fw_path_para[256];
|
||||
static const char * const fw_path[] = {
|
||||
fw_path_para,
|
||||
"/lib/firmware/updates/" UTS_RELEASE,
|
||||
"/lib/firmware/updates",
|
||||
"/lib/firmware/" UTS_RELEASE,
|
||||
"/lib/firmware"
|
||||
};
|
||||
|
||||
/*
|
||||
* Typical usage is that passing 'firmware_class.path=$CUSTOMIZED_PATH'
|
||||
* from kernel command line because firmware_class is generally built in
|
||||
* kernel instead of module.
|
||||
*/
|
||||
module_param_string(path, fw_path_para, sizeof(fw_path_para), 0644);
|
||||
MODULE_PARM_DESC(path, "customized firmware image search path with a higher priority than default path");
|
||||
|
||||
/* Don't inline this: 'struct kstat' is biggish */
|
||||
static noinline long fw_file_size(struct file *file)
|
||||
static noinline_for_stack long fw_file_size(struct file *file)
|
||||
{
|
||||
struct kstat st;
|
||||
if (vfs_getattr(file->f_path.mnt, file->f_path.dentry, &st))
|
||||
@@ -315,6 +327,11 @@ static bool fw_get_filesystem_firmware(struct firmware_buf *buf)
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(fw_path); i++) {
|
||||
struct file *file;
|
||||
|
||||
/* skip the unset customized path */
|
||||
if (!fw_path[i][0])
|
||||
continue;
|
||||
|
||||
snprintf(path, PATH_MAX, "%s/%s", fw_path[i], buf->fw_id);
|
||||
|
||||
file = filp_open(path, O_RDONLY, 0);
|
||||
@@ -667,11 +684,18 @@ static struct bin_attribute firmware_attr_data = {
|
||||
.write = firmware_data_write,
|
||||
};
|
||||
|
||||
static void firmware_class_timeout(u_long data)
|
||||
static void firmware_class_timeout_work(struct work_struct *work)
|
||||
{
|
||||
struct firmware_priv *fw_priv = (struct firmware_priv *) data;
|
||||
struct firmware_priv *fw_priv = container_of(work,
|
||||
struct firmware_priv, timeout_work.work);
|
||||
|
||||
mutex_lock(&fw_lock);
|
||||
if (test_bit(FW_STATUS_DONE, &(fw_priv->buf->status))) {
|
||||
mutex_unlock(&fw_lock);
|
||||
return;
|
||||
}
|
||||
fw_load_abort(fw_priv);
|
||||
mutex_unlock(&fw_lock);
|
||||
}
|
||||
|
||||
static struct firmware_priv *
|
||||
@@ -690,8 +714,8 @@ fw_create_instance(struct firmware *firmware, const char *fw_name,
|
||||
|
||||
fw_priv->nowait = nowait;
|
||||
fw_priv->fw = firmware;
|
||||
setup_timer(&fw_priv->timeout,
|
||||
firmware_class_timeout, (u_long) fw_priv);
|
||||
INIT_DELAYED_WORK(&fw_priv->timeout_work,
|
||||
firmware_class_timeout_work);
|
||||
|
||||
f_dev = &fw_priv->dev;
|
||||
|
||||
@@ -858,7 +882,9 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,
|
||||
dev_dbg(f_dev->parent, "firmware: direct-loading"
|
||||
" firmware %s\n", buf->fw_id);
|
||||
|
||||
mutex_lock(&fw_lock);
|
||||
set_bit(FW_STATUS_DONE, &buf->status);
|
||||
mutex_unlock(&fw_lock);
|
||||
complete_all(&buf->completion);
|
||||
direct_load = 1;
|
||||
goto handle_fw;
|
||||
@@ -894,15 +920,14 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,
|
||||
dev_set_uevent_suppress(f_dev, false);
|
||||
dev_dbg(f_dev, "firmware: requesting %s\n", buf->fw_id);
|
||||
if (timeout != MAX_SCHEDULE_TIMEOUT)
|
||||
mod_timer(&fw_priv->timeout,
|
||||
round_jiffies_up(jiffies + timeout));
|
||||
schedule_delayed_work(&fw_priv->timeout_work, timeout);
|
||||
|
||||
kobject_uevent(&fw_priv->dev.kobj, KOBJ_ADD);
|
||||
}
|
||||
|
||||
wait_for_completion(&buf->completion);
|
||||
|
||||
del_timer_sync(&fw_priv->timeout);
|
||||
cancel_delayed_work_sync(&fw_priv->timeout_work);
|
||||
|
||||
handle_fw:
|
||||
mutex_lock(&fw_lock);
|
||||
@@ -963,6 +988,9 @@ err_put_dev:
|
||||
* firmware image for this or any other device.
|
||||
*
|
||||
* Caller must hold the reference count of @device.
|
||||
*
|
||||
* The function can be called safely inside device's suspend and
|
||||
* resume callback.
|
||||
**/
|
||||
int
|
||||
request_firmware(const struct firmware **firmware_p, const char *name,
|
||||
|
||||
@@ -45,7 +45,7 @@ EXPORT_SYMBOL_GPL(platform_bus);
|
||||
* be setup before the platform_notifier is called. So if a user needs to
|
||||
* manipulate any relevant information in the pdev_archdata they can do:
|
||||
*
|
||||
* platform_devic_alloc()
|
||||
* platform_device_alloc()
|
||||
* ... manipulate ...
|
||||
* platform_device_add()
|
||||
*
|
||||
@@ -123,7 +123,7 @@ struct resource *platform_get_resource_byname(struct platform_device *dev,
|
||||
EXPORT_SYMBOL_GPL(platform_get_resource_byname);
|
||||
|
||||
/**
|
||||
* platform_get_irq - get an IRQ for a device
|
||||
* platform_get_irq_byname - get an IRQ for a device by name
|
||||
* @dev: platform device
|
||||
* @name: IRQ name
|
||||
*/
|
||||
|
||||
@@ -555,7 +555,7 @@ static struct tpm_vendor_specific tpm_tis_i2c = {
|
||||
.miscdev.fops = &tis_ops,
|
||||
};
|
||||
|
||||
static int __devinit tpm_tis_i2c_init(struct device *dev)
|
||||
static int tpm_tis_i2c_init(struct device *dev)
|
||||
{
|
||||
u32 vendor;
|
||||
int rc = 0;
|
||||
@@ -632,7 +632,7 @@ static const struct i2c_device_id tpm_tis_i2c_table[] = {
|
||||
MODULE_DEVICE_TABLE(i2c, tpm_tis_i2c_table);
|
||||
static SIMPLE_DEV_PM_OPS(tpm_tis_i2c_ops, tpm_pm_suspend, tpm_pm_resume);
|
||||
|
||||
static int __devinit tpm_tis_i2c_probe(struct i2c_client *client,
|
||||
static int tpm_tis_i2c_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
int rc;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user