Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

Pull driver core fixes from Greg Kroah-Hartman:
"Here are a number of firmware core fixes for 3.7, and some other minor
fixes. And some documentation updates thrown in for good measure.

All have been in the linux-next tree for a while.

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

* tag 'driver-core-3.7-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core:
Documentation:Chinese translation of Documentation/arm64/memory.txt
Documentation:Chinese translation of Documentation/arm64/booting.txt
Documentation:Chinese translation of Documentation/IRQ.txt
firmware loader: document kernel direct loading
sysfs: sysfs_pathname/sysfs_add_one: Use strlcat() instead of strcat()
dynamic_debug: Remove unnecessary __used
firmware loader: sync firmware cache by async_synchronize_full_domain
firmware loader: let direct loading back on 'firmware_buf'
firmware loader: fix one reqeust_firmware race
firmware loader: cancel uncache work before caching firmware

+464 -132
+16 -8
Documentation/firmware_class/README
··· 18 18 High level behavior (mixed): 19 19 ============================ 20 20 21 - kernel(driver): calls request_firmware(&fw_entry, $FIRMWARE, device) 21 + 1), kernel(driver): 22 + - calls request_firmware(&fw_entry, $FIRMWARE, device) 23 + - kernel searchs the fimware image with name $FIRMWARE directly 24 + in the below search path of root filesystem: 25 + "/lib/firmware/updates/" UTS_RELEASE, 26 + "/lib/firmware/updates", 27 + "/lib/firmware/" UTS_RELEASE, 28 + "/lib/firmware" 29 + - If found, goto 7), else goto 2) 22 30 23 - userspace: 31 + 2), userspace: 24 32 - /sys/class/firmware/xxx/{loading,data} appear. 25 33 - hotplug gets called with a firmware identifier in $FIRMWARE 26 34 and the usual hotplug environment. 27 35 - hotplug: echo 1 > /sys/class/firmware/xxx/loading 28 36 29 - kernel: Discard any previous partial load. 37 + 3), kernel: Discard any previous partial load. 30 38 31 - userspace: 39 + 4), userspace: 32 40 - hotplug: cat appropriate_firmware_image > \ 33 41 /sys/class/firmware/xxx/data 34 42 35 - kernel: grows a buffer in PAGE_SIZE increments to hold the image as it 43 + 5), kernel: grows a buffer in PAGE_SIZE increments to hold the image as it 36 44 comes in. 37 45 38 - userspace: 46 + 6), userspace: 39 47 - hotplug: echo 0 > /sys/class/firmware/xxx/loading 40 48 41 - kernel: request_firmware() returns and the driver has the firmware 49 + 7), kernel: request_firmware() returns and the driver has the firmware 42 50 image in fw_entry->{data,size}. If something went wrong 43 51 request_firmware() returns non-zero and fw_entry is set to 44 52 NULL. 45 53 46 - kernel(driver): Driver code calls release_firmware(fw_entry) releasing 54 + 8), kernel(driver): Driver code calls release_firmware(fw_entry) releasing 47 55 the firmware image and any related resource. 48 56 49 57 High level behavior (driver code):
+39
Documentation/zh_CN/IRQ.txt
··· 1 + Chinese translated version of Documentation/IRQ.txt 2 + 3 + If you have any comment or update to the content, please contact the 4 + original document maintainer directly. However, if you have a problem 5 + communicating in English you can also ask the Chinese maintainer for 6 + help. Contact the Chinese maintainer if this translation is outdated 7 + or if there is a problem with the translation. 8 + 9 + Maintainer: Eric W. Biederman <ebiederman@xmission.com> 10 + Chinese maintainer: Fu Wei <tekkamanninja@gmail.com> 11 + --------------------------------------------------------------------- 12 + Documentation/IRQ.txt 的中文翻译 13 + 14 + 如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文 15 + 交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻 16 + 译存在问题,请联系中文版维护者。 17 + 英文版维护者: Eric W. Biederman <ebiederman@xmission.com> 18 + 中文版维护者: 傅炜 Fu Wei <tekkamanninja@gmail.com> 19 + 中文版翻译者: 傅炜 Fu Wei <tekkamanninja@gmail.com> 20 + 中文版校译者: 傅炜 Fu Wei <tekkamanninja@gmail.com> 21 + 22 + 23 + 以下为正文 24 + --------------------------------------------------------------------- 25 + 何为 IRQ? 26 + 27 + 一个 IRQ 是来自某个设备的一个中断请求。目前,它们可以来自一个硬件引脚, 28 + 或来自一个数据包。多个设备可能连接到同个硬件引脚,从而共享一个 IRQ。 29 + 30 + 一个 IRQ 编号是用于告知硬件中断源的内核标识。通常情况下,这是一个 31 + 全局 irq_desc 数组的索引,但是除了在 linux/interrupt.h 中的实现, 32 + 具体的细节是体系结构特定的。 33 + 34 + 一个 IRQ 编号是设备上某个可能的中断源的枚举。通常情况下,枚举的编号是 35 + 该引脚在系统内中断控制器的所有输入引脚中的编号。对于 ISA 总线中的情况, 36 + 枚举的是在两个 i8259 中断控制器中 16 个输入引脚。 37 + 38 + 架构可以对 IRQ 编号指定额外的含义,在硬件涉及任何手工配置的情况下, 39 + 是被提倡的。ISA 的 IRQ 是一个分配这类额外含义的典型例子。
+156
Documentation/zh_CN/arm64/booting.txt
··· 1 + Chinese translated version of Documentation/arm64/booting.txt 2 + 3 + If you have any comment or update to the content, please contact the 4 + original document maintainer directly. However, if you have a problem 5 + communicating in English you can also ask the Chinese maintainer for 6 + help. Contact the Chinese maintainer if this translation is outdated 7 + or if there is a problem with the translation. 8 + 9 + Maintainer: Will Deacon <will.deacon@arm.com> 10 + Chinese maintainer: Fu Wei <tekkamanninja@gmail.com> 11 + --------------------------------------------------------------------- 12 + Documentation/arm64/booting.txt 的中文翻译 13 + 14 + 如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文 15 + 交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻 16 + 译存在问题,请联系中文版维护者。 17 + 18 + 英文版维护者: Will Deacon <will.deacon@arm.com> 19 + 中文版维护者: 傅炜 Fu Wei <tekkamanninja@gmail.com> 20 + 中文版翻译者: 傅炜 Fu Wei <tekkamanninja@gmail.com> 21 + 中文版校译者: 傅炜 Fu Wei <tekkamanninja@gmail.com> 22 + 23 + 以下为正文 24 + --------------------------------------------------------------------- 25 + 启动 AArch64 Linux 26 + ================== 27 + 28 + 作者: Will Deacon <will.deacon@arm.com> 29 + 日期: 2012 年 09 月 07 日 30 + 31 + 本文档基于 Russell King 的 ARM 启动文档,且适用于所有公开发布的 32 + AArch64 Linux 内核代码。 33 + 34 + AArch64 异常模型由多个异常级别(EL0 - EL3)组成,对于 EL0 和 EL1 35 + 异常级有对应的安全和非安全模式。EL2 是系统管理级,且仅存在于 36 + 非安全模式下。EL3 是最高特权级,且仅存在于安全模式下。 37 + 38 + 基于本文档的目的,我们将简单地使用‘引导装载程序’(‘boot loader’) 39 + 这个术语来定义在将控制权交给 Linux 内核前 CPU 上执行的所有软件。 40 + 这可能包含安全监控和系统管理代码,或者它可能只是一些用于准备最小启动 41 + 环境的指令。 42 + 43 + 基本上,引导装载程序(至少)应实现以下操作: 44 + 45 + 1、设置和初始化 RAM 46 + 2、设置设备树数据 47 + 3、解压内核映像 48 + 4、调用内核映像 49 + 50 + 51 + 1、设置和初始化 RAM 52 + ----------------- 53 + 54 + 必要性: 强制 55 + 56 + 引导装载程序应该找到并初始化系统中所有内核用于保持系统变量数据的 RAM。 57 + 这个操作的执行是设备依赖的。(它可能使用内部算法来自动定位和计算所有 58 + RAM,或可能使用对这个设备已知的 RAM 信息,还可能使用任何引导装载程序 59 + 设计者想到的匹配方法。) 60 + 61 + 62 + 2、设置设备树数据 63 + --------------- 64 + 65 + 必要性: 强制 66 + 67 + 设备树数据块(dtb)大小必须不大于 2 MB,且位于从内核映像起始算起第一个 68 + 512MB 内的 2MB 边界上。这使得内核可以通过初始页表中的单个节描述符来 69 + 映射此数据块。 70 + 71 + 72 + 3、解压内核映像 73 + ------------- 74 + 75 + 必要性: 可选 76 + 77 + AArch64 内核当前没有提供自解压代码,因此如果使用了压缩内核映像文件 78 + (比如 Image.gz),则需要通过引导装载程序(使用 gzip 等)来进行解压。 79 + 若引导装载程序没有实现这个需求,就要使用非压缩内核映像文件。 80 + 81 + 82 + 4、调用内核映像 83 + ------------- 84 + 85 + 必要性: 强制 86 + 87 + 已解压的内核映像包含一个 32 字节的头,内容如下: 88 + 89 + u32 magic = 0x14000008; /* 跳转到 stext, 小端 */ 90 + u32 res0 = 0; /* 保留 */ 91 + u64 text_offset; /* 映像装载偏移 */ 92 + u64 res1 = 0; /* 保留 */ 93 + u64 res2 = 0; /* 保留 */ 94 + 95 + 映像必须位于系统 RAM 起始处的特定偏移(当前是 0x80000)。系统 RAM 96 + 的起始地址必须是以 2MB 对齐的。 97 + 98 + 在跳转入内核前,必须符合以下状态: 99 + 100 + - 停止所有 DMA 设备,这样内存数据就不会因为虚假网络包或磁盘数据而 101 + 被破坏。这可能可以节省你许多的调试时间。 102 + 103 + - 主 CPU 通用寄存器设置 104 + x0 = 系统 RAM 中设备树数据块(dtb)的物理地址。 105 + x1 = 0 (保留,将来可能使用) 106 + x2 = 0 (保留,将来可能使用) 107 + x3 = 0 (保留,将来可能使用) 108 + 109 + - CPU 模式 110 + 所有形式的中断必须在 PSTATE.DAIF 中被屏蔽(Debug、SError、IRQ 111 + 和 FIQ)。 112 + CPU 必须处于 EL2(推荐,可访问虚拟化扩展)或非安全 EL1 模式下。 113 + 114 + - 高速缓存、MMU 115 + MMU 必须关闭。 116 + 指令缓存开启或关闭都可以。 117 + 数据缓存必须关闭且无效。 118 + 外部高速缓存(如果存在)必须配置并禁用。 119 + 120 + - 架构计时器 121 + CNTFRQ 必须设定为计时器的频率。 122 + 如果在 EL1 模式下进入内核,则 CNTHCTL_EL2 中的 EL1PCTEN (bit 0) 123 + 必须置位。 124 + 125 + - 一致性 126 + 通过内核启动的所有 CPU 在内核入口地址上必须处于相同的一致性域中。 127 + 这可能要根据具体实现来定义初始化过程,以使能每个CPU上对维护操作的 128 + 接收。 129 + 130 + - 系统寄存器 131 + 在进入内核映像的异常级中,所有构架中可写的系统寄存器必须通过软件 132 + 在一个更高的异常级别下初始化,以防止在 未知 状态下运行。 133 + 134 + 引导装载程序必须在每个 CPU 处于以下状态时跳入内核入口: 135 + 136 + - 主 CPU 必须直接跳入内核映像的第一条指令。通过此 CPU 传递的设备树 137 + 数据块必须在每个 CPU 节点中包含以下内容: 138 + 139 + 1、‘enable-method’属性。目前,此字段支持的值仅为字符串“spin-table”。 140 + 141 + 2、‘cpu-release-addr’标识一个 64-bit、初始化为零的内存位置。 142 + 143 + 引导装载程序必须生成这些设备树属性,并在跳入内核入口之前将其插入 144 + 数据块。 145 + 146 + - 任何辅助 CPU 必须在内存保留区(通过设备树中的 /memreserve/ 域传递 147 + 给内核)中自旋于内核之外,轮询它们的 cpu-release-addr 位置(必须 148 + 包含在保留区中)。可通过插入 wfe 指令来降低忙循环开销,而主 CPU 将 149 + 发出 sev 指令。当对 cpu-release-addr 所指位置的读取操作返回非零值 150 + 时,CPU 必须直接跳入此值所指向的地址。 151 + 152 + - 辅助 CPU 通用寄存器设置 153 + x0 = 0 (保留,将来可能使用) 154 + x1 = 0 (保留,将来可能使用) 155 + x2 = 0 (保留,将来可能使用) 156 + x3 = 0 (保留,将来可能使用)
+93
Documentation/zh_CN/arm64/memory.txt
··· 1 + Chinese translated version of Documentation/arm64/memory.txt 2 + 3 + If you have any comment or update to the content, please contact the 4 + original document maintainer directly. However, if you have a problem 5 + communicating in English you can also ask the Chinese maintainer for 6 + help. Contact the Chinese maintainer if this translation is outdated 7 + or if there is a problem with the translation. 8 + 9 + Maintainer: Catalin Marinas <catalin.marinas@arm.com> 10 + Chinese maintainer: Fu Wei <tekkamanninja@gmail.com> 11 + --------------------------------------------------------------------- 12 + Documentation/arm64/memory.txt 的中文翻译 13 + 14 + 如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文 15 + 交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻 16 + 译存在问题,请联系中文版维护者。 17 + 18 + 英文版维护者: Catalin Marinas <catalin.marinas@arm.com> 19 + 中文版维护者: 傅炜 Fu Wei <tekkamanninja@gmail.com> 20 + 中文版翻译者: 傅炜 Fu Wei <tekkamanninja@gmail.com> 21 + 中文版校译者: 傅炜 Fu Wei <tekkamanninja@gmail.com> 22 + 23 + 以下为正文 24 + --------------------------------------------------------------------- 25 + Linux 在 AArch64 中的内存布局 26 + =========================== 27 + 28 + 作者: Catalin Marinas <catalin.marinas@arm.com> 29 + 日期: 2012 年 02 月 20 日 30 + 31 + 本文档描述 AArch64 Linux 内核所使用的虚拟内存布局。此构架可以实现 32 + 页大小为 4KB 的 4 级转换表和页大小为 64KB 的 3 级转换表。 33 + 34 + AArch64 Linux 使用页大小为 4KB 的 3 级转换表配置,对于用户和内核 35 + 都有 39-bit (512GB) 的虚拟地址空间。对于页大小为 64KB的配置,仅 36 + 使用 2 级转换表,但内存布局相同。 37 + 38 + 用户地址空间的 63:39 位为 0,而内核地址空间的相应位为 1。TTBRx 的 39 + 选择由虚拟地址的 63 位给出。swapper_pg_dir 仅包含内核(全局)映射, 40 + 而用户 pgd 仅包含用户(非全局)映射。swapper_pgd_dir 地址被写入 41 + TTBR1 中,且从不写入 TTBR0。 42 + 43 + 44 + AArch64 Linux 内存布局: 45 + 46 + 起始地址 结束地址 大小 用途 47 + ----------------------------------------------------------------------- 48 + 0000000000000000 0000007fffffffff 512GB 用户空间 49 + 50 + ffffff8000000000 ffffffbbfffcffff ~240GB vmalloc 51 + 52 + ffffffbbfffd0000 ffffffbcfffdffff 64KB [防护页] 53 + 54 + ffffffbbfffe0000 ffffffbcfffeffff 64KB PCI I/O 空间 55 + 56 + ffffffbbffff0000 ffffffbcffffffff 64KB [防护页] 57 + 58 + ffffffbc00000000 ffffffbdffffffff 8GB vmemmap 59 + 60 + ffffffbe00000000 ffffffbffbffffff ~8GB [防护页,未来用于 vmmemap] 61 + 62 + ffffffbffc000000 ffffffbfffffffff 64MB 模块 63 + 64 + ffffffc000000000 ffffffffffffffff 256GB 内存空间 65 + 66 + 67 + 4KB 页大小的转换表查找: 68 + 69 + +--------+--------+--------+--------+--------+--------+--------+--------+ 70 + |63 56|55 48|47 40|39 32|31 24|23 16|15 8|7 0| 71 + +--------+--------+--------+--------+--------+--------+--------+--------+ 72 + | | | | | | 73 + | | | | | v 74 + | | | | | [11:0] 页内偏移 75 + | | | | +-> [20:12] L3 索引 76 + | | | +-----------> [29:21] L2 索引 77 + | | +---------------------> [38:30] L1 索引 78 + | +-------------------------------> [47:39] L0 索引 (未使用) 79 + +-------------------------------------------------> [63] TTBR0/1 80 + 81 + 82 + 64KB 页大小的转换表查找: 83 + 84 + +--------+--------+--------+--------+--------+--------+--------+--------+ 85 + |63 56|55 48|47 40|39 32|31 24|23 16|15 8|7 0| 86 + +--------+--------+--------+--------+--------+--------+--------+--------+ 87 + | | | | | 88 + | | | | v 89 + | | | | [15:0] 页内偏移 90 + | | | +----------> [28:16] L3 索引 91 + | | +--------------------------> [41:29] L2 索引 (仅使用 38:29 ) 92 + | +-------------------------------> [47:42] L1 索引 (未使用) 93 + +-------------------------------------------------> [63] TTBR0/1
+151 -115
drivers/base/firmware_class.c
··· 36 36 MODULE_DESCRIPTION("Multi purpose firmware loading support"); 37 37 MODULE_LICENSE("GPL"); 38 38 39 - static const char *fw_path[] = { 40 - "/lib/firmware/updates/" UTS_RELEASE, 41 - "/lib/firmware/updates", 42 - "/lib/firmware/" UTS_RELEASE, 43 - "/lib/firmware" 44 - }; 45 - 46 - /* Don't inline this: 'struct kstat' is biggish */ 47 - static noinline long fw_file_size(struct file *file) 48 - { 49 - struct kstat st; 50 - if (vfs_getattr(file->f_path.mnt, file->f_path.dentry, &st)) 51 - return -1; 52 - if (!S_ISREG(st.mode)) 53 - return -1; 54 - if (st.size != (long)st.size) 55 - return -1; 56 - return st.size; 57 - } 58 - 59 - static bool fw_read_file_contents(struct file *file, struct firmware *fw) 60 - { 61 - long size; 62 - char *buf; 63 - 64 - size = fw_file_size(file); 65 - if (size < 0) 66 - return false; 67 - buf = vmalloc(size); 68 - if (!buf) 69 - return false; 70 - if (kernel_read(file, 0, buf, size) != size) { 71 - vfree(buf); 72 - return false; 73 - } 74 - fw->data = buf; 75 - fw->size = size; 76 - return true; 77 - } 78 - 79 - static bool fw_get_filesystem_firmware(struct firmware *fw, const char *name) 80 - { 81 - int i; 82 - bool success = false; 83 - char *path = __getname(); 84 - 85 - for (i = 0; i < ARRAY_SIZE(fw_path); i++) { 86 - struct file *file; 87 - snprintf(path, PATH_MAX, "%s/%s", fw_path[i], name); 88 - 89 - file = filp_open(path, O_RDONLY, 0); 90 - if (IS_ERR(file)) 91 - continue; 92 - success = fw_read_file_contents(file, fw); 93 - fput(file); 94 - if (success) 95 - break; 96 - } 97 - __putname(path); 98 - return success; 99 - } 100 - 101 39 /* Builtin firmware support */ 102 40 103 41 #ifdef CONFIG_FW_LOADER ··· 88 150 FW_STATUS_ABORT, 89 151 }; 90 152 153 + enum fw_buf_fmt { 154 + VMALLOC_BUF, /* used in direct loading */ 155 + PAGE_BUF, /* used in loading via userspace */ 156 + }; 157 + 91 158 static int loading_timeout = 60; /* In seconds */ 92 159 93 160 static inline long firmware_loading_timeout(void) ··· 116 173 spinlock_t name_lock; 117 174 struct list_head fw_names; 118 175 119 - wait_queue_head_t wait_queue; 120 - int cnt; 121 176 struct delayed_work work; 122 177 123 178 struct notifier_block pm_notify; ··· 128 187 struct completion completion; 129 188 struct firmware_cache *fwc; 130 189 unsigned long status; 190 + enum fw_buf_fmt fmt; 131 191 void *data; 132 192 size_t size; 133 193 struct page **pages; ··· 182 240 strcpy(buf->fw_id, fw_name); 183 241 buf->fwc = fwc; 184 242 init_completion(&buf->completion); 243 + buf->fmt = VMALLOC_BUF; 185 244 186 245 pr_debug("%s: fw-%s buf=%p\n", __func__, fw_name, buf); 187 246 ··· 250 307 list_del(&buf->list); 251 308 spin_unlock(&fwc->lock); 252 309 253 - vunmap(buf->data); 254 - for (i = 0; i < buf->nr_pages; i++) 255 - __free_page(buf->pages[i]); 256 - kfree(buf->pages); 310 + 311 + if (buf->fmt == PAGE_BUF) { 312 + vunmap(buf->data); 313 + for (i = 0; i < buf->nr_pages; i++) 314 + __free_page(buf->pages[i]); 315 + kfree(buf->pages); 316 + } else 317 + vfree(buf->data); 257 318 kfree(buf); 258 319 } 259 320 260 321 static void fw_free_buf(struct firmware_buf *buf) 261 322 { 262 323 kref_put(&buf->ref, __fw_free_buf); 324 + } 325 + 326 + /* direct firmware loading support */ 327 + static const char *fw_path[] = { 328 + "/lib/firmware/updates/" UTS_RELEASE, 329 + "/lib/firmware/updates", 330 + "/lib/firmware/" UTS_RELEASE, 331 + "/lib/firmware" 332 + }; 333 + 334 + /* Don't inline this: 'struct kstat' is biggish */ 335 + static noinline long fw_file_size(struct file *file) 336 + { 337 + struct kstat st; 338 + if (vfs_getattr(file->f_path.mnt, file->f_path.dentry, &st)) 339 + return -1; 340 + if (!S_ISREG(st.mode)) 341 + return -1; 342 + if (st.size != (long)st.size) 343 + return -1; 344 + return st.size; 345 + } 346 + 347 + static bool fw_read_file_contents(struct file *file, struct firmware_buf *fw_buf) 348 + { 349 + long size; 350 + char *buf; 351 + 352 + size = fw_file_size(file); 353 + if (size < 0) 354 + return false; 355 + buf = vmalloc(size); 356 + if (!buf) 357 + return false; 358 + if (kernel_read(file, 0, buf, size) != size) { 359 + vfree(buf); 360 + return false; 361 + } 362 + fw_buf->data = buf; 363 + fw_buf->size = size; 364 + return true; 365 + } 366 + 367 + static bool fw_get_filesystem_firmware(struct firmware_buf *buf) 368 + { 369 + int i; 370 + bool success = false; 371 + char *path = __getname(); 372 + 373 + for (i = 0; i < ARRAY_SIZE(fw_path); i++) { 374 + struct file *file; 375 + snprintf(path, PATH_MAX, "%s/%s", fw_path[i], buf->fw_id); 376 + 377 + file = filp_open(path, O_RDONLY, 0); 378 + if (IS_ERR(file)) 379 + continue; 380 + success = fw_read_file_contents(file, buf); 381 + fput(file); 382 + if (success) 383 + break; 384 + } 385 + __putname(path); 386 + return success; 263 387 } 264 388 265 389 static struct firmware_priv *to_firmware_priv(struct device *dev) ··· 433 423 #ifndef PAGE_KERNEL_RO 434 424 #define PAGE_KERNEL_RO PAGE_KERNEL 435 425 #endif 426 + 427 + /* one pages buffer should be mapped/unmapped only once */ 428 + static int fw_map_pages_buf(struct firmware_buf *buf) 429 + { 430 + if (buf->fmt != PAGE_BUF) 431 + return 0; 432 + 433 + if (buf->data) 434 + vunmap(buf->data); 435 + buf->data = vmap(buf->pages, buf->nr_pages, 0, PAGE_KERNEL_RO); 436 + if (!buf->data) 437 + return -ENOMEM; 438 + return 0; 439 + } 440 + 436 441 /** 437 442 * firmware_loading_store - set value in the 'loading' control file 438 443 * @dev: device pointer ··· 492 467 if (test_bit(FW_STATUS_LOADING, &fw_buf->status)) { 493 468 set_bit(FW_STATUS_DONE, &fw_buf->status); 494 469 clear_bit(FW_STATUS_LOADING, &fw_buf->status); 470 + 471 + /* 472 + * Several loading requests may be pending on 473 + * one same firmware buf, so let all requests 474 + * see the mapped 'buf->data' once the loading 475 + * is completed. 476 + * */ 477 + fw_map_pages_buf(fw_buf); 495 478 complete_all(&fw_buf->completion); 496 479 break; 497 480 } ··· 703 670 return fw_priv; 704 671 } 705 672 706 - /* one pages buffer is mapped/unmapped only once */ 707 - static int fw_map_pages_buf(struct firmware_buf *buf) 708 - { 709 - buf->data = vmap(buf->pages, buf->nr_pages, 0, PAGE_KERNEL_RO); 710 - if (!buf->data) 711 - return -ENOMEM; 712 - return 0; 713 - } 714 - 715 673 /* store the pages buffer info firmware from buf */ 716 674 static void fw_set_page_data(struct firmware_buf *buf, struct firmware *fw) 717 675 { ··· 802 778 return NULL; 803 779 } 804 780 805 - if (fw_get_filesystem_firmware(firmware, name)) { 806 - dev_dbg(device, "firmware: direct-loading firmware %s\n", name); 807 - return NULL; 808 - } 809 - 810 781 ret = fw_lookup_and_allocate_buf(name, &fw_cache, &buf); 811 782 if (!ret) 812 783 fw_priv = fw_create_instance(firmware, name, device, ··· 851 832 struct device *f_dev = &fw_priv->dev; 852 833 struct firmware_buf *buf = fw_priv->buf; 853 834 struct firmware_cache *fwc = &fw_cache; 835 + int direct_load = 0; 836 + 837 + /* try direct loading from fs first */ 838 + if (fw_get_filesystem_firmware(buf)) { 839 + dev_dbg(f_dev->parent, "firmware: direct-loading" 840 + " firmware %s\n", buf->fw_id); 841 + 842 + set_bit(FW_STATUS_DONE, &buf->status); 843 + complete_all(&buf->completion); 844 + direct_load = 1; 845 + goto handle_fw; 846 + } 847 + 848 + /* fall back on userspace loading */ 849 + buf->fmt = PAGE_BUF; 854 850 855 851 dev_set_uevent_suppress(f_dev, true); 856 852 ··· 904 870 905 871 del_timer_sync(&fw_priv->timeout); 906 872 873 + handle_fw: 907 874 mutex_lock(&fw_lock); 908 875 if (!buf->size || test_bit(FW_STATUS_ABORT, &buf->status)) 909 876 retval = -ENOENT; ··· 918 883 */ 919 884 if (!retval && f_dev->parent) 920 885 fw_add_devm_name(f_dev->parent, buf->fw_id); 921 - 922 - if (!retval) 923 - retval = fw_map_pages_buf(buf); 924 886 925 887 /* 926 888 * After caching firmware image is started, let it piggyback ··· 933 901 934 902 fw_priv->buf = NULL; 935 903 mutex_unlock(&fw_lock); 904 + 905 + if (direct_load) 906 + goto err_put_dev; 936 907 937 908 device_remove_file(f_dev, &dev_attr_loading); 938 909 err_del_bin_attr: ··· 1164 1129 } 1165 1130 1166 1131 #ifdef CONFIG_PM_SLEEP 1132 + static ASYNC_DOMAIN_EXCLUSIVE(fw_cache_domain); 1133 + 1167 1134 static struct fw_cache_entry *alloc_fw_cache_entry(const char *name) 1168 1135 { 1169 1136 struct fw_cache_entry *fce; ··· 1179 1142 return fce; 1180 1143 } 1181 1144 1145 + static int __fw_entry_found(const char *name) 1146 + { 1147 + struct firmware_cache *fwc = &fw_cache; 1148 + struct fw_cache_entry *fce; 1149 + 1150 + list_for_each_entry(fce, &fwc->fw_names, list) { 1151 + if (!strcmp(fce->name, name)) 1152 + return 1; 1153 + } 1154 + return 0; 1155 + } 1156 + 1182 1157 static int fw_cache_piggyback_on_request(const char *name) 1183 1158 { 1184 1159 struct firmware_cache *fwc = &fw_cache; ··· 1198 1149 int ret = 0; 1199 1150 1200 1151 spin_lock(&fwc->name_lock); 1201 - list_for_each_entry(fce, &fwc->fw_names, list) { 1202 - if (!strcmp(fce->name, name)) 1203 - goto found; 1204 - } 1152 + if (__fw_entry_found(name)) 1153 + goto found; 1205 1154 1206 1155 fce = alloc_fw_cache_entry(name); 1207 1156 if (fce) { ··· 1232 1185 1233 1186 free_fw_cache_entry(fce); 1234 1187 } 1235 - 1236 - spin_lock(&fwc->name_lock); 1237 - fwc->cnt--; 1238 - spin_unlock(&fwc->name_lock); 1239 - 1240 - wake_up(&fwc->wait_queue); 1241 1188 } 1242 1189 1243 1190 /* called with dev->devres_lock held */ ··· 1270 1229 list_del(&fce->list); 1271 1230 1272 1231 spin_lock(&fwc->name_lock); 1273 - fwc->cnt++; 1274 - list_add(&fce->list, &fwc->fw_names); 1232 + /* only one cache entry for one firmware */ 1233 + if (!__fw_entry_found(fce->name)) { 1234 + list_add(&fce->list, &fwc->fw_names); 1235 + } else { 1236 + free_fw_cache_entry(fce); 1237 + fce = NULL; 1238 + } 1275 1239 spin_unlock(&fwc->name_lock); 1276 1240 1277 - async_schedule(__async_dev_cache_fw_image, (void *)fce); 1241 + if (fce) 1242 + async_schedule_domain(__async_dev_cache_fw_image, 1243 + (void *)fce, 1244 + &fw_cache_domain); 1278 1245 } 1279 1246 } 1280 1247 ··· 1324 1275 1325 1276 pr_debug("%s\n", __func__); 1326 1277 1278 + /* cancel uncache work */ 1279 + cancel_delayed_work_sync(&fwc->work); 1280 + 1327 1281 /* 1328 1282 * use small loading timeout for caching devices' firmware 1329 1283 * because all these firmware images have been loaded ··· 1344 1292 mutex_unlock(&fw_lock); 1345 1293 1346 1294 /* wait for completion of caching firmware for all devices */ 1347 - spin_lock(&fwc->name_lock); 1348 - for (;;) { 1349 - prepare_to_wait(&fwc->wait_queue, &wait, 1350 - TASK_UNINTERRUPTIBLE); 1351 - if (!fwc->cnt) 1352 - break; 1353 - 1354 - spin_unlock(&fwc->name_lock); 1355 - 1356 - schedule(); 1357 - 1358 - spin_lock(&fwc->name_lock); 1359 - } 1360 - spin_unlock(&fwc->name_lock); 1361 - finish_wait(&fwc->wait_queue, &wait); 1295 + async_synchronize_full_domain(&fw_cache_domain); 1362 1296 1363 1297 loading_timeout = old_timeout; 1364 1298 } ··· 1432 1394 #ifdef CONFIG_PM_SLEEP 1433 1395 spin_lock_init(&fw_cache.name_lock); 1434 1396 INIT_LIST_HEAD(&fw_cache.fw_names); 1435 - fw_cache.cnt = 0; 1436 1397 1437 - init_waitqueue_head(&fw_cache.wait_queue); 1438 1398 INIT_DELAYED_WORK(&fw_cache.work, 1439 1399 device_uncache_fw_images_work); 1440 1400
+8 -8
fs/sysfs/dir.c
··· 485 485 /** 486 486 * sysfs_pathname - return full path to sysfs dirent 487 487 * @sd: sysfs_dirent whose path we want 488 - * @path: caller allocated buffer 488 + * @path: caller allocated buffer of size PATH_MAX 489 489 * 490 490 * Gives the name "/" to the sysfs_root entry; any path returned 491 491 * is relative to wherever sysfs is mounted. 492 - * 493 - * XXX: does no error checking on @path size 494 492 */ 495 493 static char *sysfs_pathname(struct sysfs_dirent *sd, char *path) 496 494 { 497 495 if (sd->s_parent) { 498 496 sysfs_pathname(sd->s_parent, path); 499 - strcat(path, "/"); 497 + strlcat(path, "/", PATH_MAX); 500 498 } 501 - strcat(path, sd->s_name); 499 + strlcat(path, sd->s_name, PATH_MAX); 502 500 return path; 503 501 } 504 502 ··· 529 531 char *path = kzalloc(PATH_MAX, GFP_KERNEL); 530 532 WARN(1, KERN_WARNING 531 533 "sysfs: cannot create duplicate filename '%s'\n", 532 - (path == NULL) ? sd->s_name : 533 - strcat(strcat(sysfs_pathname(acxt->parent_sd, path), "/"), 534 - sd->s_name)); 534 + (path == NULL) ? sd->s_name 535 + : (sysfs_pathname(acxt->parent_sd, path), 536 + strlcat(path, "/", PATH_MAX), 537 + strlcat(path, sd->s_name, PATH_MAX), 538 + path)); 535 539 kfree(path); 536 540 } 537 541
+1 -1
include/linux/dynamic_debug.h
··· 61 61 const char *fmt, ...); 62 62 63 63 #define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt) \ 64 - static struct _ddebug __used __aligned(8) \ 64 + static struct _ddebug __aligned(8) \ 65 65 __attribute__((section("__verbose"))) name = { \ 66 66 .modname = KBUILD_MODNAME, \ 67 67 .function = __func__, \