From 7307d1d0f96de089131741d2a9cf564b35ea3804 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Tue, 18 Feb 2020 15:33:50 +0900 Subject: [PATCH 001/592] ANDROID: net: bpf: Allow TC programs to call BPF_FUNC_skb_change_head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This enables ebpf tethering offload from a cellular interface with no L2 mac header to a wifi/ethernet/usb interface with one. Will pursue upstreaming this along with further mtu related fixups. Test: builds, real testing with identical patch on a 4.14 flame device Bug: 149724482 Signed-off-by: Lorenzo Colitti Signed-off-by: Maciej Żenczykowski Change-Id: Ic182320bf1abb248d0f86fa2973c60208710f664 --- net/core/filter.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/core/filter.c b/net/core/filter.c index a3646230fbee..a00955173328 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -3260,6 +3260,8 @@ tc_cls_act_func_proto(enum bpf_func_id func_id) return &bpf_skb_adjust_room_proto; case BPF_FUNC_skb_change_tail: return &bpf_skb_change_tail_proto; + case BPF_FUNC_skb_change_head: + return &bpf_skb_change_head_proto; case BPF_FUNC_skb_get_tunnel_key: return &bpf_skb_get_tunnel_key_proto; case BPF_FUNC_skb_set_tunnel_key: From 9224f783f18d329b9d9212ec3f87d295beb5772b Mon Sep 17 00:00:00 2001 From: Miles Chen Date: Thu, 12 Sep 2019 18:34:52 +0800 Subject: [PATCH 002/592] UPSTREAM: sched/psi: Correct overly pessimistic size calculation When passing a equal or more then 32 bytes long string to psi_write(), psi_write() copies 31 bytes to its buf and overwrites buf[30] with '\0'. Which makes the input string 1 byte shorter than it should be. Fix it by copying sizeof(buf) bytes when nbytes >= sizeof(buf). This does not cause problems in normal use case like: "some 500000 10000000" or "full 500000 10000000" because they are less than 32 bytes in length. /* assuming nbytes == 35 */ char buf[32]; buf_size = min(nbytes, (sizeof(buf) - 1)); /* buf_size = 31 */ if (copy_from_user(buf, user_buf, buf_size)) return -EFAULT; buf[buf_size - 1] = '\0'; /* buf[30] = '\0' */ Before: %cd /proc/pressure/ %echo "123456789|123456789|123456789|1234" > memory [ 22.473497] nbytes=35,buf_size=31 [ 22.473775] 123456789|123456789|123456789| (print 30 chars) %sh: write error: Invalid argument %echo "123456789|123456789|123456789|1" > memory [ 64.916162] nbytes=32,buf_size=31 [ 64.916331] 123456789|123456789|123456789| (print 30 chars) %sh: write error: Invalid argument After: %cd /proc/pressure/ %echo "123456789|123456789|123456789|1234" > memory [ 254.837863] nbytes=35,buf_size=32 [ 254.838541] 123456789|123456789|123456789|1 (print 31 chars) %sh: write error: Invalid argument %echo "123456789|123456789|123456789|1" > memory [ 9965.714935] nbytes=32,buf_size=32 [ 9965.715096] 123456789|123456789|123456789|1 (print 31 chars) %sh: write error: Invalid argument Also remove the superfluous parentheses. Signed-off-by: Miles Chen Cc: Cc: Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: https://lkml.kernel.org/r/20190912103452.13281-1-miles.chen@mediatek.com Signed-off-by: Ingo Molnar (cherry picked from commit 4adcdcea717cb2d8436bef00dd689aa5bc76f11b) Signed-off-by: Suren Baghdasaryan Change-Id: I9371b4d5e465bb8b84ff7adf5f40f30696c6ff70 --- kernel/sched/psi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/sched/psi.c b/kernel/sched/psi.c index eb6500b81626..81d96ab8a3af 100644 --- a/kernel/sched/psi.c +++ b/kernel/sched/psi.c @@ -1191,7 +1191,7 @@ static ssize_t psi_write(struct file *file, const char __user *user_buf, if (static_branch_likely(&psi_disabled)) return -EOPNOTSUPP; - buf_size = min(nbytes, (sizeof(buf) - 1)); + buf_size = min(nbytes, sizeof(buf)); if (copy_from_user(buf, user_buf, buf_size)) return -EFAULT; From 27e2f95e0440e8a828dad90d7113d6263ae1c739 Mon Sep 17 00:00:00 2001 From: Johannes Weiner Date: Tue, 3 Dec 2019 13:35:23 -0500 Subject: [PATCH 003/592] UPSTREAM: sched/psi: Fix sampling error and rare div0 crashes with cgroups and high uptime Jingfeng reports rare div0 crashes in psi on systems with some uptime: [58914.066423] divide error: 0000 [#1] SMP [58914.070416] Modules linked in: ipmi_poweroff ipmi_watchdog toa overlay fuse tcp_diag inet_diag binfmt_misc aisqos(O) aisqos_hotfixes(O) [58914.083158] CPU: 94 PID: 140364 Comm: kworker/94:2 Tainted: G W OE K 4.9.151-015.ali3000.alios7.x86_64 #1 [58914.093722] Hardware name: Alibaba Alibaba Cloud ECS/Alibaba Cloud ECS, BIOS 3.23.34 02/14/2019 [58914.102728] Workqueue: events psi_update_work [58914.107258] task: ffff8879da83c280 task.stack: ffffc90059dcc000 [58914.113336] RIP: 0010:[] [] psi_update_stats+0x1c1/0x330 [58914.122183] RSP: 0018:ffffc90059dcfd60 EFLAGS: 00010246 [58914.127650] RAX: 0000000000000000 RBX: ffff8858fe98be50 RCX: 000000007744d640 [58914.134947] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 00003594f700648e [58914.142243] RBP: ffffc90059dcfdf8 R08: 0000359500000000 R09: 0000000000000000 [58914.149538] R10: 0000000000000000 R11: 0000000000000000 R12: 0000359500000000 [58914.156837] R13: 0000000000000000 R14: 0000000000000000 R15: ffff8858fe98bd78 [58914.164136] FS: 0000000000000000(0000) GS:ffff887f7f380000(0000) knlGS:0000000000000000 [58914.172529] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [58914.178467] CR2: 00007f2240452090 CR3: 0000005d5d258000 CR4: 00000000007606f0 [58914.185765] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [58914.193061] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [58914.200360] PKRU: 55555554 [58914.203221] Stack: [58914.205383] ffff8858fe98bd48 00000000000002f0 0000002e81036d09 ffffc90059dcfde8 [58914.213168] ffff8858fe98bec8 0000000000000000 0000000000000000 0000000000000000 [58914.220951] 0000000000000000 0000000000000000 0000000000000000 0000000000000000 [58914.228734] Call Trace: [58914.231337] [] psi_update_work+0x22/0x60 [58914.237067] [] process_one_work+0x189/0x420 [58914.243063] [] worker_thread+0x4e/0x4b0 [58914.248701] [] ? process_one_work+0x420/0x420 [58914.254869] [] kthread+0xe6/0x100 [58914.259994] [] ? kthread_park+0x60/0x60 [58914.265640] [] ret_from_fork+0x39/0x50 [58914.271193] Code: 41 29 c3 4d 39 dc 4d 0f 42 dc <49> f7 f1 48 8b 13 48 89 c7 48 c1 [58914.279691] RIP [] psi_update_stats+0x1c1/0x330 The crashing instruction is trying to divide the observed stall time by the sampling period. The period, stored in R8, is not 0, but we are dividing by the lower 32 bits only, which are all 0 in this instance. We could switch to a 64-bit division, but the period shouldn't be that big in the first place. It's the time between the last update and the next scheduled one, and so should always be around 2s and comfortably fit into 32 bits. The bug is in the initialization of new cgroups: we schedule the first sampling event in a cgroup as an offset of sched_clock(), but fail to initialize the last_update timestamp, and it defaults to 0. That results in a bogusly large sampling period the first time we run the sampling code, and consequently we underreport pressure for the first 2s of a cgroup's life. But worse, if sched_clock() is sufficiently advanced on the system, and the user gets unlucky, the period's lower 32 bits can all be 0 and the sampling division will crash. Fix this by initializing the last update timestamp to the creation time of the cgroup, thus correctly marking the start of the first pressure sampling period in a new cgroup. Reported-by: Jingfeng Xie Signed-off-by: Johannes Weiner Signed-off-by: Peter Zijlstra (Intel) Cc: Suren Baghdasaryan Link: https://lkml.kernel.org/r/20191203183524.41378-2-hannes@cmpxchg.org Signed-off-by: Sasha Levin (cherry picked from commit 3dfbe25c27eab7c90c8a7e97b4c354a9d24dd985) Signed-off-by: Suren Baghdasaryan Change-Id: Iaada5c2f1a03cf38cbb053adde478f762ce40843 --- kernel/sched/psi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/sched/psi.c b/kernel/sched/psi.c index 81d96ab8a3af..4123f5459aca 100644 --- a/kernel/sched/psi.c +++ b/kernel/sched/psi.c @@ -186,7 +186,8 @@ static void group_init(struct psi_group *group) for_each_possible_cpu(cpu) seqcount_init(&per_cpu_ptr(group->pcpu, cpu)->seq); - group->avg_next_update = sched_clock() + psi_period; + group->avg_last_update = sched_clock(); + group->avg_next_update = group->avg_last_update + psi_period; INIT_DELAYED_WORK(&group->avgs_work, psi_avgs_work); mutex_init(&group->avgs_lock); /* Init trigger-related members */ From 3ff82f07088a71f5d0e6deb2baf3c5b89460cbae Mon Sep 17 00:00:00 2001 From: Johannes Weiner Date: Tue, 3 Dec 2019 13:35:24 -0500 Subject: [PATCH 004/592] UPSTREAM: psi: Fix a division error in psi poll() The psi window size is a u64 an can be up to 10 seconds right now, which exceeds the lower 32 bits of the variable. We currently use div_u64 for it, which is meant only for 32-bit divisors. The result is garbage pressure sampling values and even potential div0 crashes. Use div64_u64. Signed-off-by: Johannes Weiner Signed-off-by: Peter Zijlstra (Intel) Reviewed-by: Suren Baghdasaryan Cc: Jingfeng Xie Link: https://lkml.kernel.org/r/20191203183524.41378-3-hannes@cmpxchg.org Signed-off-by: Sasha Levin (cherry picked from commit c3466952ca1514158d7c16c9cfc48c27d5c5dc0f) Signed-off-by: Suren Baghdasaryan Change-Id: I49fdfd55751d1a2cde19666624c9c5d76dc78dad --- kernel/sched/psi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/sched/psi.c b/kernel/sched/psi.c index 4123f5459aca..5ed1027d75d6 100644 --- a/kernel/sched/psi.c +++ b/kernel/sched/psi.c @@ -483,7 +483,7 @@ static u64 window_update(struct psi_window *win, u64 now, u64 value) u32 remaining; remaining = win->size - elapsed; - growth += div_u64(win->prev_growth * remaining, win->size); + growth += div64_u64(win->prev_growth * remaining, win->size); } return growth; From d65be1c67eff4b6b3856b54eaaf64e28ee51fb85 Mon Sep 17 00:00:00 2001 From: Suren Baghdasaryan Date: Mon, 3 Feb 2020 13:22:16 -0800 Subject: [PATCH 005/592] UPSTREAM: sched/psi: Fix OOB write when writing 0 bytes to PSI files Issuing write() with count parameter set to 0 on any file under /proc/pressure/ will cause an OOB write because of the access to buf[buf_size-1] when NUL-termination is performed. Fix this by checking for buf_size to be non-zero. Signed-off-by: Suren Baghdasaryan Signed-off-by: Peter Zijlstra (Intel) Signed-off-by: Ingo Molnar Acked-by: Johannes Weiner Link: https://lkml.kernel.org/r/20200203212216.7076-1-surenb@google.com (cherry picked from commit 6fcca0fa48118e6d63733eb4644c6cd880c15b8f) Bug: 148159562 Signed-off-by: Suren Baghdasaryan Change-Id: I9ec7acfc6e1083c677a95b0ea1c559ab50152873 --- kernel/sched/psi.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/sched/psi.c b/kernel/sched/psi.c index 5ed1027d75d6..59d5371694e4 100644 --- a/kernel/sched/psi.c +++ b/kernel/sched/psi.c @@ -1192,6 +1192,9 @@ static ssize_t psi_write(struct file *file, const char __user *user_buf, if (static_branch_likely(&psi_disabled)) return -EOPNOTSUPP; + if (!nbytes) + return -EINVAL; + buf_size = min(nbytes, sizeof(buf)); if (copy_from_user(buf, user_buf, buf_size)) return -EFAULT; From e9ff34ad792247c1f99922ee9f4be84e284e6eaf Mon Sep 17 00:00:00 2001 From: Todd Kjos Date: Fri, 13 Dec 2019 12:25:31 -0800 Subject: [PATCH 006/592] UPSTREAM: binder: fix incorrect calculation for num_valid commit 16981742717b04644a41052570fb502682a315d2 upstream. For BINDER_TYPE_PTR and BINDER_TYPE_FDA transactions, the num_valid local was calculated incorrectly causing the range check in binder_validate_ptr() to miss out-of-bounds offsets. Fixes: bde4a19fc04f ("binder: use userspace pointer as base of buffer space") Change-Id: Ida77db13d8e5b726f0b14513f55c2b30277338cd Signed-off-by: Todd Kjos Cc: stable Link: https://lore.kernel.org/r/20191213202531.55010-1-tkjos@google.com Signed-off-by: Greg Kroah-Hartman Bug: 145988638 Signed-off-by: Todd Kjos --- drivers/android/binder.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/android/binder.c b/drivers/android/binder.c index f6ddec245187..2c8b629c90c3 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -3428,7 +3428,7 @@ static void binder_transaction(struct binder_proc *proc, binder_size_t parent_offset; struct binder_fd_array_object *fda = to_binder_fd_array_object(hdr); - size_t num_valid = (buffer_offset - off_start_offset) * + size_t num_valid = (buffer_offset - off_start_offset) / sizeof(binder_size_t); struct binder_buffer_object *parent = binder_validate_ptr(target_proc, t->buffer, @@ -3502,7 +3502,7 @@ static void binder_transaction(struct binder_proc *proc, t->buffer->user_data + sg_buf_offset; sg_buf_offset += ALIGN(bp->length, sizeof(u64)); - num_valid = (buffer_offset - off_start_offset) * + num_valid = (buffer_offset - off_start_offset) / sizeof(binder_size_t); ret = binder_fixup_parent(t, thread, bp, off_start_offset, From 8cb0188c631f3bd076e8a1a76e79ea1f398e9b39 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 20 Mar 2020 10:48:13 +0100 Subject: [PATCH 007/592] UPSTREAM: bpf: Explicitly memset the bpf_attr structure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For the bpf syscall, we are relying on the compiler to properly zero out the bpf_attr union that we copy userspace data into. Unfortunately that doesn't always work properly, padding and other oddities might not be correctly zeroed, and in some tests odd things have been found when the stack is pre-initialized to other values. Fix this by explicitly memsetting the structure to 0 before using it. Reported-by: Maciej Żenczykowski Reported-by: John Stultz Reported-by: Alexander Potapenko Reported-by: Alistair Delva Signed-off-by: Greg Kroah-Hartman Signed-off-by: Daniel Borkmann Acked-by: Yonghong Song Link: https://android-review.googlesource.com/c/kernel/common/+/1235490 Link: https://lore.kernel.org/bpf/20200320094813.GA421650@kroah.com (cherry picked from commit 8096f229421f7b22433775e928d506f0342e5907) Signed-off-by: Greg Kroah-Hartman Change-Id: I2dc28cd45024da5cc6861ff4a9b25fae389cc6d8 --- kernel/bpf/syscall.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 171e605d0a55..4fb4b7129fb4 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -1568,7 +1568,7 @@ static int bpf_obj_get_info_by_fd(const union bpf_attr *attr, SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, size) { - union bpf_attr attr = {}; + union bpf_attr attr; int err; if (sysctl_unprivileged_bpf_disabled && !capable(CAP_SYS_ADMIN)) @@ -1580,6 +1580,7 @@ SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, siz size = min_t(u32, size, sizeof(attr)); /* copy attributes from user space, may be less than sizeof(bpf_attr) */ + memset(&attr, 0, sizeof(attr)); if (copy_from_user(&attr, uattr, size) != 0) return -EFAULT; From ebf7b824f60970c6c3dc9497649c4885b0c351e2 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 20 Mar 2020 17:22:58 +0100 Subject: [PATCH 008/592] UPSTREAM: bpf: Explicitly memset some bpf info structures declared on the stack Trying to initialize a structure with "= {};" will not always clean out all padding locations in a structure. So be explicit and call memset to initialize everything for a number of bpf information structures that are then copied from userspace, sometimes from smaller memory locations than the size of the structure. Reported-by: Daniel Borkmann Signed-off-by: Greg Kroah-Hartman Signed-off-by: Daniel Borkmann Acked-by: Yonghong Song Link: https://lore.kernel.org/bpf/20200320162258.GA794295@kroah.com (cherry picked from commit 269efb7fc478563a7e7b22590d8076823f4ac82a) Signed-off-by: Greg Kroah-Hartman Change-Id: I52a2cab20aa310085ec104bd811ac4f2b83657b6 --- kernel/bpf/syscall.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 4fb4b7129fb4..fa749278ce6d 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -1458,7 +1458,7 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog, union bpf_attr __user *uattr) { struct bpf_prog_info __user *uinfo = u64_to_user_ptr(attr->info.info); - struct bpf_prog_info info = {}; + struct bpf_prog_info info; u32 info_len = attr->info.info_len; char __user *uinsns; u32 ulen; @@ -1469,6 +1469,7 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog, return err; info_len = min_t(u32, sizeof(info), info_len); + memset(&info, 0, sizeof(info)); if (copy_from_user(&info, uinfo, info_len)) return -EFAULT; @@ -1514,7 +1515,7 @@ static int bpf_map_get_info_by_fd(struct bpf_map *map, union bpf_attr __user *uattr) { struct bpf_map_info __user *uinfo = u64_to_user_ptr(attr->info.info); - struct bpf_map_info info = {}; + struct bpf_map_info info; u32 info_len = attr->info.info_len; int err; @@ -1523,6 +1524,7 @@ static int bpf_map_get_info_by_fd(struct bpf_map *map, return err; info_len = min_t(u32, sizeof(info), info_len); + memset(&info, 0, sizeof(info)); info.type = map->map_type; info.id = map->id; info.key_size = map->key_size; From ceaaa00330e063b066038f906f29f85c9f5b4c1b Mon Sep 17 00:00:00 2001 From: Dylan Chang Date: Mon, 23 Mar 2020 14:56:02 +0800 Subject: [PATCH 009/592] ANDROID: dm-bow: Fix free_show value is incorrect Fix free_show value is incorrect Change-Id: If7f36a64afa600c980ee8a25393f8716a6ffd474 Signed-off-by: Dylan Chang Bug: 152116739 Signed-off-by: Paul Lawrence --- drivers/md/dm-bow.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/md/dm-bow.c b/drivers/md/dm-bow.c index b92da30a3d42..ce6d4d834b17 100644 --- a/drivers/md/dm-bow.c +++ b/drivers/md/dm-bow.c @@ -792,6 +792,7 @@ static int prepare_unchanged_range(struct bow_context *bc, struct bow_range *br, */ original_type = br->type; sector0 = backup_br->sector; + bc->trims_total -= range_size(backup_br); if (backup_br->type == TRIMMED) list_del(&backup_br->trimmed_list); backup_br->type = br->type == SECTOR0_CURRENT ? SECTOR0_CURRENT From 4c669aae14bca3bfbeeab3afa73dbfbcf2cdc15a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBenczykowski?= Date: Mon, 23 Mar 2020 18:10:19 -0700 Subject: [PATCH 010/592] UPSTREAM: ipv6: ndisc: add support for 'PREF64' dns64 prefix identifier MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is trivial since we already have support for the entirely identical (from the kernel's point of view) RDNSS, DNSSL, etc. that also contain opaque data that needs to be passed down to userspace for further processing. As specified in draft-ietf-6man-ra-pref64-09 (while it is still a draft, it is purely waiting on the RFC Editor for cleanups and publishing): PREF64 option contains lifetime and a (up to) 96-bit IPv6 prefix. The 8-bit identifier of the option type as assigned by the IANA is 38. Since we lack DNS64/NAT64/CLAT support in kernel at the moment, thus this option should also be passed on to userland. See: https://tools.ietf.org/html/draft-ietf-6man-ra-pref64-09 https://www.iana.org/assignments/icmpv6-parameters/icmpv6-parameters.xhtml#icmpv6-parameters-5 Cc: Erik Kline Cc: Jen Linkova Cc: Lorenzo Colitti Cc: Michael Haro Signed-off-by: Maciej Żenczykowski Acked-By: Lorenzo Colitti Signed-off-by: David S. Miller (cherry picked from commit c24a77edc9a7ac9b5fea75407f197fe1469262f4) Bug: 150648313 Change-Id: I02bff2103194a8171f907e82f811d7ab66962138 --- include/net/ndisc.h | 1 + net/ipv6/ndisc.c | 1 + 2 files changed, 2 insertions(+) diff --git a/include/net/ndisc.h b/include/net/ndisc.h index d2a016ef5c41..35d7c887a5b9 100644 --- a/include/net/ndisc.h +++ b/include/net/ndisc.h @@ -39,6 +39,7 @@ enum { ND_OPT_DNSSL = 31, /* RFC6106 */ ND_OPT_6CO = 34, /* RFC6775 */ ND_OPT_CAPTIVE_PORTAL = 37, /* RFC7710 */ + ND_OPT_PREF64 = 38, /* RFC-ietf-6man-ra-pref64-09 */ __ND_OPT_MAX }; diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 381708112f7d..2241c5f52394 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -197,6 +197,7 @@ static inline int ndisc_is_useropt(const struct net_device *dev, return opt->nd_opt_type == ND_OPT_RDNSS || opt->nd_opt_type == ND_OPT_DNSSL || opt->nd_opt_type == ND_OPT_CAPTIVE_PORTAL || + opt->nd_opt_type == ND_OPT_PREF64 || ndisc_ops_is_useropt(dev, opt->nd_opt_type); } From 893be4cc44224ec87f523791635349b0223a7961 Mon Sep 17 00:00:00 2001 From: Martijn Coenen Date: Tue, 10 Mar 2020 14:12:30 +0100 Subject: [PATCH 011/592] UPSTREAM: loop: Only change blocksize when needed. Return early in loop_set_block_size() if the requested block size is identical to the one we already have; this avoids expensive calls to freeze the block queue. Bug: 148607611 Reviewed-by: Christoph Hellwig Signed-off-by: Martijn Coenen Signed-off-by: Jens Axboe (cherry picked from commit 7e81f99afd91c937f0e66dc135e26c1c4f78b003) Change-Id: I61778680579dbfeeb193133527a3926d376e0bac --- drivers/block/loop.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 453e3728e657..8655b5079e3c 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -1378,16 +1378,16 @@ static int loop_set_block_size(struct loop_device *lo, unsigned long arg) if (arg < 512 || arg > PAGE_SIZE || !is_power_of_2(arg)) return -EINVAL; - if (lo->lo_queue->limits.logical_block_size != arg) { - sync_blockdev(lo->lo_device); - kill_bdev(lo->lo_device); - } + if (lo->lo_queue->limits.logical_block_size == arg) + return 0; + + sync_blockdev(lo->lo_device); + kill_bdev(lo->lo_device); blk_mq_freeze_queue(lo->lo_queue); /* kill_bdev should have truncated all the pages */ - if (lo->lo_queue->limits.logical_block_size != arg && - lo->lo_device->bd_inode->i_mapping->nrpages) { + if (lo->lo_device->bd_inode->i_mapping->nrpages) { err = -EAGAIN; pr_warn("%s: loop%d (%s) has still dirty pages (nrpages=%lu)\n", __func__, lo->lo_number, lo->lo_file_name, From dfd84eb7e890e3e5cd0aa56edd7a1cd80135e476 Mon Sep 17 00:00:00 2001 From: Martijn Coenen Date: Tue, 10 Mar 2020 14:06:54 +0100 Subject: [PATCH 012/592] UPSTREAM: loop: Only freeze block queue when needed. __loop_update_dio() can be called as a part of loop_set_fd(), when the block queue is not yet up and running; avoid freezing the block queue in that case, since that is an expensive operation. Bug: 148607611 Reviewed-by: Christoph Hellwig Reviewed-by: Chaitanya Kulkarni Signed-off-by: Martijn Coenen Signed-off-by: Jens Axboe (cherry picked from commit 0fbcf57982346763ec636f176d5afaa367b5f71b) Change-Id: I17d8de6b6b54a667703d60ea1c62449bb14331da --- drivers/block/loop.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 8655b5079e3c..2ede7d74e0ee 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -211,7 +211,8 @@ static void __loop_update_dio(struct loop_device *lo, bool dio) * LO_FLAGS_READ_ONLY, both are set from kernel, and losetup * will get updated by ioctl(LOOP_GET_STATUS) */ - blk_mq_freeze_queue(lo->lo_queue); + if (lo->lo_state == Lo_bound) + blk_mq_freeze_queue(lo->lo_queue); lo->use_dio = use_dio; if (use_dio) { queue_flag_clear_unlocked(QUEUE_FLAG_NOMERGES, lo->lo_queue); @@ -220,7 +221,8 @@ static void __loop_update_dio(struct loop_device *lo, bool dio) queue_flag_set_unlocked(QUEUE_FLAG_NOMERGES, lo->lo_queue); lo->lo_flags &= ~LO_FLAGS_DIRECT_IO; } - blk_mq_unfreeze_queue(lo->lo_queue); + if (lo->lo_state == Lo_bound) + blk_mq_unfreeze_queue(lo->lo_queue); } static int From 8ad98eebd13a9fb3e3604b51da578a8bc85de0c9 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Fri, 16 Aug 2019 22:33:20 +0000 Subject: [PATCH 013/592] ANDROID: cuttlefish_defconfig: Minimally enable EFI HiKey/HiKey960 need UEFI support to boot but don't need much of the other options that default on when enabling EFI. Bug: 140204135 [adelva: backport to 4.14-q for cuttlefish vmlinux detection in extract-vmlinux, where the kernel needs to be a PE executable for compatibility with 4.19 GKI] Signed-off-by: John Stultz Change-Id: I5c2e63701ae93277fcc3ddb36a39637237c65194 Signed-off-by: Alistair Delva --- arch/arm64/configs/cuttlefish_defconfig | 2 +- arch/x86/configs/x86_64_cuttlefish_defconfig | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/arm64/configs/cuttlefish_defconfig b/arch/arm64/configs/cuttlefish_defconfig index 55ccc9ad1b40..357dc24a2e33 100644 --- a/arch/arm64/configs/cuttlefish_defconfig +++ b/arch/arm64/configs/cuttlefish_defconfig @@ -59,7 +59,6 @@ CONFIG_SETEND_EMULATION=y CONFIG_ARM64_SW_TTBR0_PAN=y CONFIG_ARM64_LSE_ATOMICS=y CONFIG_RANDOMIZE_BASE=y -# CONFIG_EFI is not set # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set CONFIG_COMPAT=y CONFIG_PM_WAKELOCKS=y @@ -422,6 +421,7 @@ CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y CONFIG_TMPFS=y CONFIG_TMPFS_POSIX_ACL=y +# CONFIG_EFIVAR_FS is not set CONFIG_SDCARD_FS=y CONFIG_PSTORE=y CONFIG_PSTORE_CONSOLE=y diff --git a/arch/x86/configs/x86_64_cuttlefish_defconfig b/arch/x86/configs/x86_64_cuttlefish_defconfig index 041475898a1f..39b1a4d10592 100644 --- a/arch/x86/configs/x86_64_cuttlefish_defconfig +++ b/arch/x86/configs/x86_64_cuttlefish_defconfig @@ -57,6 +57,7 @@ CONFIG_KSM=y CONFIG_DEFAULT_MMAP_MIN_ADDR=65536 CONFIG_ZSMALLOC=y # CONFIG_MTRR is not set +CONFIG_EFI=y CONFIG_HZ_100=y CONFIG_KEXEC=y CONFIG_CRASH_DUMP=y @@ -445,6 +446,7 @@ CONFIG_PROC_KCORE=y CONFIG_TMPFS=y CONFIG_TMPFS_POSIX_ACL=y CONFIG_HUGETLBFS=y +# CONFIG_EFIVAR_FS is not set CONFIG_SDCARD_FS=y CONFIG_PSTORE=y CONFIG_PSTORE_CONSOLE=y From 907f2050333a68ec2166f0b5badb0edd85ef584c Mon Sep 17 00:00:00 2001 From: Martijn Coenen Date: Wed, 4 Sep 2019 21:49:01 +0200 Subject: [PATCH 014/592] BACKPORT: loop: change queue block size to match when using DIO The loop driver assumes that if the passed in fd is opened with O_DIRECT, the caller wants to use direct I/O on the loop device. However, if the underlying block device has a different block size than the loop block queue, direct I/O can't be enabled. Instead of requiring userspace to manually change the blocksize and re-enable direct I/O, just change the queue block sizes to match, as well as the io_min size. Bug: 148607611 Reviewed-by: Christoph Hellwig Signed-off-by: Martijn Coenen Signed-off-by: Jens Axboe (cherry picked from commit 85560117d00f5d528e928918b8f61cadcefff98b) Change-Id: I76f95738ce0cfead24af0704b2d38be2f9ddea7e --- drivers/block/loop.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 2ede7d74e0ee..89ed319c2827 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -942,6 +942,16 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode, if (!(lo_flags & LO_FLAGS_READ_ONLY) && file->f_op->fsync) blk_queue_write_cache(lo->lo_queue, true, false); + if (io_is_direct(lo->lo_backing_file) && inode->i_sb->s_bdev) { + /* In case of direct I/O, match underlying block size */ + unsigned short bsize = bdev_logical_block_size( + inode->i_sb->s_bdev); + + blk_queue_logical_block_size(lo->lo_queue, bsize); + blk_queue_physical_block_size(lo->lo_queue, bsize); + blk_queue_io_min(lo->lo_queue, bsize); + } + loop_update_dio(lo); set_capacity(lo->lo_disk, size); bd_set_size(bdev, size << 9); From 6e1fc415e8704fe032fda29e6bb4acdeea8298d9 Mon Sep 17 00:00:00 2001 From: Evan Green Date: Mon, 2 Jul 2018 16:03:46 -0700 Subject: [PATCH 015/592] BACKPORT: loop: Add LOOP_SET_BLOCK_SIZE in compat ioctl This change adds LOOP_SET_BLOCK_SIZE as one of the supported ioctls in lo_compat_ioctl. It only takes an unsigned long argument, and in practice a 32-bit value works fine. Reviewed-by: Omar Sandoval Signed-off-by: Evan Green Signed-off-by: Jens Axboe (cherry picked from commit 9fea4b395260175de4016b42982f45a3e6e03d0b) [adelva: trivially backported around another backport conflict] Bug: 150622092 Change-Id: I98e14d3ab60ca638c3aebcea942e2207c738af95 Signed-off-by: Alistair Delva --- drivers/block/loop.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 89ed319c2827..45c74f2c9bcc 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -1627,6 +1627,7 @@ static int lo_compat_ioctl(struct block_device *bdev, fmode_t mode, arg = (unsigned long) compat_ptr(arg); case LOOP_SET_FD: case LOOP_CHANGE_FD: + case LOOP_SET_BLOCK_SIZE: case LOOP_SET_DIRECT_IO: err = lo_ioctl(bdev, mode, cmd, arg); break; From 74a4c09660236c3115a7f12d183d6d7b77ce5551 Mon Sep 17 00:00:00 2001 From: Alistair Delva Date: Fri, 1 May 2020 09:07:07 -0700 Subject: [PATCH 016/592] ANDROID: cuttlefish_defconfig: Fix dm-verity related options Use the suggestions mentioned in the APEX documentation https://source.android.com/devices/tech/ota/apex Also, enable DM_VERITY_AVB on x86, which was incorrectly disabled. Change-Id: Id9e1b0bf525802dd67a9bf4b7c6c6408e87948fd Signed-off-by: Alistair Delva --- arch/arm64/configs/cuttlefish_defconfig | 1 + arch/x86/configs/x86_64_cuttlefish_defconfig | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/arm64/configs/cuttlefish_defconfig b/arch/arm64/configs/cuttlefish_defconfig index 357dc24a2e33..1cc26061705b 100644 --- a/arch/arm64/configs/cuttlefish_defconfig +++ b/arch/arm64/configs/cuttlefish_defconfig @@ -202,6 +202,7 @@ CONFIG_DEBUG_DEVRES=y CONFIG_OF_UNITTEST=y CONFIG_ZRAM=y CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_LOOP_MIN_COUNT=16 CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=8192 CONFIG_VIRTIO_BLK=y diff --git a/arch/x86/configs/x86_64_cuttlefish_defconfig b/arch/x86/configs/x86_64_cuttlefish_defconfig index 39b1a4d10592..88eb2873f4e4 100644 --- a/arch/x86/configs/x86_64_cuttlefish_defconfig +++ b/arch/x86/configs/x86_64_cuttlefish_defconfig @@ -218,6 +218,7 @@ CONFIG_OF_UNITTEST=y # CONFIG_PNP_DEBUG_MESSAGES is not set CONFIG_ZRAM=y CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_LOOP_MIN_COUNT=16 CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=8192 CONFIG_VIRTIO_BLK=y @@ -238,7 +239,7 @@ CONFIG_DM_ZERO=y CONFIG_DM_UEVENT=y CONFIG_DM_VERITY=y CONFIG_DM_VERITY_FEC=y -CONFIG_DM_ANDROID_VERITY=y +CONFIG_DM_VERITY_AVB=y CONFIG_DM_BOW=y CONFIG_NETDEVICES=y CONFIG_NETCONSOLE=y From 348acfb2be567396eaafd37d62d54b001ece8616 Mon Sep 17 00:00:00 2001 From: Minchan Kim Date: Sat, 30 Nov 2019 17:58:29 -0800 Subject: [PATCH 017/592] UPSTREAM: mm/page_io.c: annotate refault stalls from swap_readpage If a block device supports rw_page operation, it doesn't submit bios so the annotation in submit_bio() for refault stall doesn't work. It happens with zram in android, especially swap read path which could consume CPU cycle for decompress. It is also a problem for zswap which uses frontswap. Annotate swap_readpage() to account the synchronous IO overhead to prevent underreport memory pressure. [akpm@linux-foundation.org: add comment, per Johannes] Link: http://lkml.kernel.org/r/20191010152134.38545-1-minchan@kernel.org Signed-off-by: Minchan Kim Acked-by: Johannes Weiner Reviewed-by: Shakeel Butt Cc: Seth Jennings Cc: Dan Streetman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds (cherry picked from commit 937790699be9c8100e5358625e7dfa8b32bd33f2) Bug: 142418748 Signed-off-by: Suren Baghdasaryan Change-Id: I8a63030888996b6c0a3a9abe3f2d0eca0a0d765b --- mm/page_io.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/mm/page_io.c b/mm/page_io.c index 5d882de3fbfd..9f8fd8f42b0d 100644 --- a/mm/page_io.c +++ b/mm/page_io.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -354,10 +355,19 @@ int swap_readpage(struct page *page, bool do_poll) struct swap_info_struct *sis = page_swap_info(page); blk_qc_t qc; struct gendisk *disk; + unsigned long pflags; VM_BUG_ON_PAGE(!PageSwapCache(page), page); VM_BUG_ON_PAGE(!PageLocked(page), page); VM_BUG_ON_PAGE(PageUptodate(page), page); + + /* + * Count submission time as memory stall. When the device is congested, + * or the submitting cgroup IO-throttled, submission can be a + * significant part of overall IO time. + */ + psi_memstall_enter(&pflags); + if (frontswap_load(page) == 0) { SetPageUptodate(page); unlock_page(page); @@ -371,7 +381,7 @@ int swap_readpage(struct page *page, bool do_poll) ret = mapping->a_ops->readpage(swap_file, page); if (!ret) count_vm_event(PSWPIN); - return ret; + goto out; } ret = bdev_read_page(sis->bdev, swap_page_sector(page), page); @@ -382,7 +392,7 @@ int swap_readpage(struct page *page, bool do_poll) } count_vm_event(PSWPIN); - return 0; + goto out; } ret = 0; @@ -415,6 +425,7 @@ int swap_readpage(struct page *page, bool do_poll) bio_put(bio); out: + psi_memstall_leave(&pflags); return ret; } From 8a4cf21fd747f333fd4b236fdfc7548d454f549c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBenczykowski?= Date: Wed, 6 May 2020 16:25:38 -0700 Subject: [PATCH 018/592] ANDROID: net: bpf: permit redirect from ingress L3 to egress L2 devices at near max mtu MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit __bpf_skb_max_len(skb) is used from: bpf_skb_adjust_room __bpf_skb_change_tail __bpf_skb_change_head but in the case of forwarding we're likely calling these functions during receive processing on ingress and bpf_redirect()'ing at a later point in time to egress on another interface, thus these mtu checks are for the wrong device (input instead of output). This is particularly problematic if we're receiving on an L3 1500 mtu cellular interface, trying to add an L2 header and forwarding to an L3 mtu 1500 mtu wifi/ethernet device (which is thus L2 1514). The mtu check prevents us from adding the 14 byte ethernet header prior to forwarding the packet. After the packet has already been redirected, we'd need to add an additional 2nd ebpf program on the target device's egress tc hook, but then we'd also see non-redirected traffic and have no easy way to tell apart normal egress with ethernet header packets from forwarded ethernet headerless packets. Cc: Alexei Starovoitov Cc: Jakub Kicinski Signed-off-by: Maciej Żenczykowski Link: https://patchwork.ozlabs.org/project/netdev/patch/20200507023606.111650-1-zenczykowski@gmail.com/ But note that a more thorough solution will be pursued. Bug: 149816401 Change-Id: If55a144d7822e23bce85f65897bca7de4e0f9b24 --- net/core/filter.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/core/filter.c b/net/core/filter.c index a00955173328..b19fbab3395a 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -2281,6 +2281,8 @@ static int bpf_skb_net_shrink(struct sk_buff *skb, u32 len_diff) static u32 __bpf_skb_max_len(const struct sk_buff *skb) { + if (skb_at_tc_ingress(skb) || !skb->dev) + return SKB_MAX_ALLOC; return skb->dev->mtu + skb->dev->hard_header_len; } From 7187dbb30c7259db610bdc53abc213cd42e4cefd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBenczykowski?= Date: Thu, 28 May 2020 04:44:40 -0700 Subject: [PATCH 019/592] ANDROID: cuttlefish defconfig - enable mount/net/uts namespaces. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These configs are the default for qemu backed kernel net tests. This matches: https://android-review.googlesource.com/c/kernel/configs/+/1320157 R+: require mount/net/uts namespace support Generated via: echo 'CONFIG_NAMESPACES=y' >> arch/arm64/configs/cuttlefish_defconfig make ARCH=arm64 cuttlefish_defconfig make ARCH=arm64 savedefconfig mv defconfig arch/arm64/configs/cuttlefish_defconfig Test: treehugger Bug: 144061615 Signed-off-by: Maciej Żenczykowski Change-Id: I1e15dc04116155ede485dd0458f55ee405fb285c --- arch/arm64/configs/cuttlefish_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/cuttlefish_defconfig b/arch/arm64/configs/cuttlefish_defconfig index 1cc26061705b..4f6591ec4bc6 100644 --- a/arch/arm64/configs/cuttlefish_defconfig +++ b/arch/arm64/configs/cuttlefish_defconfig @@ -17,6 +17,7 @@ CONFIG_CPUSETS=y # CONFIG_PROC_PID_CPUSET is not set CONFIG_CGROUP_CPUACCT=y CONFIG_CGROUP_BPF=y +CONFIG_NAMESPACES=y CONFIG_SCHED_AUTOGROUP=y CONFIG_SCHED_TUNE=y CONFIG_DEFAULT_USE_ENERGY_AWARE=y From 545c1014f0833bb9fb7f21e8cacb4d40fb671d18 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 29 May 2020 10:52:09 -0700 Subject: [PATCH 020/592] BACKPORT: arm64: vdso: use $(LD) instead of $(CC) to link VDSO We use $(LD) to link vmlinux, modules, decompressors, etc. VDSO is the only exceptional case where $(CC) is used as the linker driver, but I do not know why we need to do so. VDSO uses a special linker script, and does not link standard libraries at all. I changed the Makefile to use $(LD) rather than $(CC). I tested this, and VDSO worked for me. Users will be able to use their favorite linker (e.g. lld instead of of bfd) by passing LD= from the command line. My plan is to rewrite all VDSO Makefiles to use $(LD), then delete cc-ldoption. Signed-off-by: Masahiro Yamada Signed-off-by: Will Deacon Change-Id: I8a14d6dd51d46b6942e68720e24217d1564b7869 [nd: conflicts due to ANDROID patches for LTO and SCS] (cherry picked from commit 691efbedc60d2a7364a90e38882fc762f06f52c4) Bug: 153418016 Bug: 157279372 Signed-off-by: Nick Desaulniers (cherry picked from commit 64ea9b4b072b37bd624dd98b963161fd22c1be34) --- arch/arm64/kernel/vdso/Makefile | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/arch/arm64/kernel/vdso/Makefile b/arch/arm64/kernel/vdso/Makefile index ef3f9d9d4062..83cf80d64add 100644 --- a/arch/arm64/kernel/vdso/Makefile +++ b/arch/arm64/kernel/vdso/Makefile @@ -12,18 +12,13 @@ obj-vdso := gettimeofday.o note.o sigreturn.o targets := $(obj-vdso) vdso.so vdso.so.dbg obj-vdso := $(addprefix $(obj)/, $(obj-vdso)) -ccflags-y := -shared -fno-common -fno-builtin -ccflags-y += -nostdlib -Wl,-soname=linux-vdso.so.1 \ - $(call cc-ldoption, -Wl$(comma)--hash-style=sysv) +ldflags-y := -shared -nostdlib -soname=linux-vdso.so.1 \ + $(call ld-option, --hash-style=sysv) -n -T ccflags-y += $(DISABLE_LTO) # Disable gcov profiling for VDSO code GCOV_PROFILE := n -# Workaround for bare-metal (ELF) toolchains that neglect to pass -shared -# down to collect2, resulting in silent corruption of the vDSO image. -ccflags-y += -Wl,-shared - obj-y += vdso.o extra-y += vdso.lds CPPFLAGS_vdso.lds += -P -C -U$(ARCH) @@ -33,7 +28,7 @@ $(obj)/vdso.o : $(obj)/vdso.so # Link rule for the .so file, .lds has to be first $(obj)/vdso.so.dbg: $(src)/vdso.lds $(obj-vdso) - $(call if_changed,vdsold) + $(call if_changed,ld) # Strip rule for the .so file $(obj)/%.so: OBJCOPYFLAGS := -S @@ -55,8 +50,6 @@ $(obj-vdso): %.o: %.S FORCE $(call if_changed_dep,vdsoas) # Actual build commands -quiet_cmd_vdsold = VDSOL $@ - cmd_vdsold = $(CC) $(c_flags) -Wl,-n -Wl,-T $^ -o $@ quiet_cmd_vdsoas = VDSOA $@ cmd_vdsoas = $(CC) $(a_flags) -c -o $@ $< From 8381e52b2c1b312353445c560eab60f887784f71 Mon Sep 17 00:00:00 2001 From: Laura Abbott Date: Fri, 29 May 2020 10:54:25 -0700 Subject: [PATCH 021/592] BACKPORT: arm64: vdso: Explicitly add build-id option Commit 691efbedc60d ("arm64: vdso: use $(LD) instead of $(CC) to link VDSO") switched to using LD explicitly. The --build-id option needs to be passed explicitly, similar to x86. Add this option. Fixes: 691efbedc60d ("arm64: vdso: use $(LD) instead of $(CC) to link VDSO") Reviewed-by: Masahiro Yamada Signed-off-by: Laura Abbott [will: drop redundant use of 'call ld-option' as requested by Masahiro] Signed-off-by: Will Deacon Change-Id: I4a0f5c1bb60bda682221a7ff96a783bf8731cc00 [nd: conflict due to ANDROID LTO and CFI] (cherry picked from commit 7a0a93c51799edc45ee57c6cc1679aa94f1e03d5) Bug: 153418016 Bug: 157279372 Signed-off-by: Nick Desaulniers (cherry picked from commit a9ee8bba814d956404c12b1c2e2c24cf4b710f08) --- arch/arm64/kernel/vdso/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/kernel/vdso/Makefile b/arch/arm64/kernel/vdso/Makefile index 83cf80d64add..01d6f496d1eb 100644 --- a/arch/arm64/kernel/vdso/Makefile +++ b/arch/arm64/kernel/vdso/Makefile @@ -12,8 +12,8 @@ obj-vdso := gettimeofday.o note.o sigreturn.o targets := $(obj-vdso) vdso.so vdso.so.dbg obj-vdso := $(addprefix $(obj)/, $(obj-vdso)) -ldflags-y := -shared -nostdlib -soname=linux-vdso.so.1 \ - $(call ld-option, --hash-style=sysv) -n -T +ldflags-y := -shared -nostdlib -soname=linux-vdso.so.1 --hash-style=sysv \ + --build-id -n -T ccflags-y += $(DISABLE_LTO) # Disable gcov profiling for VDSO code From 23f7a94bc9c762e80495bd69b6759fbe2c03f835 Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Thu, 4 Jun 2020 11:49:55 -0700 Subject: [PATCH 022/592] ANDROID: arm64: vdso: wrap -n in ld-option ld.lld distributed in clang-r353983c AOSP LLVM release (the final AOSP LLVM release for Android Q) did not support `-n` linker flag. It was eventually added to clang-r360593. Android OEM's may wish to still use ld.lld to link their kernels for Q. This flag was disabled for Pixel 4 in go/pag/1258086. This patch is equivalent, but rebased on upstream changes that removed cc-ldoption in favor of ld-option. For Android R, the final AOSP LLVM release, clang-r383902 has long supported `-n` for ld.lld. Change-Id: Iab41c9e1039e163113b428fc487a4a0708822faa Bug: 63740206 Bug: 157279372 Link: https://github.com/ClangBuiltLinux/linux/issues/340 Link: https://bugs.llvm.org/show_bug.cgi?id=40542 Signed-off-by: Nick Desaulniers --- arch/arm64/kernel/vdso/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/kernel/vdso/Makefile b/arch/arm64/kernel/vdso/Makefile index 01d6f496d1eb..b2c1695c4d4c 100644 --- a/arch/arm64/kernel/vdso/Makefile +++ b/arch/arm64/kernel/vdso/Makefile @@ -13,7 +13,7 @@ targets := $(obj-vdso) vdso.so vdso.so.dbg obj-vdso := $(addprefix $(obj)/, $(obj-vdso)) ldflags-y := -shared -nostdlib -soname=linux-vdso.so.1 --hash-style=sysv \ - --build-id -n -T + --build-id $(call ld-option,-n) -T ccflags-y += $(DISABLE_LTO) # Disable gcov profiling for VDSO code From de8c9c77dcbeebf64b970881ac8672112d2480a3 Mon Sep 17 00:00:00 2001 From: Jack Pham Date: Fri, 5 Jun 2020 17:52:21 -0700 Subject: [PATCH 023/592] usb: pd: Correctly handle SVDM versions When receiving an SVDM with an unsupported version, we should still send a response with the highest version we support, rather than dropping the packet outright. Also update the outgoing SVDM version field to 1 (2.0) if operating in PD3 mode. Change-Id: I0bafb619e0ac16bc45064ef699870b0c03b52b47 Signed-off-by: Jack Pham --- drivers/usb/pd/policy_engine.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c index d24adaca9524..3697d923b3c7 100644 --- a/drivers/usb/pd/policy_engine.c +++ b/drivers/usb/pd/policy_engine.c @@ -1847,10 +1847,12 @@ int usbpd_send_svdm(struct usbpd *pd, u16 svid, u8 cmd, enum usbpd_svdm_cmd_type cmd_type, int obj_pos, const u32 *vdos, int num_vdos) { - u32 svdm_hdr = SVDM_HDR(svid, 0, obj_pos, cmd_type, cmd); + u32 svdm_hdr = SVDM_HDR(svid, pd->spec_rev == USBPD_REV_30 ? 1 : 0, + obj_pos, cmd_type, cmd); - usbpd_dbg(&pd->dev, "VDM tx: svid:%x cmd:%x cmd_type:%x svdm_hdr:%x\n", - svid, cmd, cmd_type, svdm_hdr); + usbpd_dbg(&pd->dev, "VDM tx: svid:%04x ver:%d obj_pos:%d cmd:%x cmd_type:%x svdm_hdr:%x\n", + svid, pd->spec_rev == USBPD_REV_30 ? 1 : 0, obj_pos, + cmd, cmd_type, svdm_hdr); return usbpd_send_vdm(pd, svdm_hdr, vdos, num_vdos); } @@ -1880,7 +1882,7 @@ static void handle_vdm_rx(struct usbpd *pd, struct rx_msg *rx_msg) ktime_t recvd_time = ktime_get(); usbpd_dbg(&pd->dev, - "VDM rx: svid:%x cmd:%x cmd_type:%x vdm_hdr:%x has_dp: %s\n", + "VDM rx: svid:%04x cmd:%x cmd_type:%x vdm_hdr:%x has_dp: %s\n", svid, cmd, cmd_type, vdm_hdr, pd->has_dp ? "true" : "false"); @@ -1907,11 +1909,9 @@ static void handle_vdm_rx(struct usbpd *pd, struct rx_msg *rx_msg) return; } - if (SVDM_HDR_VER(vdm_hdr) > 1) { - usbpd_dbg(&pd->dev, "Discarding SVDM with incorrect version:%d\n", + if (SVDM_HDR_VER(vdm_hdr) > 1) + usbpd_dbg(&pd->dev, "Received SVDM with incorrect version:%d\n", SVDM_HDR_VER(vdm_hdr)); - return; - } if (cmd_type != SVDM_CMD_TYPE_INITIATOR && pd->current_state != PE_SRC_STARTUP_WAIT_FOR_VDM_RESP) From de9c5230a2ffe2a84b9cb39bdd73f0d1d476134f Mon Sep 17 00:00:00 2001 From: Sujin Panicker Date: Wed, 27 May 2020 11:09:04 +0530 Subject: [PATCH 024/592] asoc: add code change for proxy playback and capture BE DAIs. proxy AFE port based BE DAIs can be used for various use cases, including but not limited to voice call. Add support for BE DAI link based on pseudo ports. Change-Id: Ifb6d9c894dcaf6080040d9bcd6f364ceda17e60a Signed-off-by: Sujin Panicker --- 4.0/asoc/msm-dai-q6-v2.c | 48 +++++++++++++++++++++++++++++++++- 4.0/asoc/msm-pcm-routing-v2.c | 37 +++++++++++++++++++++++++- 4.0/asoc/msm-pcm-routing-v2.h | 6 ++++- 4.0/dsp/q6afe.c | 10 +++++++ 4.0/dsp/q6audio-v2.c | 12 ++++++++- 4.0/include/dsp/apr_audio-v2.h | 12 ++++++++- 4.0/include/dsp/q6afe-v2.h | 5 +++- 7 files changed, 124 insertions(+), 6 deletions(-) diff --git a/4.0/asoc/msm-dai-q6-v2.c b/4.0/asoc/msm-dai-q6-v2.c index bf9c4c5b597b..0ed0dae05b90 100644 --- a/4.0/asoc/msm-dai-q6-v2.c +++ b/4.0/asoc/msm-dai-q6-v2.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. */ #include @@ -2621,6 +2621,8 @@ static int msm_dai_q6_hw_params(struct snd_pcm_substream *substream, case RT_PROXY_DAI_001_RX: case RT_PROXY_DAI_002_TX: case RT_PROXY_DAI_002_RX: + case RT_PROXY_PORT_002_TX: + case RT_PROXY_PORT_002_RX: rc = msm_dai_q6_afe_rtproxy_hw_params(params, dai); break; case VOICE_PLAYBACK_TX: @@ -4247,6 +4249,42 @@ static struct snd_soc_dai_driver msm_dai_q6_incall_record_dai[] = { }, }; +static struct snd_soc_dai_driver msm_dai_q6_proxy_tx_dai = { + .capture = { + .stream_name = "Proxy Capture", + .aif_name = "PROXY_TX", + .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .channels_min = 1, + .channels_max = 2, + .rate_min = 8000, + .rate_max = 48000, + }, + .ops = &msm_dai_q6_ops, + .id = RT_PROXY_PORT_002_TX, + .probe = msm_dai_q6_dai_probe, + .remove = msm_dai_q6_dai_remove, +}; + +static struct snd_soc_dai_driver msm_dai_q6_proxy_rx_dai = { + .playback = { + .stream_name = "Proxy Playback", + .aif_name = "PROXY_RX", + .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .channels_min = 1, + .channels_max = 2, + .rate_min = 8000, + .rate_max = 48000, + }, + .ops = &msm_dai_q6_ops, + .id = RT_PROXY_PORT_002_RX, + .probe = msm_dai_q6_dai_probe, + .remove = msm_dai_q6_dai_remove, +}; + static struct snd_soc_dai_driver msm_dai_q6_usb_rx_dai = { .playback = { .stream_name = "USB Audio Playback", @@ -7288,6 +7326,14 @@ register_uplink_capture: __func__, stream_name); break; + case RT_PROXY_PORT_002_RX: + rc = snd_soc_register_component(&pdev->dev, + &msm_dai_q6_component, &msm_dai_q6_proxy_rx_dai, 1); + break; + case RT_PROXY_PORT_002_TX: + rc = snd_soc_register_component(&pdev->dev, + &msm_dai_q6_component, &msm_dai_q6_proxy_tx_dai, 1); + break; default: rc = -ENODEV; break; diff --git a/4.0/asoc/msm-pcm-routing-v2.c b/4.0/asoc/msm-pcm-routing-v2.c index efaa4ef2b623..f3b229410a19 100644 --- a/4.0/asoc/msm-pcm-routing-v2.c +++ b/4.0/asoc/msm-pcm-routing-v2.c @@ -699,6 +699,8 @@ struct msm_pcm_routing_bdai_data msm_bedais[MSM_BACKEND_DAI_MAX] = { LPASS_BE_PRI_META_MI2S_RX}, { AFE_PORT_ID_SECONDARY_META_MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0, LPASS_BE_SEC_META_MI2S_RX}, + { RT_PROXY_PORT_002_RX, 0, {0}, {0}, 0, 0, 0, 0, LPASS_BE_PROXY_RX}, + { RT_PROXY_PORT_002_TX, 0, {0}, {0}, 0, 0, 0, 0, LPASS_BE_PROXY_TX}, }; /* Track ASM playback & capture sessions of DAI @@ -3530,7 +3532,7 @@ static const char *const be_name[] = { "RX_CDC_DMA_RX_6", "RX_CDC_DMA_RX_7", "PRI_SPDIF_TX", "SEC_SPDIF_RX", "SEC_SPDIF_TX", "SLIM_9_RX", "SLIM_9_TX", "AFE_LOOPBACK_TX", "PRI_META_MI2S_RX", -"SEC_META_MI2S_RX" +"SEC_META_MI2S_RX", "PROXY_RX", "PROXY_TX" }; static SOC_ENUM_SINGLE_DECL(mm1_channel_mux, @@ -20347,6 +20349,17 @@ static const struct snd_kcontrol_new slimbus_3_rx_mixer_controls[] = { msm_routing_put_voice_mixer), }; +static const struct snd_kcontrol_new proxy_rx_voice_mixer_controls[] = { + SOC_DOUBLE_EXT("VoiceMMode1", SND_SOC_NOPM, + MSM_BACKEND_DAI_PROXY_RX, + MSM_FRONTEND_DAI_VOICEMMODE1, 1, 0, msm_routing_get_voice_mixer, + msm_routing_put_voice_mixer), + SOC_DOUBLE_EXT("VoiceMMode2", SND_SOC_NOPM, + MSM_BACKEND_DAI_PROXY_RX, + MSM_FRONTEND_DAI_VOICEMMODE2, 1, 0, msm_routing_get_voice_mixer, + msm_routing_put_voice_mixer), +}; + static const struct snd_kcontrol_new tx_voicemmode1_mixer_controls[] = { SOC_DOUBLE_EXT("PRI_TX_MMode1", SND_SOC_NOPM, MSM_BACKEND_DAI_PRI_I2S_TX, @@ -20448,6 +20461,9 @@ static const struct snd_kcontrol_new tx_voicemmode1_mixer_controls[] = { SOC_DOUBLE_EXT("PRI_TDM_TX_3_MMode1", SND_SOC_NOPM, MSM_BACKEND_DAI_PRI_TDM_TX_3, MSM_FRONTEND_DAI_VOICEMMODE1, 1, 0, msm_routing_get_voice_mixer, msm_routing_put_voice_mixer), + SOC_DOUBLE_EXT("PROXY_TX_MMode1", SND_SOC_NOPM, + MSM_BACKEND_DAI_PROXY_TX, MSM_FRONTEND_DAI_VOICEMMODE1, + 1, 0, msm_routing_get_voice_mixer, msm_routing_put_voice_mixer), }; static const struct snd_kcontrol_new tx_voicemmode2_mixer_controls[] = { @@ -20547,6 +20563,9 @@ static const struct snd_kcontrol_new tx_voicemmode2_mixer_controls[] = { SOC_DOUBLE_EXT("PRI_TDM_TX_3_MMode2", SND_SOC_NOPM, MSM_BACKEND_DAI_PRI_TDM_TX_3, MSM_FRONTEND_DAI_VOICEMMODE2, 1, 0, msm_routing_get_voice_mixer, msm_routing_put_voice_mixer), + SOC_DOUBLE_EXT("PROXY_TX_MMode2", SND_SOC_NOPM, + MSM_BACKEND_DAI_PROXY_TX, MSM_FRONTEND_DAI_VOICEMMODE2, + 1, 0, msm_routing_get_voice_mixer, msm_routing_put_voice_mixer), }; static const struct snd_kcontrol_new tx_voip_mixer_controls[] = { @@ -23764,6 +23783,8 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { SND_SOC_DAPM_AIF_IN("SLIMBUS_9_TX", "Slimbus9 Capture", 0, 0, 0, 0), SND_SOC_DAPM_AIF_OUT("USB_AUDIO_RX", "USB Audio Playback", 0, 0, 0, 0), SND_SOC_DAPM_AIF_IN("USB_AUDIO_TX", "USB Audio Capture", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_OUT("PROXY_RX", "Proxy Playback", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_IN("PROXY_TX", "Proxy Capture", 0, 0, 0, 0), /* Switch Definitions */ SND_SOC_DAPM_SWITCH("SLIMBUS_DL_HL", SND_SOC_NOPM, 0, 0, @@ -23930,6 +23951,10 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { SND_SOC_NOPM, 0, 0, wsa_cdc_dma_rx_0_voice_mixer_controls, ARRAY_SIZE(wsa_cdc_dma_rx_0_voice_mixer_controls)), + SND_SOC_DAPM_MIXER("PROXY_RX_Voice Mixer", + SND_SOC_NOPM, 0, 0, + proxy_rx_voice_mixer_controls, + ARRAY_SIZE(proxy_rx_voice_mixer_controls)), SND_SOC_DAPM_MIXER("RX_CDC_DMA_RX_0_Voice Mixer", SND_SOC_NOPM, 0, 0, rx_cdc_dma_rx_0_voice_mixer_controls, @@ -26201,6 +26226,12 @@ static const struct snd_soc_dapm_route intercon[] = { {"WSA_CDC_DMA_RX_0_Voice Mixer", "VoiceMMode2", "VOICEMMODE2_DL"}, {"WSA_CDC_DMA_RX_0", NULL, "WSA_CDC_DMA_RX_0_Voice Mixer"}, + {"PROXY_RX_Voice Mixer", "VoiceMMode1", "VOICEMMODE1_DL"}, + {"PROXY_RX", NULL, "PROXY_RX_Voice Mixer"}, + + {"PROXY_RX_Voice Mixer", "VoiceMMode2", "VOICEMMODE2_DL"}, + {"PROXY_RX", NULL, "PROXY_RX_Voice Mixer"}, + {"RX_CDC_DMA_RX_0_Voice Mixer", "Voip", "VOIP_DL"}, {"RX_CDC_DMA_RX_0_Voice Mixer", "VoiceMMode1", "VOICEMMODE1_DL"}, {"RX_CDC_DMA_RX_0_Voice Mixer", "VoiceMMode2", "VOICEMMODE2_DL"}, @@ -26258,6 +26289,7 @@ static const struct snd_soc_dapm_route intercon[] = { {"VoiceMMode1_Tx Mixer", "TX_CDC_DMA_TX_3_MMode1", "TX_CDC_DMA_TX_3"}, {"VoiceMMode1_Tx Mixer", "TX_CDC_DMA_TX_4_MMode1", "TX_CDC_DMA_TX_4"}, {"VoiceMMode1_Tx Mixer", "TX_CDC_DMA_TX_5_MMode1", "TX_CDC_DMA_TX_5"}, + {"VoiceMMode1_Tx Mixer", "PROXY_TX_MMode1", "PROXY_TX"}, {"VOICEMMODE1_UL", NULL, "VoiceMMode1_Tx Mixer"}, {"VoiceMMode2_Tx Mixer", "SLIM_0_TX_MMode2", "SLIMBUS_0_TX"}, @@ -26272,6 +26304,7 @@ static const struct snd_soc_dapm_route intercon[] = { {"VoiceMMode2_Tx Mixer", "TX_CDC_DMA_TX_3_MMode2", "TX_CDC_DMA_TX_3"}, {"VoiceMMode2_Tx Mixer", "TX_CDC_DMA_TX_4_MMode2", "TX_CDC_DMA_TX_4"}, {"VoiceMMode2_Tx Mixer", "TX_CDC_DMA_TX_5_MMode2", "TX_CDC_DMA_TX_5"}, + {"VoiceMMode2_Tx Mixer", "PROXY_TX_MMode2", "PROXY_TX"}, {"VOICEMMODE2_UL", NULL, "VoiceMMode2_Tx Mixer"}, {"Voip_Tx Mixer", "SLIM_0_TX_Voip", "SLIMBUS_0_TX"}, @@ -26578,6 +26611,7 @@ static const struct snd_soc_dapm_route intercon[] = { {"BE_OUT", NULL, "RX_CDC_DMA_RX_5"}, {"BE_OUT", NULL, "RX_CDC_DMA_RX_6"}, {"BE_OUT", NULL, "RX_CDC_DMA_RX_7"}, + {"BE_OUT", NULL, "PROXY_RX"}, {"SLIMBUS_0_TX", NULL, "BE_IN" }, {"SLIMBUS_1_TX", NULL, "BE_IN" }, @@ -26620,6 +26654,7 @@ static const struct snd_soc_dapm_route intercon[] = { {"TX_CDC_DMA_TX_5", NULL, "BE_IN"}, {"PRI_SPDIF_TX", NULL, "BE_IN"}, {"SEC_SPDIF_TX", NULL, "BE_IN"}, + {"PROXY_TX", NULL, "BE_IN"}, }; #ifndef CONFIG_AUXPCM_DISABLE diff --git a/4.0/asoc/msm-pcm-routing-v2.h b/4.0/asoc/msm-pcm-routing-v2.h index 9c74c32ffbd5..ee9c63ad89c8 100644 --- a/4.0/asoc/msm-pcm-routing-v2.h +++ b/4.0/asoc/msm-pcm-routing-v2.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0-only */ -/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. */ #ifndef _MSM_PCM_ROUTING_H #define _MSM_PCM_ROUTING_H @@ -42,6 +42,8 @@ #define LPASS_BE_VOICE2_PLAYBACK_TX "VOICE2_PLAYBACK_TX" #define LPASS_BE_INCALL_RECORD_RX "INCALL_RECORD_RX" #define LPASS_BE_INCALL_RECORD_TX "INCALL_RECORD_TX" +#define LPASS_BE_PROXY_RX "PROXY_RX" +#define LPASS_BE_PROXY_TX "PROXY_TX" #define LPASS_BE_SEC_I2S_RX "SECONDARY_I2S_RX" #define LPASS_BE_PRI_SPDIF_RX "PRI_SPDIF_RX" #define LPASS_BE_PRI_SPDIF_TX "PRI_SPDIF_TX" @@ -500,6 +502,8 @@ enum { MSM_BACKEND_DAI_AFE_LOOPBACK_TX, MSM_BACKEND_DAI_PRI_META_MI2S_RX, MSM_BACKEND_DAI_SEC_META_MI2S_RX, + MSM_BACKEND_DAI_PROXY_RX, + MSM_BACKEND_DAI_PROXY_TX, MSM_BACKEND_DAI_MAX, }; diff --git a/4.0/dsp/q6afe.c b/4.0/dsp/q6afe.c index 16d156783c53..e3d75ccc5727 100644 --- a/4.0/dsp/q6afe.c +++ b/4.0/dsp/q6afe.c @@ -988,6 +988,8 @@ int afe_sizeof_cfg_cmd(u16 port_id) break; case RT_PROXY_PORT_001_RX: case RT_PROXY_PORT_001_TX: + case RT_PROXY_PORT_002_RX: + case RT_PROXY_PORT_002_TX: ret_size = SIZEOF_CFG_CMD(afe_param_id_rt_proxy_port_cfg); break; case AFE_PORT_ID_USB_RX: @@ -4755,6 +4757,8 @@ static int __afe_port_start(u16 port_id, union afe_port_config *afe_config, break; case RT_PROXY_PORT_001_RX: case RT_PROXY_PORT_001_TX: + case RT_PROXY_PORT_002_RX: + case RT_PROXY_PORT_002_TX: cfg_type = AFE_PARAM_ID_RT_PROXY_CONFIG; break; case INT_BT_SCO_RX: @@ -5302,6 +5306,10 @@ int afe_get_port_index(u16 port_id) return IDX_AFE_PORT_ID_RX_CODEC_DMA_RX_7; case AFE_LOOPBACK_TX: return IDX_AFE_LOOPBACK_TX; + case RT_PROXY_PORT_002_RX: + return IDX_RT_PROXY_PORT_002_RX; + case RT_PROXY_PORT_002_TX: + return IDX_RT_PROXY_PORT_002_TX; default: pr_err("%s: port 0x%x\n", __func__, port_id); return -EINVAL; @@ -7499,6 +7507,8 @@ int afe_validate_port(u16 port_id) case AFE_PORT_ID_TX_CODEC_DMA_TX_5: case AFE_PORT_ID_RX_CODEC_DMA_RX_6: case AFE_PORT_ID_RX_CODEC_DMA_RX_7: + case RT_PROXY_PORT_002_RX: + case RT_PROXY_PORT_002_TX: { ret = 0; break; diff --git a/4.0/dsp/q6audio-v2.c b/4.0/dsp/q6audio-v2.c index 68b373629a18..e3a2dc7805b7 100644 --- a/4.0/dsp/q6audio-v2.c +++ b/4.0/dsp/q6audio-v2.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. */ #include @@ -385,6 +385,10 @@ int q6audio_get_port_index(u16 port_id) return IDX_AFE_PORT_ID_RX_CODEC_DMA_RX_6; case AFE_PORT_ID_RX_CODEC_DMA_RX_7: return IDX_AFE_PORT_ID_RX_CODEC_DMA_RX_7; + case RT_PROXY_PORT_002_RX: + return IDX_RT_PROXY_PORT_002_RX; + case RT_PROXY_PORT_002_TX: + return IDX_RT_PROXY_PORT_002_TX; default: return -EINVAL; } } @@ -767,6 +771,10 @@ int q6audio_get_port_id(u16 port_id) return AFE_PORT_ID_RX_CODEC_DMA_RX_6; case AFE_PORT_ID_RX_CODEC_DMA_RX_7: return AFE_PORT_ID_RX_CODEC_DMA_RX_7; + case RT_PROXY_PORT_002_RX: + return RT_PROXY_PORT_002_RX; + case RT_PROXY_PORT_002_TX: + return RT_PROXY_PORT_002_TX; default: pr_warn("%s: Invalid port_id %d\n", __func__, port_id); return -EINVAL; @@ -1196,6 +1204,8 @@ int q6audio_validate_port(u16 port_id) case AFE_PORT_ID_TX_CODEC_DMA_TX_5: case AFE_PORT_ID_RX_CODEC_DMA_RX_6: case AFE_PORT_ID_RX_CODEC_DMA_RX_7: + case RT_PROXY_PORT_002_RX: + case RT_PROXY_PORT_002_TX: { ret = 0; break; diff --git a/4.0/include/dsp/apr_audio-v2.h b/4.0/include/dsp/apr_audio-v2.h index cdc838ebb3a7..908ec649e462 100644 --- a/4.0/include/dsp/apr_audio-v2.h +++ b/4.0/include/dsp/apr_audio-v2.h @@ -1385,7 +1385,7 @@ struct adm_cmd_connect_afe_port_v5 { #define AFE_PORT_ID_SLIMBUS_RANGE_SIZE 0xA /* Size of the range of port IDs for real-time proxy ports. */ -#define AFE_PORT_ID_RT_PROXY_PORT_RANGE_SIZE 0x2 +#define AFE_PORT_ID_RT_PROXY_PORT_RANGE_SIZE 0x4 /* Size of the range of port IDs for pseudoports. */ #define AFE_PORT_ID_PSEUDOPORT_RANGE_SIZE 0x5 @@ -1664,6 +1664,16 @@ struct adm_cmd_connect_afe_port_v5 { #define AFE_PORT_ID_VOICE2_PLAYBACK_TX 0x8002 #define AFE_PORT_ID_VOICE_PLAYBACK_TX 0x8005 +/* + * Proxyport used for voice call data processing. + * In cases like call-screening feature, where user can communicate + * with caller with the help of "call screen" mode, and without + * connecting the call with any HW input/output devices in the phon, + * voice call can use Pseudo port to start voice data processing. + */ +#define RT_PROXY_PORT_002_TX 0x2003 +#define RT_PROXY_PORT_002_RX 0x2002 + #define AFE_PORT_ID_PRIMARY_TDM_RX \ (AFE_PORT_ID_TDM_PORT_RANGE_START + 0x00) #define AFE_PORT_ID_PRIMARY_TDM_RX_1 \ diff --git a/4.0/include/dsp/q6afe-v2.h b/4.0/include/dsp/q6afe-v2.h index 9e1a0b2f44fb..73a7cf872a61 100644 --- a/4.0/include/dsp/q6afe-v2.h +++ b/4.0/include/dsp/q6afe-v2.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. */ #ifndef __Q6AFE_V2_H__ #define __Q6AFE_V2_H__ @@ -284,6 +284,9 @@ enum { /* IDX 208-> 209 */ IDX_AFE_PORT_ID_PRIMARY_META_MI2S_RX, IDX_AFE_PORT_ID_SECONDARY_META_MI2S_RX, + /* IDX 210-> 211 */ + IDX_RT_PROXY_PORT_002_RX, + IDX_RT_PROXY_PORT_002_TX, AFE_MAX_PORTS }; From 68b3ceb113fa9050f4ec0b4406bcb048280c9748 Mon Sep 17 00:00:00 2001 From: Sujin Panicker Date: Tue, 26 May 2020 14:39:12 +0530 Subject: [PATCH 025/592] audio-kernel: add proxy ports for call screening in machine driver add machine driver changes for proxy port changes. Change-Id: If8e1a91e11eead094e7604e779bd46bf323efac8 Signed-off-by: Sujin Panicker --- 4.0/asoc/kona.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/4.0/asoc/kona.c b/4.0/asoc/kona.c index f9fad426847b..005a9becfa61 100644 --- a/4.0/asoc/kona.c +++ b/4.0/asoc/kona.c @@ -6224,6 +6224,33 @@ static struct snd_soc_dai_link msm_common_be_dai_links[] = { .ignore_suspend = 1, .ignore_pmdown_time = 1, }, + /* Proxy Tx BACK END DAI Link */ + { + .name = LPASS_BE_PROXY_TX, + .stream_name = "Proxy Capture", + .cpu_dai_name = "msm-dai-q6-dev.8195", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-tx", + .no_pcm = 1, + .dpcm_capture = 1, + .id = MSM_BACKEND_DAI_PROXY_TX, + .ignore_suspend = 1, + }, + /* Proxy Rx BACK END DAI Link */ + { + .name = LPASS_BE_PROXY_RX, + .stream_name = "Proxy Playback", + .cpu_dai_name = "msm-dai-q6-dev.8194", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-rx", + .no_pcm = 1, + .dpcm_playback = 1, + .id = MSM_BACKEND_DAI_PROXY_RX, + .ignore_pmdown_time = 1, + .ignore_suspend = 1, + }, { .name = LPASS_BE_USB_AUDIO_RX, .stream_name = "USB Audio Playback", From debd2a899ab9b84e1ef9ac4cb525d250a95c27ed Mon Sep 17 00:00:00 2001 From: Vatsal Bucha Date: Wed, 17 Jun 2020 08:21:11 +0530 Subject: [PATCH 026/592] ASoC: bolero: Fix higher btn press noise issue There is higher noise during headset btn press on some headsets. Change hold time after button release to 600ms to resolve the noise. Change-Id: I089550aacfe103f30900e1a68ae8442cc8f50246 Signed-off-by: Vatsal Bucha --- 4.0/asoc/codecs/bolero/tx-macro.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/4.0/asoc/codecs/bolero/tx-macro.c b/4.0/asoc/codecs/bolero/tx-macro.c index 880a6748fa0e..a90dcc16ca1b 100644 --- a/4.0/asoc/codecs/bolero/tx-macro.c +++ b/4.0/asoc/codecs/bolero/tx-macro.c @@ -2721,7 +2721,7 @@ undefined_rate: } static const struct tx_macro_reg_mask_val tx_macro_reg_init[] = { - {BOLERO_CDC_TX0_TX_PATH_SEC7, 0x3F, 0x02}, + {BOLERO_CDC_TX0_TX_PATH_SEC7, 0x3F, 0x0A}, }; static int tx_macro_init(struct snd_soc_codec *codec) { From 3a50ed281867384ff32d52ba96ae94e19d31230e Mon Sep 17 00:00:00 2001 From: Dhaval Patel Date: Fri, 12 Jun 2020 12:41:55 +0800 Subject: [PATCH 027/592] drm/msm/sde: use atomic counter for pending frame done SDE encoder uses bit mask logic to check the pending pp_done IRQ for dual dsi and trigger release fence when both IRQs are received. It causes issue when encoder triggers two frames back to back without waiting for first frame done. Bitmask clears the frame done prematurely and miss to trigger the release fence for second frame. Atomic counter usages allows to track the number of pending IRQ and release frame_done when both pp_done IRQs are received. Change-Id: I669aea124bae922641afe5d34f8f035dc5de82b3 Signed-off-by: Dhaval Patel Signed-off-by: Bruce Hoo Signed-off-by: Ray Zhang --- drivers/gpu/drm/msm/sde/sde_encoder.c | 90 +++++++++++++-------------- 1 file changed, 44 insertions(+), 46 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c index f455f24da622..e83b3063c99a 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder.c @@ -197,9 +197,8 @@ enum sde_enc_rc_states { * @debugfs_root: Debug file system root file node * @enc_lock: Lock around physical encoder create/destroy and access. - * @frame_busy_mask: Bitmask tracking which phys_enc we are still - * busy processing current command. - * Bit0 = phys_encs[0] etc. + * @frame_done_cnt: Atomic counter for tracking which phy_enc is + * done with frame processing. * @crtc_frame_event_cb: callback handler for frame event * @crtc_frame_event_cb_data: callback handler private data * @vsync_event_timer: vsync timer @@ -260,7 +259,7 @@ struct sde_encoder_virt { struct dentry *debugfs_root; struct mutex enc_lock; - DECLARE_BITMAP(frame_busy_mask, MAX_PHYS_ENCODERS_PER_VIRTUAL); + atomic_t frame_done_cnt[MAX_PHYS_ENCODERS_PER_VIRTUAL]; void (*crtc_frame_event_cb)(void *, u32 event); struct sde_crtc_frame_event_cb_data crtc_frame_event_cb_data; @@ -2448,6 +2447,16 @@ static int sde_encoder_resource_control(struct drm_encoder *drm_enc, return -EINVAL; } + /* + * schedule off work item only when there are no + * frames pending + */ + if (sde_crtc_frame_pending(sde_enc->crtc) > 1) { + SDE_DEBUG_ENC(sde_enc, "skip schedule work"); + SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state, + SDE_EVTLOG_FUNC_CASE2); + return 0; + } if (sde_enc->crtc->index >= ARRAY_SIZE(priv->disp_thread)) { SDE_ERROR("invalid crtc index :%u\n", sde_enc->crtc->index); @@ -2469,17 +2478,6 @@ static int sde_encoder_resource_control(struct drm_encoder *drm_enc, return -EINVAL; } - /* - * schedule off work item only when there are no - * frames pending - */ - if (sde_crtc_frame_pending(sde_enc->crtc) > 1) { - SDE_DEBUG_ENC(sde_enc, "skip schedule work"); - SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state, - SDE_EVTLOG_FUNC_CASE2); - return 0; - } - /* schedule delayed off work if autorefresh is disabled */ if (sde_enc->cur_master && sde_enc->cur_master->ops.is_autorefresh_enabled) @@ -2692,17 +2690,10 @@ static int sde_encoder_resource_control(struct drm_encoder *drm_enc, SDE_EVTLOG_ERROR); mutex_unlock(&sde_enc->rc_lock); return 0; - } - - /* - * if we are in ON but a frame was just kicked off, - * ignore the IDLE event, it's probably a stale timer event - */ - if (sde_enc->frame_busy_mask[0]) { - SDE_ERROR_ENC(sde_enc, - "sw_event:%d, rc:%d frame pending\n", - sw_event, sde_enc->rc_state); + } else if (sde_crtc_frame_pending(sde_enc->crtc) > 1) { + SDE_DEBUG_ENC(sde_enc, "skip idle entry"); SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state, + sde_crtc_frame_pending(sde_enc->crtc), SDE_EVTLOG_ERROR); mutex_unlock(&sde_enc->rc_lock); return 0; @@ -3663,6 +3654,8 @@ static void sde_encoder_frame_done_callback( { struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc); unsigned int i; + bool trigger = true; + enum sde_rm_topology_name topology = SDE_RM_TOPOLOGY_NONE; if (!drm_enc || !sde_enc->cur_master) { SDE_ERROR("invalid param: drm_enc %lx, cur_master %lx\n", @@ -3677,26 +3670,35 @@ static void sde_encoder_frame_done_callback( if (event & (SDE_ENCODER_FRAME_EVENT_DONE | SDE_ENCODER_FRAME_EVENT_ERROR | SDE_ENCODER_FRAME_EVENT_PANEL_DEAD)) { - - if (!sde_enc->frame_busy_mask[0]) { - /** - * suppress frame_done without waiter, - * likely autorefresh - */ - SDE_EVT32(DRMID(drm_enc), event, ready_phys->intf_idx); - return; - } + if (ready_phys->connector) + topology = sde_connector_get_topology_name( + ready_phys->connector); /* One of the physical encoders has become idle */ for (i = 0; i < sde_enc->num_phys_encs; i++) { - if (sde_enc->phys_encs[i] == ready_phys) { - clear_bit(i, sde_enc->frame_busy_mask); + if ((sde_enc->phys_encs[i] == ready_phys) || + (event & SDE_ENCODER_FRAME_EVENT_ERROR)) { SDE_EVT32_VERBOSE(DRMID(drm_enc), i, - sde_enc->frame_busy_mask[0]); + atomic_read( + &sde_enc->frame_done_cnt[i])); + if (!atomic_add_unless( + &sde_enc->frame_done_cnt[i], 1, 1)) { + SDE_EVT32(DRMID(drm_enc), event, + ready_phys->intf_idx, + SDE_EVTLOG_ERROR); + SDE_ERROR_ENC(sde_enc, + "intf idx:%d, event:%d\n", + ready_phys->intf_idx, event); + return; + } } + + if (topology != SDE_RM_TOPOLOGY_PPSPLIT && + atomic_read(&sde_enc->frame_done_cnt[i]) != 1) + trigger = false; } - if (!sde_enc->frame_busy_mask[0]) { + if (trigger) { sde_encoder_resource_control(drm_enc, SDE_ENC_RC_EVENT_FRAME_DONE); @@ -3704,6 +3706,8 @@ static void sde_encoder_frame_done_callback( sde_enc->crtc_frame_event_cb( &sde_enc->crtc_frame_event_cb_data, event); + for (i = 0; i < sde_enc->num_phys_encs; i++) + atomic_set(&sde_enc->frame_done_cnt[i], 0); } } else { if (sde_enc->crtc_frame_event_cb) @@ -4015,14 +4019,6 @@ static void _sde_encoder_kickoff_phys(struct sde_encoder_virt *sde_enc) if (phys->connector) topology = sde_connector_get_topology_name( phys->connector); - /* - * don't wait on ppsplit slaves or skipped encoders because - * they dont receive irqs - */ - if (!(topology == SDE_RM_TOPOLOGY_PPSPLIT && - phys->split_role == ENC_ROLE_SLAVE) && - phys->split_role != ENC_ROLE_SKIP) - set_bit(i, sde_enc->frame_busy_mask); if (!phys->ops.needs_single_flush || !phys->ops.needs_single_flush(phys)) { @@ -5487,6 +5483,8 @@ struct drm_encoder *sde_encoder_init_with_ops( sde_enc->cur_master = NULL; spin_lock_init(&sde_enc->enc_spinlock); mutex_init(&sde_enc->vblank_ctl_lock); + for (i = 0; i < MAX_PHYS_ENCODERS_PER_VIRTUAL; i++) + atomic_set(&sde_enc->frame_done_cnt[i], 0); drm_enc = &sde_enc->base; drm_encoder_init(dev, drm_enc, &sde_encoder_funcs, drm_enc_mode, NULL); drm_encoder_helper_add(drm_enc, &sde_encoder_helper_funcs); From 8e94c21b1d0acd8ab386edefdee299e960d02b86 Mon Sep 17 00:00:00 2001 From: Dhaval Patel Date: Fri, 12 Jun 2020 16:54:36 +0800 Subject: [PATCH 028/592] drm/msm/sde: support posted frame trigger for cmd mode Support posted frame trigger for command mode panel with queue depth 1. It allows panel vsync time for frame transfer duration and reduces the MDP clock and BW requirement. The change also support debugfs entry support to select the cmd mode frame done wait between serialize trigger, posted trigger and default behavior. Change-Id: I84134a6458665c40e94aa29805e528caa2d91a93 Signed-off-by: Dhaval Patel Signed-off-by: Bruce Hoo Signed-off-by: Ray Zhang --- drivers/gpu/drm/msm/sde/sde_encoder.c | 7 ++ drivers/gpu/drm/msm/sde/sde_encoder.h | 3 +- drivers/gpu/drm/msm/sde/sde_encoder_phys.h | 8 +- .../gpu/drm/msm/sde/sde_encoder_phys_cmd.c | 86 +++++++++++-------- drivers/gpu/drm/msm/sde/sde_kms.h | 16 +++- 5 files changed, 79 insertions(+), 41 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c index e83b3063c99a..f1d288ef7da8 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder.c @@ -221,6 +221,8 @@ enum sde_enc_rc_states { * @topology: topology of the display * @vblank_enabled: boolean to track userspace vblank vote * @idle_pc_restore: flag to indicate idle_pc_restore happened + * @frame_trigger_mode: frame trigger mode indication for command + * mode display * @rsc_config: rsc configuration for display vtotal, fps, etc. * @cur_conn_roi: current connector roi * @prv_conn_roi: previous connector roi to optimize if unchanged @@ -283,6 +285,7 @@ struct sde_encoder_virt { struct msm_display_topology topology; bool vblank_enabled; bool idle_pc_restore; + enum frame_trigger_mode_type frame_trigger_mode; struct sde_rsc_cmd_config rsc_config; struct sde_rect cur_conn_roi; @@ -3316,6 +3319,7 @@ static void sde_encoder_virt_enable(struct drm_encoder *drm_enc) phys->comp_type = comp_info->comp_type; phys->comp_ratio = comp_info->comp_ratio; phys->wide_bus_en = mode_info.wide_bus_en; + phys->frame_trigger_mode = sde_enc->frame_trigger_mode; if (phys->comp_type == MSM_DISPLAY_COMPRESSION_DSC) { phys->dsc_extra_pclk_cycle_cnt = @@ -5152,6 +5156,9 @@ static int _sde_encoder_init_debugfs(struct drm_encoder *drm_enc) debugfs_create_bool("idle_power_collapse", 0600, sde_enc->debugfs_root, &sde_enc->idle_pc_enabled); + debugfs_create_u32("frame_trigger_mode", 0600, sde_enc->debugfs_root, + &sde_enc->frame_trigger_mode); + for (i = 0; i < sde_enc->num_phys_encs; i++) if (sde_enc->phys_encs[i] && sde_enc->phys_encs[i]->ops.late_register) diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.h b/drivers/gpu/drm/msm/sde/sde_encoder.h index 74639846af3b..7fa700e2910a 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder.h +++ b/drivers/gpu/drm/msm/sde/sde_encoder.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark * @@ -23,6 +23,7 @@ #include "msm_prop.h" #include "sde_hw_mdss.h" +#include "sde_kms.h" #define SDE_ENCODER_FRAME_EVENT_DONE BIT(0) #define SDE_ENCODER_FRAME_EVENT_ERROR BIT(1) diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h index 1fe0075d03d3..841ffb9f7407 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2020 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -296,6 +296,8 @@ struct sde_encoder_irq { * @in_clone_mode Indicates if encoder is in clone mode ref@CWB * @vfp_cached: cached vertical front porch to be used for * programming ROT and MDP fetch start + * @frame_trigger_mode: frame trigger mode indication for command + * mode display */ struct sde_encoder_phys { struct drm_encoder *parent; @@ -339,6 +341,7 @@ struct sde_encoder_phys { bool cont_splash_enabled; bool in_clone_mode; int vfp_cached; + enum frame_trigger_mode_type frame_trigger_mode; }; static inline int sde_encoder_phys_inc_pending(struct sde_encoder_phys *phys) @@ -382,8 +385,6 @@ struct sde_encoder_phys_cmd_autorefresh { * @base: Baseclass physical encoder structure * @intf_idx: Intf Block index used by this phys encoder * @stream_sel: Stream selection for multi-stream interfaces - * @serialize_wait4pp: serialize wait4pp feature waits for pp_done interrupt - * after ctl_start instead of before next frame kickoff * @pp_timeout_report_cnt: number of pingpong done irq timeout errors * @autorefresh: autorefresh feature state * @pending_rd_ptr_cnt: atomic counter to indicate if retire fence can be @@ -397,7 +398,6 @@ struct sde_encoder_phys_cmd_autorefresh { struct sde_encoder_phys_cmd { struct sde_encoder_phys base; int stream_sel; - bool serialize_wait4pp; int pp_timeout_report_cnt; struct sde_encoder_phys_cmd_autorefresh autorefresh; atomic_t pending_rd_ptr_cnt; diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c index c6f5b15c70b4..8fd37447bb8c 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2020 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -199,24 +199,6 @@ static void sde_encoder_phys_cmd_pp_tx_done_irq(void *arg, int irq_idx) SDE_ATRACE_BEGIN("pp_done_irq"); - /* handle rare cases where the ctl_start_irq is not received */ - if (sde_encoder_phys_cmd_is_master(phys_enc)) { - /* - * Reduce the refcount for the retire fence as well - * as for the ctl_start if the counters are greater - * than zero. If there was a retire fence count pending, - * then signal the RETIRE FENCE here. - */ - if (atomic_add_unless(&phys_enc->pending_retire_fence_cnt, - -1, 0)) - phys_enc->parent_ops.handle_frame_done( - phys_enc->parent, - phys_enc, - SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE); - atomic_add_unless(&phys_enc->pending_ctlstart_cnt, -1, 0); - atomic_set(&phys_enc->ctlstart_timeout, 0); - } - /* notify all synchronous clients first, then asynchronous clients */ if (phys_enc->parent_ops.handle_frame_done) phys_enc->parent_ops.handle_frame_done(phys_enc->parent, @@ -229,6 +211,23 @@ static void sde_encoder_phys_cmd_pp_tx_done_irq(void *arg, int irq_idx) SDE_EVT32_IRQ(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0, new_cnt, event); + /* + * Reduce the refcount for the retire fence as well as for the ctl_start + * if the counters are greater than zero. Signal retire fence if there + * was a retire fence count pending and kickoff count is zero. + */ + if (sde_encoder_phys_cmd_is_master(phys_enc) && (new_cnt == 0)) { + while (atomic_add_unless(&phys_enc->pending_retire_fence_cnt, + -1, 0)) { + if (phys_enc->parent_ops.handle_frame_done) + phys_enc->parent_ops.handle_frame_done( + phys_enc->parent, phys_enc, + SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE); + atomic_add_unless(&phys_enc->pending_ctlstart_cnt, + -1, 0); + } + } + /* Signal any waiting atomic commit thread */ wake_up_all(&phys_enc->pending_kickoff_wq); SDE_ATRACE_END("pp_done_irq"); @@ -545,6 +544,10 @@ static int _sde_encoder_phys_cmd_handle_ppdone_timeout( conn = phys_enc->connector; sde_conn = to_sde_connector(conn); + + if (atomic_read(&phys_enc->pending_kickoff_cnt) == 0) + return 0; + cmd_enc->pp_timeout_report_cnt++; pending_kickoff_cnt = atomic_read(&phys_enc->pending_kickoff_cnt); @@ -744,7 +747,7 @@ static int _sde_encoder_phys_cmd_wait_for_idle( to_sde_encoder_phys_cmd(phys_enc); struct sde_encoder_wait_info wait_info; bool recovery_events; - int ret; + int ret, i, pending_cnt; if (!phys_enc) { SDE_ERROR("invalid encoder\n"); @@ -764,7 +767,9 @@ static int _sde_encoder_phys_cmd_wait_for_idle( ret = sde_encoder_helper_wait_for_irq(phys_enc, INTR_IDX_PINGPONG, &wait_info); if (ret == -ETIMEDOUT) { - _sde_encoder_phys_cmd_handle_ppdone_timeout(phys_enc, + pending_cnt = atomic_read(&phys_enc->pending_kickoff_cnt); + for (i = 0; i < pending_cnt; i++) + _sde_encoder_phys_cmd_handle_ppdone_timeout(phys_enc, recovery_events); } else if (!ret) { if (cmd_enc->pp_timeout_report_cnt && recovery_events) { @@ -1360,7 +1365,7 @@ static int sde_encoder_phys_cmd_prepare_for_kickoff( struct sde_hw_tear_check tc_cfg = {0}; struct sde_encoder_phys_cmd *cmd_enc = to_sde_encoder_phys_cmd(phys_enc); - int ret; + int ret = 0; u32 extra_frame_trigger_time; if (!phys_enc || !phys_enc->hw_pp) { @@ -1373,17 +1378,19 @@ static int sde_encoder_phys_cmd_prepare_for_kickoff( atomic_read(&phys_enc->pending_kickoff_cnt), atomic_read(&cmd_enc->autorefresh.kickoff_cnt)); - /* - * Mark kickoff request as outstanding. If there are more than one, - * outstanding, then we have to wait for the previous one to complete - */ - ret = _sde_encoder_phys_cmd_wait_for_idle(phys_enc); - if (ret) { - /* force pending_kickoff_cnt 0 to discard failed kickoff */ - atomic_set(&phys_enc->pending_kickoff_cnt, 0); - SDE_EVT32(DRMID(phys_enc->parent), + if (phys_enc->frame_trigger_mode == FRAME_DONE_WAIT_DEFAULT) { + /* + * Mark kickoff request as outstanding. If there are more than + * one outstanding frame, then we have to wait for the previous + * frame to complete + */ + ret = _sde_encoder_phys_cmd_wait_for_idle(phys_enc); + if (ret) { + atomic_set(&phys_enc->pending_kickoff_cnt, 0); + SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0); - SDE_ERROR("failed wait_for_idle: %d\n", ret); + SDE_ERROR("failed wait_for_idle: %d\n", ret); + } } if (sde_connector_is_qsync_updated(phys_enc->connector)) { @@ -1511,9 +1518,18 @@ static int sde_encoder_phys_cmd_wait_for_commit_done( cmd_enc->autorefresh.cfg.enable) rc = _sde_encoder_phys_cmd_wait_for_autorefresh_done(phys_enc); - /* required for both controllers */ - if (!rc && cmd_enc->serialize_wait4pp) - sde_encoder_phys_cmd_prepare_for_kickoff(phys_enc, NULL); + /* wait for posted start or serialize trigger */ + if ((atomic_read(&phys_enc->pending_kickoff_cnt) > 1) || + (!rc && phys_enc->frame_trigger_mode == + FRAME_DONE_WAIT_SERIALIZE)) { + rc = _sde_encoder_phys_cmd_wait_for_idle(phys_enc); + if (rc) { + atomic_set(&phys_enc->pending_kickoff_cnt, 0); + SDE_EVT32(DRMID(phys_enc->parent), + phys_enc->hw_pp->idx - PINGPONG_0); + SDE_ERROR("failed wait_for_idle: %d\n", rc); + } + } return rc; } diff --git a/drivers/gpu/drm/msm/sde/sde_kms.h b/drivers/gpu/drm/msm/sde/sde_kms.h index 1001bc1a48be..d11393fa8890 100644 --- a/drivers/gpu/drm/msm/sde/sde_kms.h +++ b/drivers/gpu/drm/msm/sde/sde_kms.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark * @@ -169,6 +169,20 @@ enum sde_kms_sui_misr_state { SUI_MISR_DISABLE_REQ }; +/* + * @FRAME_DONE_WAIT_DEFAULT: waits for frame N pp_done interrupt before + * triggering frame N+1. + * @FRAME_DONE_WAIT_SERIALIZE: serialize pp_done and ctl_start irq for frame + * N without next frame trigger wait. + * @FRAME_DONE_WAIT_POSTED_START: Do not wait for pp_done interrupt for any + * frame. Wait will trigger only for error case. + */ +enum frame_trigger_mode_type { + FRAME_DONE_WAIT_DEFAULT, + FRAME_DONE_WAIT_SERIALIZE, + FRAME_DONE_WAIT_POSTED_START, +}; + /** * struct sde_kms_smmu_state_data: stores the smmu state and transition type * @state: current state of smmu context banks From 6773daeb3dc897a8c039d0093a7ec52ed3bbebb9 Mon Sep 17 00:00:00 2001 From: Dhaval Patel Date: Fri, 12 Jun 2020 17:23:21 +0800 Subject: [PATCH 029/592] drm/msm/sde: delay reset frame by a frame for posted trigger Posted frame trigger method triggers the frame without checking for frame done for previous frame. However, it waits for current frame trigger. It should iniatiate the recovery sequence only if current frame trigger fails. Change-Id: I3eac35ba722ac01a57504e78c628e82b3dcfb526 Signed-off-by: Dhaval Patel Signed-off-by: Bruce Hoo Signed-off-by: Ray Zhang --- drivers/gpu/drm/msm/sde/sde_crtc.c | 18 ++++++++--------- drivers/gpu/drm/msm/sde/sde_crtc.h | 28 ++++++++++++++++++++++++++- drivers/gpu/drm/msm/sde/sde_encoder.c | 3 +++ drivers/gpu/drm/msm/sde/sde_encoder.h | 2 ++ drivers/gpu/drm/msm/sde/sde_kms.c | 1 + 5 files changed, 42 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c index 663cb76b0c79..035eed949d2e 100644 --- a/drivers/gpu/drm/msm/sde/sde_crtc.c +++ b/drivers/gpu/drm/msm/sde/sde_crtc.c @@ -4094,14 +4094,13 @@ static void _sde_crtc_remove_pipe_flush(struct drm_crtc *crtc) } /** - * _sde_crtc_reset_hw - attempt hardware reset on errors + * sde_crtc_reset_hw - attempt hardware reset on errors * @crtc: Pointer to DRM crtc instance * @old_state: Pointer to crtc state for previous commit * @recovery_events: Whether or not recovery events are enabled * Returns: Zero if current commit should still be attempted */ -static int _sde_crtc_reset_hw(struct drm_crtc *crtc, - struct drm_crtc_state *old_state, +int sde_crtc_reset_hw(struct drm_crtc *crtc, struct drm_crtc_state *old_state, bool recovery_events) { struct drm_plane *plane_halt[MAX_PLANES]; @@ -4299,9 +4298,10 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc, struct msm_drm_private *priv; struct sde_kms *sde_kms; struct sde_crtc_state *cstate; - bool is_error, reset_req, recovery_events; + bool is_error, reset_req; unsigned long flags; enum sde_crtc_idle_pc_state idle_pc_state; + struct sde_encoder_kickoff_params params = { 0 }; if (!crtc) { SDE_ERROR("invalid argument\n"); @@ -4335,7 +4335,6 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc, idle_pc_state = sde_crtc_get_property(cstate, CRTC_PROP_IDLE_PC_STATE); list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { - struct sde_encoder_kickoff_params params = { 0 }; if (encoder->crtc != crtc) continue; @@ -4350,9 +4349,6 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc, if (sde_encoder_prepare_for_kickoff(encoder, ¶ms)) reset_req = true; - recovery_events = - sde_encoder_recovery_events_enabled(encoder); - if (idle_pc_state != IDLE_PC_NONE) sde_encoder_control_idle_pc(encoder, (idle_pc_state == IDLE_PC_ENABLE) ? true : false); @@ -4363,7 +4359,11 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc, * preparing for the kickoff */ if (reset_req) { - if (_sde_crtc_reset_hw(crtc, old_state, recovery_events)) + sde_crtc->frame_trigger_mode = params.frame_trigger_mode; + if (sde_crtc->frame_trigger_mode + != FRAME_DONE_WAIT_POSTED_START && + sde_crtc_reset_hw(crtc, old_state, + params.recovery_events_enabled)) is_error = true; } diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.h b/drivers/gpu/drm/msm/sde/sde_crtc.h index aea5290c0538..d3d875f08492 100644 --- a/drivers/gpu/drm/msm/sde/sde_crtc.h +++ b/drivers/gpu/drm/msm/sde/sde_crtc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2020 The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark * @@ -227,6 +227,7 @@ struct sde_crtc_fps_info { * @rp_lock : serialization lock for resource pool * @rp_head : list of active resource pool * @plane_mask_old: keeps track of the planes used in the previous commit + * @frame_trigger_mode: frame trigger mode */ struct sde_crtc { struct drm_crtc base; @@ -305,6 +306,7 @@ struct sde_crtc { /* blob for histogram data */ struct drm_property_blob *hist_blob; + enum frame_trigger_mode_type frame_trigger_mode; }; #define to_sde_crtc(x) container_of(x, struct sde_crtc, base) @@ -542,6 +544,30 @@ static inline int sde_crtc_frame_pending(struct drm_crtc *crtc) return atomic_read(&sde_crtc->frame_pending); } +/** + * sde_crtc_reset_hw - attempt hardware reset on errors + * @crtc: Pointer to DRM crtc instance + * @old_state: Pointer to crtc state for previous commit + * @recovery_events: Whether or not recovery events are enabled + * Returns: Zero if current commit should still be attempted + */ +int sde_crtc_reset_hw(struct drm_crtc *crtc, struct drm_crtc_state *old_state, + bool recovery_events); + +/** + * sde_crtc_request_frame_reset - requests for next frame reset + * @crtc: Pointer to drm crtc object + */ +static inline int sde_crtc_request_frame_reset(struct drm_crtc *crtc) +{ + struct sde_crtc *sde_crtc = to_sde_crtc(crtc); + + if (sde_crtc->frame_trigger_mode == FRAME_DONE_WAIT_POSTED_START) + sde_crtc_reset_hw(crtc, crtc->state, false); + + return 0; +} + /** * sde_crtc_vblank - enable or disable vblanks for this crtc * @crtc: Pointer to drm crtc object diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c index f1d288ef7da8..402e52e118a8 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder.c @@ -4683,6 +4683,9 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, for (i = 0; i < sde_enc->num_phys_encs; i++) { phys = sde_enc->phys_encs[i]; params->is_primary = sde_enc->disp_info.is_primary; + params->frame_trigger_mode = sde_enc->frame_trigger_mode; + params->recovery_events_enabled = + sde_enc->recovery_events_enabled; if (phys) { if (phys->ops.prepare_for_kickoff) { rc = phys->ops.prepare_for_kickoff( diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.h b/drivers/gpu/drm/msm/sde/sde_encoder.h index 7fa700e2910a..69b3ad28bb01 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder.h +++ b/drivers/gpu/drm/msm/sde/sde_encoder.h @@ -60,12 +60,14 @@ struct sde_encoder_hw_resources { * @affected_displays: bitmask, bit set means the ROI of the commit lies within * the bounds of the physical display at the bit index * @recovery_events_enabled: indicates status of client for recoovery events + * @frame_trigger_mode: indicates frame trigger mode */ struct sde_encoder_kickoff_params { u32 inline_rotate_prefill; u32 is_primary; unsigned long affected_displays; bool recovery_events_enabled; + enum frame_trigger_mode_type frame_trigger_mode; }; /** diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c index 9da771981d2e..3dc379caa327 100644 --- a/drivers/gpu/drm/msm/sde/sde_kms.c +++ b/drivers/gpu/drm/msm/sde/sde_kms.c @@ -1220,6 +1220,7 @@ static void sde_kms_wait_for_commit_done(struct msm_kms *kms, ret = sde_encoder_wait_for_event(encoder, MSM_ENC_COMMIT_DONE); if (ret && ret != -EWOULDBLOCK) { SDE_ERROR("wait for commit done returned %d\n", ret); + sde_crtc_request_frame_reset(crtc); break; } From ae77a32db2f69461c9ef04fa94370128cb6b65ee Mon Sep 17 00:00:00 2001 From: Dhaval Patel Date: Fri, 12 Jun 2020 17:38:48 +0800 Subject: [PATCH 030/592] drm/msm/sde: add connector property for frame trigger mode Add connector property for frame trigger mode. Change-Id: I6d193032b49c3a230b3e9a4897a9822540af61a2 Signed-off-by: Dhaval Patel Signed-off-by: Bruce Hoo Signed-off-by: Ray Zhang --- drivers/gpu/drm/msm/msm_drv.h | 3 +- drivers/gpu/drm/msm/sde/sde_connector.c | 243 +++++++++++++----------- drivers/gpu/drm/msm/sde/sde_encoder.c | 54 +++--- 3 files changed, 166 insertions(+), 134 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 4862ba8e5b06..b415efd4ef6b 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark * @@ -199,6 +199,7 @@ enum msm_mdp_conn_property { CONNECTOR_PROP_LP, CONNECTOR_PROP_FB_TRANSLATION_MODE, CONNECTOR_PROP_QSYNC_MODE, + CONNECTOR_PROP_CMD_FRAME_TRIGGER_MODE, /* total # of properties */ CONNECTOR_PROP_COUNT diff --git a/drivers/gpu/drm/msm/sde/sde_connector.c b/drivers/gpu/drm/msm/sde/sde_connector.c index b268ac780ff6..2cddea4605b1 100644 --- a/drivers/gpu/drm/msm/sde/sde_connector.c +++ b/drivers/gpu/drm/msm/sde/sde_connector.c @@ -64,6 +64,12 @@ static const struct drm_prop_enum_list e_qsync_mode[] = { {SDE_RM_QSYNC_ONE_SHOT_MODE, "one_shot"}, }; +static const struct drm_prop_enum_list e_frame_trigger_mode[] = { + {FRAME_DONE_WAIT_DEFAULT, "default"}, + {FRAME_DONE_WAIT_SERIALIZE, "serialize_frame_trigger"}, + {FRAME_DONE_WAIT_POSTED_START, "posted_start"}, +}; + static int sde_backlight_device_update_status(struct backlight_device *bd) { int brightness; @@ -1204,6 +1210,12 @@ static int sde_connector_atomic_set_property(struct drm_connector *connector, c_conn->bl_scale_ad = val; c_conn->bl_scale_dirty = true; break; + case CONNECTOR_PROP_HDR_METADATA: + rc = _sde_connector_set_ext_hdr_info(c_conn, + c_state, (void __user *)(uintptr_t)val); + if (rc) + SDE_ERROR_CONN(c_conn, "cannot set hdr info %d\n", rc); + break; case CONNECTOR_PROP_QSYNC_MODE: msm_property_set_dirty(&c_conn->property_info, &c_state->property_state, idx); @@ -1212,13 +1224,6 @@ static int sde_connector_atomic_set_property(struct drm_connector *connector, break; } - if (idx == CONNECTOR_PROP_HDR_METADATA) { - rc = _sde_connector_set_ext_hdr_info(c_conn, - c_state, (void *)(uintptr_t)val); - if (rc) - SDE_ERROR_CONN(c_conn, "cannot set hdr info %d\n", rc); - } - /* check for custom property handling */ if (!rc && c_conn->ops.set_property) { rc = c_conn->ops.set_property(connector, @@ -2125,6 +2130,122 @@ exit: return rc; } +static int _sde_connector_install_properties(struct drm_device *dev, + struct sde_kms *sde_kms, struct sde_connector *c_conn, + int connector_type, void *display, + struct msm_display_info *display_info) +{ + struct dsi_display *dsi_display; + int rc; + + msm_property_install_blob(&c_conn->property_info, "capabilities", + DRM_MODE_PROP_IMMUTABLE, CONNECTOR_PROP_SDE_INFO); + + rc = sde_connector_set_blob_data(&c_conn->base, + NULL, CONNECTOR_PROP_SDE_INFO); + if (rc) { + SDE_ERROR_CONN(c_conn, + "failed to setup connector info, rc = %d\n", rc); + return rc; + } + + msm_property_install_blob(&c_conn->property_info, "mode_properties", + DRM_MODE_PROP_IMMUTABLE, CONNECTOR_PROP_MODE_INFO); + + if (connector_type == DRM_MODE_CONNECTOR_DSI) { + dsi_display = (struct dsi_display *)(display); + if (dsi_display && dsi_display->panel && + dsi_display->panel->hdr_props.hdr_enabled == true) { + msm_property_install_blob(&c_conn->property_info, + "hdr_properties", + DRM_MODE_PROP_IMMUTABLE, + CONNECTOR_PROP_HDR_INFO); + + msm_property_set_blob(&c_conn->property_info, + &c_conn->blob_hdr, + &dsi_display->panel->hdr_props, + sizeof(dsi_display->panel->hdr_props), + CONNECTOR_PROP_HDR_INFO); + } + } + + msm_property_install_volatile_range( + &c_conn->property_info, "sde_drm_roi_v1", 0x0, + 0, ~0, 0, CONNECTOR_PROP_ROI_V1); + + /* install PP_DITHER properties */ + _sde_connector_install_dither_property(dev, sde_kms, c_conn); + + if (connector_type == DRM_MODE_CONNECTOR_DisplayPort) { + struct drm_msm_ext_hdr_properties hdr = {0}; + + msm_property_install_blob(&c_conn->property_info, + "ext_hdr_properties", + DRM_MODE_PROP_IMMUTABLE, + CONNECTOR_PROP_EXT_HDR_INFO); + + /* set default values to avoid reading uninitialized data */ + msm_property_set_blob(&c_conn->property_info, + &c_conn->blob_ext_hdr, + &hdr, + sizeof(hdr), + CONNECTOR_PROP_EXT_HDR_INFO); + } + + msm_property_install_volatile_range(&c_conn->property_info, + "hdr_metadata", 0x0, 0, ~0, 0, CONNECTOR_PROP_HDR_METADATA); + + msm_property_install_volatile_range(&c_conn->property_info, + "RETIRE_FENCE", 0x0, 0, ~0, 0, CONNECTOR_PROP_RETIRE_FENCE); + + msm_property_install_range(&c_conn->property_info, "autorefresh", + 0x0, 0, AUTOREFRESH_MAX_FRAME_CNT, 0, + CONNECTOR_PROP_AUTOREFRESH); + + if (connector_type == DRM_MODE_CONNECTOR_DSI) { + if (sde_kms->catalog->has_qsync && display_info->qsync_min_fps) + msm_property_install_enum(&c_conn->property_info, + "qsync_mode", 0, 0, e_qsync_mode, + ARRAY_SIZE(e_qsync_mode), + CONNECTOR_PROP_QSYNC_MODE); + + if (display_info->capabilities & MSM_DISPLAY_CAP_CMD_MODE) + msm_property_install_enum(&c_conn->property_info, + "frame_trigger_mode", 0, 0, + e_frame_trigger_mode, + ARRAY_SIZE(e_frame_trigger_mode), + CONNECTOR_PROP_CMD_FRAME_TRIGGER_MODE); + } + + msm_property_install_range(&c_conn->property_info, "bl_scale", + 0x0, 0, MAX_BL_SCALE_LEVEL, MAX_BL_SCALE_LEVEL, + CONNECTOR_PROP_BL_SCALE); + + msm_property_install_range(&c_conn->property_info, "ad_bl_scale", + 0x0, 0, MAX_AD_BL_SCALE_LEVEL, MAX_AD_BL_SCALE_LEVEL, + CONNECTOR_PROP_AD_BL_SCALE); + + c_conn->bl_scale_dirty = false; + c_conn->bl_scale = MAX_BL_SCALE_LEVEL; + c_conn->bl_scale_ad = MAX_AD_BL_SCALE_LEVEL; + + /* enum/bitmask properties */ + msm_property_install_enum(&c_conn->property_info, "topology_name", + DRM_MODE_PROP_IMMUTABLE, 0, e_topology_name, + ARRAY_SIZE(e_topology_name), + CONNECTOR_PROP_TOPOLOGY_NAME); + msm_property_install_enum(&c_conn->property_info, "topology_control", + 0, 1, e_topology_control, + ARRAY_SIZE(e_topology_control), + CONNECTOR_PROP_TOPOLOGY_CONTROL); + msm_property_install_enum(&c_conn->property_info, "LP", + 0, 0, e_power_mode, + ARRAY_SIZE(e_power_mode), + CONNECTOR_PROP_LP); + + return 0; +} + struct drm_connector *sde_connector_init(struct drm_device *dev, struct drm_encoder *encoder, struct drm_panel *panel, @@ -2136,7 +2257,6 @@ struct drm_connector *sde_connector_init(struct drm_device *dev, struct msm_drm_private *priv; struct sde_kms *sde_kms; struct sde_connector *c_conn = NULL; - struct dsi_display *dsi_display; struct msm_display_info display_info; int rc; @@ -2244,42 +2364,6 @@ struct drm_connector *sde_connector_init(struct drm_device *dev, } } - msm_property_install_blob(&c_conn->property_info, - "capabilities", - DRM_MODE_PROP_IMMUTABLE, - CONNECTOR_PROP_SDE_INFO); - - rc = sde_connector_set_blob_data(&c_conn->base, - NULL, - CONNECTOR_PROP_SDE_INFO); - if (rc) { - SDE_ERROR_CONN(c_conn, - "failed to setup connector info, rc = %d\n", rc); - goto error_cleanup_fence; - } - - msm_property_install_blob(&c_conn->property_info, - "mode_properties", - DRM_MODE_PROP_IMMUTABLE, - CONNECTOR_PROP_MODE_INFO); - - if (connector_type == DRM_MODE_CONNECTOR_DSI) { - dsi_display = (struct dsi_display *)(display); - if (dsi_display && dsi_display->panel && - dsi_display->panel->hdr_props.hdr_enabled == true) { - msm_property_install_blob(&c_conn->property_info, - "hdr_properties", - DRM_MODE_PROP_IMMUTABLE, - CONNECTOR_PROP_HDR_INFO); - - msm_property_set_blob(&c_conn->property_info, - &c_conn->blob_hdr, - &dsi_display->panel->hdr_props, - sizeof(dsi_display->panel->hdr_props), - CONNECTOR_PROP_HDR_INFO); - } - } - rc = sde_connector_get_info(&c_conn->base, &display_info); if (!rc && (connector_type == DRM_MODE_CONNECTOR_DSI) && (display_info.capabilities & MSM_DISPLAY_CAP_VID_MODE)) @@ -2288,73 +2372,10 @@ struct drm_connector *sde_connector_init(struct drm_device *dev, sde_connector_handle_disp_recovery, c_conn); - msm_property_install_volatile_range( - &c_conn->property_info, "sde_drm_roi_v1", 0x0, - 0, ~0, 0, CONNECTOR_PROP_ROI_V1); - - /* install PP_DITHER properties */ - _sde_connector_install_dither_property(dev, sde_kms, c_conn); - - if (connector_type == DRM_MODE_CONNECTOR_DisplayPort) { - struct drm_msm_ext_hdr_properties hdr = {0}; - - c_conn->hdr_capable = true; - - msm_property_install_blob(&c_conn->property_info, - "ext_hdr_properties", - DRM_MODE_PROP_IMMUTABLE, - CONNECTOR_PROP_EXT_HDR_INFO); - - /* set default values to avoid reading uninitialized data */ - msm_property_set_blob(&c_conn->property_info, - &c_conn->blob_ext_hdr, - &hdr, - sizeof(hdr), - CONNECTOR_PROP_EXT_HDR_INFO); - } - - msm_property_install_volatile_range(&c_conn->property_info, - "hdr_metadata", 0x0, 0, ~0, 0, CONNECTOR_PROP_HDR_METADATA); - - msm_property_install_volatile_range(&c_conn->property_info, - "RETIRE_FENCE", 0x0, 0, ~0, 0, CONNECTOR_PROP_RETIRE_FENCE); - - msm_property_install_range(&c_conn->property_info, "autorefresh", - 0x0, 0, AUTOREFRESH_MAX_FRAME_CNT, 0, - CONNECTOR_PROP_AUTOREFRESH); - - if (connector_type == DRM_MODE_CONNECTOR_DSI && - sde_kms->catalog->has_qsync && - display_info.qsync_min_fps) - msm_property_install_enum(&c_conn->property_info, "qsync_mode", - 0, 0, e_qsync_mode, ARRAY_SIZE(e_qsync_mode), - CONNECTOR_PROP_QSYNC_MODE); - - msm_property_install_range(&c_conn->property_info, "bl_scale", - 0x0, 0, MAX_BL_SCALE_LEVEL, MAX_BL_SCALE_LEVEL, - CONNECTOR_PROP_BL_SCALE); - - msm_property_install_range(&c_conn->property_info, "ad_bl_scale", - 0x0, 0, MAX_AD_BL_SCALE_LEVEL, MAX_AD_BL_SCALE_LEVEL, - CONNECTOR_PROP_AD_BL_SCALE); - - c_conn->bl_scale_dirty = false; - c_conn->bl_scale = MAX_BL_SCALE_LEVEL; - c_conn->bl_scale_ad = MAX_AD_BL_SCALE_LEVEL; - - /* enum/bitmask properties */ - msm_property_install_enum(&c_conn->property_info, "topology_name", - DRM_MODE_PROP_IMMUTABLE, 0, e_topology_name, - ARRAY_SIZE(e_topology_name), - CONNECTOR_PROP_TOPOLOGY_NAME); - msm_property_install_enum(&c_conn->property_info, "topology_control", - 0, 1, e_topology_control, - ARRAY_SIZE(e_topology_control), - CONNECTOR_PROP_TOPOLOGY_CONTROL); - msm_property_install_enum(&c_conn->property_info, "LP", - 0, 0, e_power_mode, - ARRAY_SIZE(e_power_mode), - CONNECTOR_PROP_LP); + rc = _sde_connector_install_properties(dev, sde_kms, c_conn, + connector_type, display, &display_info); + if (rc) + goto error_cleanup_fence; rc = msm_property_install_get_status(&c_conn->property_info); if (rc) { diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c index 402e52e118a8..7b04b6d019d7 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder.c @@ -4643,6 +4643,29 @@ static void _helper_flush_dsc(struct sde_encoder_virt *sde_enc) } } +static void _sde_encoder_needs_hw_reset(struct drm_encoder *drm_enc, + int ln_cnt1) +{ + struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc); + struct sde_encoder_phys *phys; + int ln_cnt2, i; + + /* query line count before cur_master is updated */ + if (sde_enc->cur_master && sde_enc->cur_master->ops.get_wr_line_count) + ln_cnt2 = sde_enc->cur_master->ops.get_wr_line_count( + sde_enc->cur_master); + else + ln_cnt2 = -EINVAL; + + SDE_EVT32(DRMID(drm_enc), ln_cnt1, ln_cnt2); + + for (i = 0; i < sde_enc->num_phys_encs; i++) { + phys = sde_enc->phys_encs[i]; + if (phys && phys->ops.hw_reset) + phys->ops.hw_reset(phys); + } +} + int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, struct sde_encoder_kickoff_params *params) { @@ -4652,9 +4675,7 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, struct sde_crtc *sde_crtc; struct msm_drm_private *priv = NULL; bool needs_hw_reset = false; - uint32_t ln_cnt1, ln_cnt2; - unsigned int i; - int rc, ret = 0; + int ln_cnt1 = -EINVAL, i, rc, ret = 0; struct msm_display_info *disp_info; if (!drm_enc || !params || !drm_enc->dev || @@ -4675,8 +4696,12 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, if (sde_enc->cur_master && sde_enc->cur_master->ops.get_wr_line_count) ln_cnt1 = sde_enc->cur_master->ops.get_wr_line_count( sde_enc->cur_master); - else - ln_cnt1 = -EINVAL; + + if (sde_enc->cur_master && sde_enc->cur_master->connector && + disp_info->capabilities & MSM_DISPLAY_CAP_CMD_MODE) + sde_enc->frame_trigger_mode = sde_connector_get_property( + sde_enc->cur_master->connector->state, + CONNECTOR_PROP_CMD_FRAME_TRIGGER_MODE); /* prepare for next kickoff, may include waiting on previous kickoff */ SDE_ATRACE_BEGIN("sde_encoder_prepare_for_kickoff"); @@ -4713,23 +4738,8 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, } /* if any phys needs reset, reset all phys, in-order */ - if (needs_hw_reset) { - /* query line count before cur_master is updated */ - if (sde_enc->cur_master && - sde_enc->cur_master->ops.get_wr_line_count) - ln_cnt2 = sde_enc->cur_master->ops.get_wr_line_count( - sde_enc->cur_master); - else - ln_cnt2 = -EINVAL; - - SDE_EVT32(DRMID(drm_enc), ln_cnt1, ln_cnt2, - SDE_EVTLOG_FUNC_CASE1); - for (i = 0; i < sde_enc->num_phys_encs; i++) { - phys = sde_enc->phys_encs[i]; - if (phys && phys->ops.hw_reset) - phys->ops.hw_reset(phys); - } - } + if (needs_hw_reset) + _sde_encoder_needs_hw_reset(drm_enc, ln_cnt1); _sde_encoder_update_master(drm_enc, params); From 45ca9aa53a350108c2aea19ad0fa30522e7f0910 Mon Sep 17 00:00:00 2001 From: Dhaval Patel Date: Fri, 12 Jun 2020 17:49:13 +0800 Subject: [PATCH 031/592] drm/msm/sde: avoid frame done event during autorefresh Autorefresh enabled configuration updates the pending kickoff count once and receives multiple pp_done interrupts. Avoid frame done event trigger on these multiple interrupts if there is no pending frame. Change-Id: I03e4cd5758c958be27af05bd2ecdbb6fac5e9354 Signed-off-by: Dhaval Patel Signed-off-by: Krishna Manikandan Signed-off-by: Bruce Hoo Signed-off-by: Ray Zhang --- drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c index 8fd37447bb8c..d546ee2b34cf 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c @@ -200,7 +200,8 @@ static void sde_encoder_phys_cmd_pp_tx_done_irq(void *arg, int irq_idx) SDE_ATRACE_BEGIN("pp_done_irq"); /* notify all synchronous clients first, then asynchronous clients */ - if (phys_enc->parent_ops.handle_frame_done) + if (phys_enc->parent_ops.handle_frame_done && + atomic_read(&phys_enc->pending_kickoff_cnt)) phys_enc->parent_ops.handle_frame_done(phys_enc->parent, phys_enc, event); From d2288839b4798d824d93a9e0c5c6fb7eea4aa3d4 Mon Sep 17 00:00:00 2001 From: Dhaval Patel Date: Fri, 12 Jun 2020 18:06:33 +0800 Subject: [PATCH 032/592] drm/msm/sde: trigger frame done if ctl is idle Command mode display triggers next frame without waiting for current frame transfer complete. In this case, MDP HW transfers two frames and generates done interrupt status for two frames. SW may miss one interrupt if there is a jiffie jump during these two frame done interrupt. This patch checks the controller idle status for posted start triggered frame to avoid invalid pingpong timeout issue. Change-Id: I344357f19e051ebd5ff4d5555d7d27009803f7c2 Signed-off-by: Dhaval Patel Signed-off-by: Ray Zhang Signed-off-by: Bruce Hoo --- drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c | 14 ++++++++++++++ drivers/gpu/drm/msm/sde/sde_hw_ctl.c | 11 ++++++++++- drivers/gpu/drm/msm/sde/sde_hw_ctl.h | 9 ++++++++- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c index d546ee2b34cf..a1c1a2afaf93 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c @@ -1427,11 +1427,13 @@ static int _sde_encoder_phys_cmd_wait_for_ctl_start( struct sde_encoder_wait_info wait_info; int ret; bool frame_pending = true; + struct sde_hw_ctl *ctl; if (!phys_enc || !phys_enc->hw_ctl) { SDE_ERROR("invalid argument(s)\n"); return -EINVAL; } + ctl = phys_enc->hw_ctl; wait_info.wq = &phys_enc->pending_kickoff_wq; wait_info.atomic_cnt = &phys_enc->pending_ctlstart_cnt; @@ -1474,6 +1476,18 @@ static int _sde_encoder_phys_cmd_wait_for_ctl_start( atomic_inc_return(&phys_enc->ctlstart_timeout); } + } else if ((ret == 0) && + (phys_enc->frame_trigger_mode == FRAME_DONE_WAIT_POSTED_START) && + atomic_read(&phys_enc->pending_kickoff_cnt) && + ctl->ops.get_scheduler_status && + (ctl->ops.get_scheduler_status(ctl) & BIT(0)) && + phys_enc->parent_ops.handle_frame_done) { + atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0); + + phys_enc->parent_ops.handle_frame_done( + phys_enc->parent, phys_enc, + SDE_ENCODER_FRAME_EVENT_DONE | + SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE); } return ret; diff --git a/drivers/gpu/drm/msm/sde/sde_hw_ctl.c b/drivers/gpu/drm/msm/sde/sde_hw_ctl.c index 53efad2778e1..39a0c620fbfa 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_ctl.c +++ b/drivers/gpu/drm/msm/sde/sde_hw_ctl.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -31,6 +31,7 @@ #define CTL_PREPARE 0x0d0 #define CTL_SW_RESET 0x030 #define CTL_SW_RESET_OVERRIDE 0x060 +#define CTL_STATUS 0x064 #define CTL_LAYER_EXTN_OFFSET 0x40 #define CTL_ROT_TOP 0x0C0 #define CTL_ROT_FLUSH 0x0C4 @@ -709,6 +710,13 @@ static u32 sde_hw_ctl_get_reset_status(struct sde_hw_ctl *ctx) return (u32)SDE_REG_READ(&ctx->hw, CTL_SW_RESET); } +static u32 sde_hw_ctl_get_scheduler_status(struct sde_hw_ctl *ctx) +{ + if (!ctx) + return 0; + return (u32)SDE_REG_READ(&ctx->hw, CTL_STATUS); +} + static int sde_hw_ctl_reset_control(struct sde_hw_ctl *ctx) { struct sde_hw_blk_reg_map *c; @@ -1273,6 +1281,7 @@ static void _setup_ctl_ops(struct sde_hw_ctl_ops *ops, sde_hw_ctl_update_bitmask_periph_v1; ops->get_ctl_intf = sde_hw_ctl_get_intf_v1; ops->reset_post_disable = sde_hw_ctl_reset_post_disable; + ops->get_scheduler_status = sde_hw_ctl_get_scheduler_status; } else { ops->update_pending_flush = sde_hw_ctl_update_pending_flush; ops->trigger_flush = sde_hw_ctl_trigger_flush; diff --git a/drivers/gpu/drm/msm/sde/sde_hw_ctl.h b/drivers/gpu/drm/msm/sde/sde_hw_ctl.h index e1ee9f89c7e6..1cef1f2ef58f 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_ctl.h +++ b/drivers/gpu/drm/msm/sde/sde_hw_ctl.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -296,6 +296,13 @@ struct sde_hw_ctl_ops { */ u32 (*get_reset)(struct sde_hw_ctl *ctx); + /** + * get_scheduler_reset - check ctl scheduler status bit + * @ctx : ctl path ctx pointer + * Returns: current value of ctl scheduler and idle status + */ + u32 (*get_scheduler_status)(struct sde_hw_ctl *ctx); + /** * hard_reset - force reset on ctl_path * @ctx : ctl path ctx pointer From 6e3e245002886311be48bb1b8a17ba4100ab8a48 Mon Sep 17 00:00:00 2001 From: Veera Sundaram Sankaran Date: Fri, 12 Jun 2020 18:21:17 +0800 Subject: [PATCH 033/592] disp: msm: sde: use wr_ptr interrupt instead of ctl_start SDE driver triggers the frame and waits for the ctl_start interrupt for command mode display. This interrupt provides confirmation that hardware has picked up the frame. Retire fence signaling is associated with this interrupt and it is sent at the rd_ptr interrupt after ctl_start. Due to lut dma delay, ctl_start interrupt may be trigger before rd_ptr or after rd_ptr. SW manages this complexity and handle retire fence for different cases with 500us threshold logic. This change replaces the ctl_start interrupt with wr_ptr interrupt by programming it to trigger at 1st write line count. This is guaranteed to come every time and it is close to rd_ptr interrupt. That allows retire fence trigger at wr_ptr interrupt and simplifies the SW logic. CRTC commit thread would be held slightly longer with this change as the wr_ptr is always close to rd_ptr and after ctl_start. Change-Id: Ic47a8f82c854b4aded0d70c95af853b28a68ffd6 Signed-off-by: Veera Sundaram Sankaran Signed-off-by: Bruce Hoo Signed-off-by: Ray Zhang --- drivers/gpu/drm/msm/sde/sde_crtc.c | 28 +-- drivers/gpu/drm/msm/sde/sde_encoder.c | 17 -- drivers/gpu/drm/msm/sde/sde_encoder.h | 11 +- drivers/gpu/drm/msm/sde/sde_encoder_phys.h | 22 +- .../gpu/drm/msm/sde/sde_encoder_phys_cmd.c | 196 +++++------------- drivers/gpu/drm/msm/sde/sde_hw_intf.c | 3 +- drivers/gpu/drm/msm/sde/sde_hw_mdss.h | 4 +- drivers/gpu/drm/msm/sde/sde_hw_pingpong.c | 1 + 8 files changed, 70 insertions(+), 212 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c index 035eed949d2e..f5a537007d09 100644 --- a/drivers/gpu/drm/msm/sde/sde_crtc.c +++ b/drivers/gpu/drm/msm/sde/sde_crtc.c @@ -944,26 +944,6 @@ static bool sde_crtc_mode_fixup(struct drm_crtc *crtc, return true; } -static int _sde_crtc_get_ctlstart_timeout(struct drm_crtc *crtc) -{ - struct drm_encoder *encoder; - int rc = 0; - - if (!crtc || !crtc->dev) - return 0; - - list_for_each_entry(encoder, - &crtc->dev->mode_config.encoder_list, head) { - if (encoder->crtc != crtc) - continue; - - if (sde_encoder_get_intf_mode(encoder) == INTF_MODE_CMD) - rc += sde_encoder_get_ctlstart_timeout_state(encoder); - } - - return rc; -} - static void _sde_crtc_setup_blend_cfg(struct sde_crtc_mixer *mixer, struct sde_plane_state *pstate, struct sde_format *format) { @@ -3762,13 +3742,7 @@ static void sde_crtc_atomic_begin(struct drm_crtc *crtc, if (unlikely(!sde_crtc->num_mixers)) goto end; - if (_sde_crtc_get_ctlstart_timeout(crtc)) { - _sde_crtc_blend_setup(crtc, old_state, false); - SDE_ERROR("border fill only commit after ctlstart timeout\n"); - } else { - _sde_crtc_blend_setup(crtc, old_state, true); - } - + _sde_crtc_blend_setup(crtc, old_state, true); _sde_crtc_dest_scaler_setup(crtc); /* cancel the idle notify delayed work */ diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c index 7b04b6d019d7..13aadfd4975a 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder.c @@ -3757,23 +3757,6 @@ int sde_encoder_idle_request(struct drm_encoder *drm_enc) return 0; } -int sde_encoder_get_ctlstart_timeout_state(struct drm_encoder *drm_enc) -{ - struct sde_encoder_virt *sde_enc = NULL; - int i, count = 0; - - if (!drm_enc) - return 0; - - sde_enc = to_sde_encoder_virt(drm_enc); - - for (i = 0; i < sde_enc->num_phys_encs; i++) { - count += atomic_read(&sde_enc->phys_encs[i]->ctlstart_timeout); - atomic_set(&sde_enc->phys_encs[i]->ctlstart_timeout, 0); - } - - return count; -} /** * _sde_encoder_trigger_flush - trigger flush for a physical encoder * drm_enc: Pointer to drm encoder structure diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.h b/drivers/gpu/drm/msm/sde/sde_encoder.h index 69b3ad28bb01..2f626dfadeb4 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder.h +++ b/drivers/gpu/drm/msm/sde/sde_encoder.h @@ -171,11 +171,11 @@ void sde_encoder_kickoff(struct drm_encoder *encoder, bool is_error); * @encoder: encoder pointer * @event: event to wait for * MSM_ENC_COMMIT_DONE - Wait for hardware to have flushed the current pending - * frames to hardware at a vblank or ctl_start + * frames to hardware at a vblank or wr_ptr_start * Encoders will map this differently depending on the * panel type. * vid mode -> vsync_irq - * cmd mode -> ctl_start + * cmd mode -> wr_ptr_start_irq * MSM_ENC_TX_COMPLETE - Wait for the hardware to transfer all the pixels to * the panel. Encoders will map this differently * depending on the panel type. @@ -345,11 +345,4 @@ void sde_encoder_control_idle_pc(struct drm_encoder *enc, bool enable); */ int sde_encoder_in_cont_splash(struct drm_encoder *enc); -/** - * sde_encoder_get_ctlstart_timeout_state - checks if ctl start timeout happened - * @drm_enc: Pointer to drm encoder structure - * @Return: non zero value if ctl start timeout occurred - */ -int sde_encoder_get_ctlstart_timeout_state(struct drm_encoder *enc); - #endif /* __SDE_ENCODER_H__ */ diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h index 841ffb9f7407..e5f7ea0192d9 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h @@ -197,9 +197,9 @@ struct sde_encoder_phys_ops { /** * enum sde_intr_idx - sde encoder interrupt index * @INTR_IDX_VSYNC: Vsync interrupt for video mode panel - * @INTR_IDX_PINGPONG: Pingpong done unterrupt for cmd mode panel - * @INTR_IDX_UNDERRUN: Underrun unterrupt for video and cmd mode panel - * @INTR_IDX_RDPTR: Readpointer done unterrupt for cmd mode panel + * @INTR_IDX_PINGPONG: Pingpong done interrupt for cmd mode panel + * @INTR_IDX_UNDERRUN: Underrun interrupt for video and cmd mode panel + * @INTR_IDX_RDPTR: Readpointer done interrupt for cmd mode panel * @INTR_IDX_WB_DONE: Writeback done interrupt for WB * @INTR_IDX_PP1_OVFL: Pingpong overflow interrupt on PP1 for Concurrent WB * @INTR_IDX_PP2_OVFL: Pingpong overflow interrupt on PP2 for Concurrent WB @@ -208,6 +208,7 @@ struct sde_encoder_phys_ops { * @INTR_IDX_PP5_OVFL: Pingpong overflow interrupt on PP5 for Concurrent WB * @INTR_IDX_AUTOREFRESH_DONE: Autorefresh done for cmd mode panel meaning * autorefresh has triggered a double buffer flip + * @INTR_IDX_WRPTR: Writepointer start interrupt for cmd mode panel */ enum sde_intr_idx { INTR_IDX_VSYNC, @@ -222,6 +223,7 @@ enum sde_intr_idx { INTR_IDX_PP3_OVFL, INTR_IDX_PP4_OVFL, INTR_IDX_PP5_OVFL, + INTR_IDX_WRPTR, INTR_IDX_MAX, }; @@ -283,12 +285,9 @@ struct sde_encoder_irq { * vs. the number of done/vblank irqs. Should hover * between 0-2 Incremented when a new kickoff is * scheduled. Decremented in irq handler - * @pending_ctlstart_cnt: Atomic counter tracking the number of ctl start - * pending. * @pending_retire_fence_cnt: Atomic counter tracking the pending retire * fences that have to be signalled. * @pending_kickoff_wq: Wait queue for blocking until kickoff completes - * @ctlstart_timeout: Indicates if ctl start timeout occurred * @irq: IRQ tracking structures * @has_intf_te: Interface TE configuration support * @cont_splash_single_flush Variable to check if single flush is enabled. @@ -330,10 +329,8 @@ struct sde_encoder_phys { atomic_t wbirq_refcount; atomic_t vsync_cnt; atomic_t underrun_cnt; - atomic_t pending_ctlstart_cnt; atomic_t pending_kickoff_cnt; atomic_t pending_retire_fence_cnt; - atomic_t ctlstart_timeout; wait_queue_head_t pending_kickoff_wq; struct sde_encoder_irq irq[INTR_IDX_MAX]; bool has_intf_te; @@ -346,7 +343,6 @@ struct sde_encoder_phys { static inline int sde_encoder_phys_inc_pending(struct sde_encoder_phys *phys) { - atomic_inc_return(&phys->pending_ctlstart_cnt); return atomic_inc_return(&phys->pending_kickoff_cnt); } @@ -387,24 +383,16 @@ struct sde_encoder_phys_cmd_autorefresh { * @stream_sel: Stream selection for multi-stream interfaces * @pp_timeout_report_cnt: number of pingpong done irq timeout errors * @autorefresh: autorefresh feature state - * @pending_rd_ptr_cnt: atomic counter to indicate if retire fence can be - * signaled at the next rd_ptr_irq - * @rd_ptr_timestamp: last rd_ptr_irq timestamp * @pending_vblank_cnt: Atomic counter tracking pending wait for VBLANK * @pending_vblank_wq: Wait queue for blocking until VBLANK received - * @ctl_start_threshold: A threshold in microseconds allows command mode - * engine to trigger the retire fence without waiting for rd_ptr. */ struct sde_encoder_phys_cmd { struct sde_encoder_phys base; int stream_sel; int pp_timeout_report_cnt; struct sde_encoder_phys_cmd_autorefresh autorefresh; - atomic_t pending_rd_ptr_cnt; - ktime_t rd_ptr_timestamp; atomic_t pending_vblank_cnt; wait_queue_head_t pending_vblank_wq; - u32 ctl_start_threshold; }; /** diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c index a1c1a2afaf93..ffa1d04597e3 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c @@ -44,12 +44,6 @@ #define SDE_ENC_WR_PTR_START_TIMEOUT_US 20000 -/* - * Threshold for signalling retire fences in cases where - * CTL_START_IRQ is received just after RD_PTR_IRQ - */ -#define SDE_ENC_CTL_START_THRESHOLD_US 500 - #define SDE_ENC_MAX_POLL_TIMEOUT_US 2000 static inline int _sde_encoder_phys_cmd_get_idle_timeout( @@ -212,23 +206,6 @@ static void sde_encoder_phys_cmd_pp_tx_done_irq(void *arg, int irq_idx) SDE_EVT32_IRQ(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0, new_cnt, event); - /* - * Reduce the refcount for the retire fence as well as for the ctl_start - * if the counters are greater than zero. Signal retire fence if there - * was a retire fence count pending and kickoff count is zero. - */ - if (sde_encoder_phys_cmd_is_master(phys_enc) && (new_cnt == 0)) { - while (atomic_add_unless(&phys_enc->pending_retire_fence_cnt, - -1, 0)) { - if (phys_enc->parent_ops.handle_frame_done) - phys_enc->parent_ops.handle_frame_done( - phys_enc->parent, phys_enc, - SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE); - atomic_add_unless(&phys_enc->pending_ctlstart_cnt, - -1, 0); - } - } - /* Signal any waiting atomic commit thread */ wake_up_all(&phys_enc->pending_kickoff_wq); SDE_ATRACE_END("pp_done_irq"); @@ -263,7 +240,6 @@ static void sde_encoder_phys_cmd_te_rd_ptr_irq(void *arg, int irq_idx) { struct sde_encoder_phys *phys_enc = arg; struct sde_encoder_phys_cmd *cmd_enc; - u32 event = 0; if (!phys_enc || !phys_enc->hw_pp || !phys_enc->hw_intf) return; @@ -271,94 +247,46 @@ static void sde_encoder_phys_cmd_te_rd_ptr_irq(void *arg, int irq_idx) SDE_ATRACE_BEGIN("rd_ptr_irq"); cmd_enc = to_sde_encoder_phys_cmd(phys_enc); - /** - * signal only for master, when the ctl_start irq is - * done and incremented the pending_rd_ptr_cnt. - */ - if (sde_encoder_phys_cmd_is_master(phys_enc) - && atomic_add_unless(&cmd_enc->pending_rd_ptr_cnt, -1, 0) - && atomic_add_unless( - &phys_enc->pending_retire_fence_cnt, -1, 0)) { - - event = SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE; - if (phys_enc->parent_ops.handle_frame_done) - phys_enc->parent_ops.handle_frame_done( - phys_enc->parent, phys_enc, event); - } - SDE_EVT32_IRQ(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0, phys_enc->hw_intf->idx - INTF_0, - event, 0xfff); + 0xfff); if (phys_enc->parent_ops.handle_vblank_virt) phys_enc->parent_ops.handle_vblank_virt(phys_enc->parent, phys_enc); - cmd_enc->rd_ptr_timestamp = ktime_get(); - atomic_add_unless(&cmd_enc->pending_vblank_cnt, -1, 0); wake_up_all(&cmd_enc->pending_vblank_wq); SDE_ATRACE_END("rd_ptr_irq"); } -static void sde_encoder_phys_cmd_ctl_start_irq(void *arg, int irq_idx) +static void sde_encoder_phys_cmd_wr_ptr_irq(void *arg, int irq_idx) { struct sde_encoder_phys *phys_enc = arg; - struct sde_encoder_phys_cmd *cmd_enc; struct sde_hw_ctl *ctl; u32 event = 0; - s64 time_diff_us; if (!phys_enc || !phys_enc->hw_ctl) return; - SDE_ATRACE_BEGIN("ctl_start_irq"); - cmd_enc = to_sde_encoder_phys_cmd(phys_enc); + SDE_ATRACE_BEGIN("wr_ptr_irq"); ctl = phys_enc->hw_ctl; - atomic_add_unless(&phys_enc->pending_ctlstart_cnt, -1, 0); - atomic_set(&phys_enc->ctlstart_timeout, 0); - time_diff_us = ktime_us_delta(ktime_get(), cmd_enc->rd_ptr_timestamp); - - /* handle retire fence based on only master */ - if (sde_encoder_phys_cmd_is_master(phys_enc) - && atomic_read(&phys_enc->pending_retire_fence_cnt)) { - /** - * Handle rare cases where the ctl_start_irq is received - * after rd_ptr_irq. If it falls within a threshold, it is - * guaranteed the frame would be picked up in the current TE. - * Signal retire fence immediately in such case. The threshold - * timer adds extra line time duration based on lowest panel - * fps for qsync enabled case. - */ - if ((time_diff_us <= cmd_enc->ctl_start_threshold) - && atomic_add_unless( - &phys_enc->pending_retire_fence_cnt, -1, 0)) { - - event = SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE; - - if (phys_enc->parent_ops.handle_frame_done) - phys_enc->parent_ops.handle_frame_done( + if (atomic_add_unless(&phys_enc->pending_retire_fence_cnt, -1, 0)) { + event = SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE; + if (phys_enc->parent_ops.handle_frame_done) + phys_enc->parent_ops.handle_frame_done( phys_enc->parent, phys_enc, event); - - /** - * In ideal cases, ctl_start_irq is received before the - * rd_ptr_irq, so set the atomic flag to indicate the event - * and rd_ptr_irq will handle signalling the retire fence - */ - } else { - atomic_inc(&cmd_enc->pending_rd_ptr_cnt); - } } SDE_EVT32_IRQ(DRMID(phys_enc->parent), ctl->idx - CTL_0, - time_diff_us, event, 0xfff); + event, 0xfff); - /* Signal any waiting ctl start interrupt */ + /* Signal any waiting wr_ptr interrupt */ wake_up_all(&phys_enc->pending_kickoff_wq); - SDE_ATRACE_END("ctl_start_irq"); + SDE_ATRACE_END("wr_ptr_irq"); } static void sde_encoder_phys_cmd_underrun_irq(void *arg, int irq_idx) @@ -432,6 +360,13 @@ static void _sde_encoder_phys_cmd_setup_irq_hw_idx( else irq->hw_idx = phys_enc->hw_pp->idx; + irq = &phys_enc->irq[INTR_IDX_WRPTR]; + irq->irq_idx = -EINVAL; + if (phys_enc->has_intf_te) + irq->hw_idx = phys_enc->hw_intf->idx; + else + irq->hw_idx = phys_enc->hw_pp->idx; + mutex_unlock(phys_enc->vblank_ctl_lock); } @@ -552,17 +487,6 @@ static int _sde_encoder_phys_cmd_handle_ppdone_timeout( cmd_enc->pp_timeout_report_cnt++; pending_kickoff_cnt = atomic_read(&phys_enc->pending_kickoff_cnt); - if (sde_encoder_phys_cmd_is_master(phys_enc)) { - /* trigger the retire fence if it was missed */ - if (atomic_add_unless(&phys_enc->pending_retire_fence_cnt, - -1, 0)) - phys_enc->parent_ops.handle_frame_done( - phys_enc->parent, - phys_enc, - SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE); - atomic_add_unless(&phys_enc->pending_ctlstart_cnt, -1, 0); - } - SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0, cmd_enc->pp_timeout_report_cnt, pending_kickoff_cnt, @@ -904,12 +828,11 @@ void sde_encoder_phys_cmd_irq_control(struct sde_encoder_phys *phys_enc, if (enable) { sde_encoder_helper_register_irq(phys_enc, INTR_IDX_PINGPONG); - sde_encoder_helper_register_irq(phys_enc, INTR_IDX_UNDERRUN); sde_encoder_phys_cmd_control_vblank_irq(phys_enc, true); if (sde_encoder_phys_cmd_is_master(phys_enc)) { sde_encoder_helper_register_irq(phys_enc, - INTR_IDX_CTL_START); + INTR_IDX_WRPTR); sde_encoder_helper_register_irq(phys_enc, INTR_IDX_AUTOREFRESH_DONE); } @@ -917,12 +840,11 @@ void sde_encoder_phys_cmd_irq_control(struct sde_encoder_phys *phys_enc, } else { if (sde_encoder_phys_cmd_is_master(phys_enc)) { sde_encoder_helper_unregister_irq(phys_enc, - INTR_IDX_CTL_START); + INTR_IDX_WRPTR); sde_encoder_helper_unregister_irq(phys_enc, INTR_IDX_AUTOREFRESH_DONE); } - sde_encoder_helper_unregister_irq(phys_enc, INTR_IDX_UNDERRUN); sde_encoder_phys_cmd_control_vblank_irq(phys_enc, false); sde_encoder_helper_unregister_irq(phys_enc, INTR_IDX_PINGPONG); } @@ -1078,9 +1000,7 @@ static void sde_encoder_phys_cmd_tearcheck_config( tc_cfg.sync_threshold_continue = DEFAULT_TEARCHECK_SYNC_THRESH_CONTINUE; tc_cfg.start_pos = mode->vdisplay; tc_cfg.rd_ptr_irq = mode->vdisplay + 1; - - cmd_enc->ctl_start_threshold = (extra_frame_trigger_time / 1000) + - SDE_ENC_CTL_START_THRESHOLD_US; + tc_cfg.wr_ptr_irq = 1; SDE_DEBUG_CMDENC(cmd_enc, "tc %d intf %d vsync_clk_speed_hz %u vtotal %u vrefresh %u\n", @@ -1088,10 +1008,11 @@ static void sde_encoder_phys_cmd_tearcheck_config( phys_enc->hw_intf->idx - INTF_0, vsync_hz, mode->vtotal, mode->vrefresh); SDE_DEBUG_CMDENC(cmd_enc, - "tc %d intf %d enable %u start_pos %u rd_ptr_irq %u\n", + "tc %d intf %d enable %u start_pos %u rd_ptr_irq %u wr_ptr_irq %u\n", phys_enc->hw_pp->idx - PINGPONG_0, phys_enc->hw_intf->idx - INTF_0, - tc_enable, tc_cfg.start_pos, tc_cfg.rd_ptr_irq); + tc_enable, tc_cfg.start_pos, tc_cfg.rd_ptr_irq, + tc_cfg.wr_ptr_irq); SDE_DEBUG_CMDENC(cmd_enc, "tc %d intf %d hw_vsync_mode %u vsync_count %u vsync_init_val %u\n", phys_enc->hw_pp->idx - PINGPONG_0, @@ -1099,12 +1020,11 @@ static void sde_encoder_phys_cmd_tearcheck_config( tc_cfg.hw_vsync_mode, tc_cfg.vsync_count, tc_cfg.vsync_init_val); SDE_DEBUG_CMDENC(cmd_enc, - "tc %d intf %d cfgheight %u thresh_start %u thresh_cont %u ctl_start_threshold:%d\n", + "tc %d intf %d cfgheight %u thresh_start %u thresh_cont %u\n", phys_enc->hw_pp->idx - PINGPONG_0, phys_enc->hw_intf->idx - INTF_0, tc_cfg.sync_cfg_height, - tc_cfg.sync_threshold_start, tc_cfg.sync_threshold_continue, - cmd_enc->ctl_start_threshold); + tc_cfg.sync_threshold_start, tc_cfg.sync_threshold_continue); if (phys_enc->has_intf_te) { phys_enc->hw_intf->ops.setup_tearcheck(phys_enc->hw_intf, @@ -1300,7 +1220,6 @@ static void sde_encoder_phys_cmd_disable(struct sde_encoder_phys *phys_enc) SDE_ERROR("invalid encoder\n"); return; } - atomic_set(&phys_enc->ctlstart_timeout, 0); SDE_DEBUG_CMDENC(cmd_enc, "pp %d intf %d state %d\n", phys_enc->hw_pp->idx - PINGPONG_0, phys_enc->hw_intf->idx - INTF_0, @@ -1378,6 +1297,7 @@ static int sde_encoder_phys_cmd_prepare_for_kickoff( SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0, atomic_read(&phys_enc->pending_kickoff_cnt), atomic_read(&cmd_enc->autorefresh.kickoff_cnt)); + phys_enc->frame_trigger_mode = params->frame_trigger_mode; if (phys_enc->frame_trigger_mode == FRAME_DONE_WAIT_DEFAULT) { /* @@ -1406,11 +1326,7 @@ static int sde_encoder_phys_cmd_prepare_for_kickoff( phys_enc->hw_pp->ops.update_tearcheck( phys_enc->hw_pp, &tc_cfg); - cmd_enc->ctl_start_threshold = - (extra_frame_trigger_time / 1000) + - SDE_ENC_CTL_START_THRESHOLD_US; - SDE_EVT32(DRMID(phys_enc->parent), - tc_cfg.sync_threshold_start, cmd_enc->ctl_start_threshold); + SDE_EVT32(DRMID(phys_enc->parent), tc_cfg.sync_threshold_start); } SDE_DEBUG_CMDENC(cmd_enc, "pp:%d pending_cnt %d\n", @@ -1419,7 +1335,7 @@ static int sde_encoder_phys_cmd_prepare_for_kickoff( return ret; } -static int _sde_encoder_phys_cmd_wait_for_ctl_start( +static int _sde_encoder_phys_cmd_wait_for_wr_ptr( struct sde_encoder_phys *phys_enc) { struct sde_encoder_phys_cmd *cmd_enc = @@ -1436,14 +1352,14 @@ static int _sde_encoder_phys_cmd_wait_for_ctl_start( ctl = phys_enc->hw_ctl; wait_info.wq = &phys_enc->pending_kickoff_wq; - wait_info.atomic_cnt = &phys_enc->pending_ctlstart_cnt; + wait_info.atomic_cnt = &phys_enc->pending_retire_fence_cnt; wait_info.timeout_ms = KICKOFF_TIMEOUT_MS; /* slave encoder doesn't enable for ppsplit */ if (_sde_encoder_phys_is_ppsplit_slave(phys_enc)) return 0; - ret = sde_encoder_helper_wait_for_irq(phys_enc, INTR_IDX_CTL_START, + ret = sde_encoder_helper_wait_for_irq(phys_enc, INTR_IDX_WRPTR, &wait_info); if (ret == -ETIMEDOUT) { struct sde_hw_ctl *ctl = phys_enc->hw_ctl; @@ -1453,29 +1369,23 @@ static int _sde_encoder_phys_cmd_wait_for_ctl_start( if (frame_pending) SDE_ERROR_CMDENC(cmd_enc, - "ctl start interrupt wait failed\n"); + "wr_ptr interrupt wait failed\n"); else ret = 0; - if (sde_encoder_phys_cmd_is_master(phys_enc)) { - /* - * Signaling the retire fence at ctl start timeout - * to allow the next commit and avoid device freeze. - * As ctl start timeout can occurs due to no read ptr, - * updating pending_rd_ptr_cnt here may not cover all - * cases. Hence signaling the retire fence. - */ - if (atomic_add_unless( - &phys_enc->pending_retire_fence_cnt, -1, 0)) - phys_enc->parent_ops.handle_frame_done( - phys_enc->parent, - phys_enc, - SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE); - atomic_add_unless( - &phys_enc->pending_ctlstart_cnt, -1, 0); - atomic_inc_return(&phys_enc->ctlstart_timeout); - } - + /* + * Signaling the retire fence at wr_ptr timeout + * to allow the next commit and avoid device freeze. + * As wr_ptr timeout can occurs due to no read ptr, + * updating pending_rd_ptr_cnt here may not cover all + * cases. Hence signaling the retire fence. + */ + if (sde_encoder_phys_cmd_is_master(phys_enc) && + atomic_add_unless(&phys_enc->pending_retire_fence_cnt, + -1, 0)) + phys_enc->parent_ops.handle_frame_done( + phys_enc->parent, phys_enc, + SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE); } else if ((ret == 0) && (phys_enc->frame_trigger_mode == FRAME_DONE_WAIT_POSTED_START) && atomic_read(&phys_enc->pending_kickoff_cnt) && @@ -1527,7 +1437,7 @@ static int sde_encoder_phys_cmd_wait_for_commit_done( /* only required for master controller */ if (sde_encoder_phys_cmd_is_master(phys_enc)) - rc = _sde_encoder_phys_cmd_wait_for_ctl_start(phys_enc); + rc = _sde_encoder_phys_cmd_wait_for_wr_ptr(phys_enc); if (!rc && sde_encoder_phys_cmd_is_master(phys_enc) && cmd_enc->autorefresh.cfg.enable) @@ -1760,7 +1670,6 @@ struct sde_encoder_phys *sde_encoder_phys_cmd_init( phys_enc->enc_spinlock = p->enc_spinlock; phys_enc->vblank_ctl_lock = p->vblank_ctl_lock; cmd_enc->stream_sel = 0; - cmd_enc->ctl_start_threshold = SDE_ENC_CTL_START_THRESHOLD_US; phys_enc->enable_state = SDE_ENC_DISABLED; sde_encoder_phys_cmd_init_ops(&phys_enc->ops); phys_enc->comp_type = p->comp_type; @@ -1782,7 +1691,7 @@ struct sde_encoder_phys *sde_encoder_phys_cmd_init( irq->name = "ctl_start"; irq->intr_type = SDE_IRQ_TYPE_CTL_START; irq->intr_idx = INTR_IDX_CTL_START; - irq->cb.func = sde_encoder_phys_cmd_ctl_start_irq; + irq->cb.func = NULL; irq = &phys_enc->irq[INTR_IDX_PINGPONG]; irq->name = "pp_done"; @@ -1818,13 +1727,20 @@ struct sde_encoder_phys *sde_encoder_phys_cmd_init( irq->intr_idx = INTR_IDX_AUTOREFRESH_DONE; irq->cb.func = sde_encoder_phys_cmd_autorefresh_done_irq; + irq = &phys_enc->irq[INTR_IDX_WRPTR]; + irq->intr_idx = INTR_IDX_WRPTR; + irq->name = "wr_ptr"; + + if (phys_enc->has_intf_te) + irq->intr_type = SDE_IRQ_TYPE_INTF_TEAR_WR_PTR; + else + irq->intr_type = SDE_IRQ_TYPE_PING_PONG_WR_PTR; + irq->cb.func = sde_encoder_phys_cmd_wr_ptr_irq; + atomic_set(&phys_enc->vblank_refcount, 0); atomic_set(&phys_enc->pending_kickoff_cnt, 0); - atomic_set(&phys_enc->pending_ctlstart_cnt, 0); atomic_set(&phys_enc->pending_retire_fence_cnt, 0); - atomic_set(&cmd_enc->pending_rd_ptr_cnt, 0); atomic_set(&cmd_enc->pending_vblank_cnt, 0); - atomic_set(&phys_enc->ctlstart_timeout, 0); init_waitqueue_head(&phys_enc->pending_kickoff_wq); init_waitqueue_head(&cmd_enc->pending_vblank_wq); atomic_set(&cmd_enc->autorefresh.kickoff_cnt, 0); diff --git a/drivers/gpu/drm/msm/sde/sde_hw_intf.c b/drivers/gpu/drm/msm/sde/sde_hw_intf.c index b88d4b525db2..e318395635a9 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_intf.c +++ b/drivers/gpu/drm/msm/sde/sde_hw_intf.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -497,6 +497,7 @@ static int sde_hw_intf_setup_te_config(struct sde_hw_intf *intf, SDE_REG_WRITE(c, INTF_TEAR_SYNC_CONFIG_HEIGHT, te->sync_cfg_height); SDE_REG_WRITE(c, INTF_TEAR_VSYNC_INIT_VAL, te->vsync_init_val); SDE_REG_WRITE(c, INTF_TEAR_RD_PTR_IRQ, te->rd_ptr_irq); + SDE_REG_WRITE(c, INTF_TEAR_WR_PTR_IRQ, te->wr_ptr_irq); SDE_REG_WRITE(c, INTF_TEAR_START_POS, te->start_pos); SDE_REG_WRITE(c, INTF_TEAR_SYNC_THRESH, ((te->sync_threshold_continue << 16) | diff --git a/drivers/gpu/drm/msm/sde/sde_hw_mdss.h b/drivers/gpu/drm/msm/sde/sde_hw_mdss.h index 145da74946f2..49be98dd3c2a 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_mdss.h +++ b/drivers/gpu/drm/msm/sde/sde_hw_mdss.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -647,6 +647,7 @@ struct sde_splash_data { * needs to be above the read pointer * @start_pos: The position from which the start_threshold value is added * @rd_ptr_irq: The read pointer line at which interrupt has to be generated + * @wr_ptr_irq: The write pointer line at which interrupt has to be generated * @hw_vsync_mode: Sync with external frame sync input */ struct sde_hw_tear_check { @@ -657,6 +658,7 @@ struct sde_hw_tear_check { u32 sync_threshold_continue; u32 start_pos; u32 rd_ptr_irq; + u32 wr_ptr_irq; u8 hw_vsync_mode; }; diff --git a/drivers/gpu/drm/msm/sde/sde_hw_pingpong.c b/drivers/gpu/drm/msm/sde/sde_hw_pingpong.c index 64c1a90f5952..308fd5f6ee46 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_pingpong.c +++ b/drivers/gpu/drm/msm/sde/sde_hw_pingpong.c @@ -183,6 +183,7 @@ static int sde_hw_pp_setup_te_config(struct sde_hw_pingpong *pp, SDE_REG_WRITE(c, PP_SYNC_CONFIG_HEIGHT, te->sync_cfg_height); SDE_REG_WRITE(c, PP_VSYNC_INIT_VAL, te->vsync_init_val); SDE_REG_WRITE(c, PP_RD_PTR_IRQ, te->rd_ptr_irq); + SDE_REG_WRITE(c, PP_WR_PTR_IRQ, te->wr_ptr_irq); SDE_REG_WRITE(c, PP_START_POS, te->start_pos); SDE_REG_WRITE(c, PP_SYNC_THRESH, ((te->sync_threshold_continue << 16) | From 5c6cd1bd1febbaa7a5e9fea311ecc9533231d692 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Mon, 2 Mar 2020 15:21:32 +0900 Subject: [PATCH 034/592] exfat: add in-memory and on-disk structures and headers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds in-memory and on-disk structures and headers. Signed-off-by: Namjae Jeon Signed-off-by: Sungjong Seo Reviewed-by: Pali Rohár Reviewed-by: Christoph Hellwig Signed-off-by: Al Viro Signed-off-by: Park Ju Hyung --- exfat_fs.h | 519 ++++++++++++++++++++++++++++++++++++++++++++++++++++ exfat_raw.h | 184 +++++++++++++++++++ 2 files changed, 703 insertions(+) create mode 100644 exfat_fs.h create mode 100644 exfat_raw.h diff --git a/exfat_fs.h b/exfat_fs.h new file mode 100644 index 000000000000..67d4e46fb810 --- /dev/null +++ b/exfat_fs.h @@ -0,0 +1,519 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + */ + +#ifndef _EXFAT_FS_H +#define _EXFAT_FS_H + +#include +#include +#include + +#define EXFAT_SUPER_MAGIC 0x2011BAB0UL +#define EXFAT_ROOT_INO 1 + +#define EXFAT_SB_DIRTY 0 + +#define EXFAT_CLUSTERS_UNTRACKED (~0u) + +/* + * exfat error flags + */ +enum exfat_error_mode { + EXFAT_ERRORS_CONT, /* ignore error and continue */ + EXFAT_ERRORS_PANIC, /* panic on error */ + EXFAT_ERRORS_RO, /* remount r/o on error */ +}; + +/* + * exfat nls lossy flag + */ +enum { + NLS_NAME_NO_LOSSY, /* no lossy */ + NLS_NAME_LOSSY, /* just detected incorrect filename(s) */ + NLS_NAME_OVERLEN, /* the length is over than its limit */ +}; + +#define EXFAT_HASH_BITS 8 +#define EXFAT_HASH_SIZE (1UL << EXFAT_HASH_BITS) + +/* + * Type Definitions + */ +#define ES_2_ENTRIES 2 +#define ES_ALL_ENTRIES 0 + +#define DIR_DELETED 0xFFFF0321 + +/* type values */ +#define TYPE_UNUSED 0x0000 +#define TYPE_DELETED 0x0001 +#define TYPE_INVALID 0x0002 +#define TYPE_CRITICAL_PRI 0x0100 +#define TYPE_BITMAP 0x0101 +#define TYPE_UPCASE 0x0102 +#define TYPE_VOLUME 0x0103 +#define TYPE_DIR 0x0104 +#define TYPE_FILE 0x011F +#define TYPE_CRITICAL_SEC 0x0200 +#define TYPE_STREAM 0x0201 +#define TYPE_EXTEND 0x0202 +#define TYPE_ACL 0x0203 +#define TYPE_BENIGN_PRI 0x0400 +#define TYPE_GUID 0x0401 +#define TYPE_PADDING 0x0402 +#define TYPE_ACLTAB 0x0403 +#define TYPE_BENIGN_SEC 0x0800 +#define TYPE_ALL 0x0FFF + +#define MAX_CHARSET_SIZE 6 /* max size of multi-byte character */ +#define MAX_NAME_LENGTH 255 /* max len of file name excluding NULL */ +#define MAX_VFSNAME_BUF_SIZE ((MAX_NAME_LENGTH + 1) * MAX_CHARSET_SIZE) + +#define FAT_CACHE_SIZE 128 +#define FAT_CACHE_HASH_SIZE 64 +#define BUF_CACHE_SIZE 256 +#define BUF_CACHE_HASH_SIZE 64 + +#define EXFAT_HINT_NONE -1 +#define EXFAT_MIN_SUBDIR 2 + +/* + * helpers for cluster size to byte conversion. + */ +#define EXFAT_CLU_TO_B(b, sbi) ((b) << (sbi)->cluster_size_bits) +#define EXFAT_B_TO_CLU(b, sbi) ((b) >> (sbi)->cluster_size_bits) +#define EXFAT_B_TO_CLU_ROUND_UP(b, sbi) \ + (((b - 1) >> (sbi)->cluster_size_bits) + 1) +#define EXFAT_CLU_OFFSET(off, sbi) ((off) & ((sbi)->cluster_size - 1)) + +/* + * helpers for block size to byte conversion. + */ +#define EXFAT_BLK_TO_B(b, sb) ((b) << (sb)->s_blocksize_bits) +#define EXFAT_B_TO_BLK(b, sb) ((b) >> (sb)->s_blocksize_bits) +#define EXFAT_B_TO_BLK_ROUND_UP(b, sb) \ + (((b - 1) >> (sb)->s_blocksize_bits) + 1) +#define EXFAT_BLK_OFFSET(off, sb) ((off) & ((sb)->s_blocksize - 1)) + +/* + * helpers for block size to dentry size conversion. + */ +#define EXFAT_B_TO_DEN_IDX(b, sbi) \ + ((b) << ((sbi)->cluster_size_bits - DENTRY_SIZE_BITS)) +#define EXFAT_B_TO_DEN(b) ((b) >> DENTRY_SIZE_BITS) +#define EXFAT_DEN_TO_B(b) ((b) << DENTRY_SIZE_BITS) + +/* + * helpers for fat entry. + */ +#define FAT_ENT_SIZE (4) +#define FAT_ENT_SIZE_BITS (2) +#define FAT_ENT_OFFSET_SECTOR(sb, loc) (EXFAT_SB(sb)->FAT1_start_sector + \ + (((u64)loc << FAT_ENT_SIZE_BITS) >> sb->s_blocksize_bits)) +#define FAT_ENT_OFFSET_BYTE_IN_SECTOR(sb, loc) \ + ((loc << FAT_ENT_SIZE_BITS) & (sb->s_blocksize - 1)) + +/* + * helpers for bitmap. + */ +#define CLUSTER_TO_BITMAP_ENT(clu) ((clu) - EXFAT_RESERVED_CLUSTERS) +#define BITMAP_ENT_TO_CLUSTER(ent) ((ent) + EXFAT_RESERVED_CLUSTERS) +#define BITS_PER_SECTOR(sb) ((sb)->s_blocksize * BITS_PER_BYTE) +#define BITS_PER_SECTOR_MASK(sb) (BITS_PER_SECTOR(sb) - 1) +#define BITMAP_OFFSET_SECTOR_INDEX(sb, ent) \ + ((ent / BITS_PER_BYTE) >> (sb)->s_blocksize_bits) +#define BITMAP_OFFSET_BIT_IN_SECTOR(sb, ent) (ent & BITS_PER_SECTOR_MASK(sb)) +#define BITMAP_OFFSET_BYTE_IN_SECTOR(sb, ent) \ + ((ent / BITS_PER_BYTE) & ((sb)->s_blocksize - 1)) +#define BITS_PER_BYTE_MASK 0x7 +#define IGNORED_BITS_REMAINED(clu, clu_base) ((1 << ((clu) - (clu_base))) - 1) + +struct exfat_dentry_namebuf { + char *lfn; + int lfnbuf_len; /* usally MAX_UNINAME_BUF_SIZE */ +}; + +/* unicode name structure */ +struct exfat_uni_name { + /* +3 for null and for converting */ + unsigned short name[MAX_NAME_LENGTH + 3]; + unsigned short name_hash; + unsigned char name_len; +}; + +/* directory structure */ +struct exfat_chain { + unsigned int dir; + unsigned int size; + unsigned char flags; +}; + +/* first empty entry hint information */ +struct exfat_hint_femp { + /* entry index of a directory */ + int eidx; + /* count of continuous empty entry */ + int count; + /* the cluster that first empty slot exists in */ + struct exfat_chain cur; +}; + +/* hint structure */ +struct exfat_hint { + unsigned int clu; + union { + unsigned int off; /* cluster offset */ + int eidx; /* entry index */ + }; +}; + +struct exfat_entry_set_cache { + /* sector number that contains file_entry */ + sector_t sector; + /* byte offset in the sector */ + unsigned int offset; + /* flag in stream entry. 01 for cluster chain, 03 for contig. */ + int alloc_flag; + unsigned int num_entries; + struct exfat_dentry entries[]; +}; + +struct exfat_dir_entry { + struct exfat_chain dir; + int entry; + unsigned int type; + unsigned int start_clu; + unsigned char flags; + unsigned short attr; + loff_t size; + unsigned int num_subdirs; + struct timespec64 atime; + struct timespec64 mtime; + struct timespec64 crtime; + struct exfat_dentry_namebuf namebuf; +}; + +/* + * exfat mount in-memory data + */ +struct exfat_mount_options { + kuid_t fs_uid; + kgid_t fs_gid; + unsigned short fs_fmask; + unsigned short fs_dmask; + /* permission for setting the [am]time */ + unsigned short allow_utime; + /* charset for filename input/display */ + char *iocharset; + /* on error: continue, panic, remount-ro */ + enum exfat_error_mode errors; + unsigned utf8:1, /* Use of UTF-8 character set */ + discard:1; /* Issue discard requests on deletions */ + int time_offset; /* Offset of timestamps from UTC (in minutes) */ +}; + +/* + * EXFAT file system superblock in-memory data + */ +struct exfat_sb_info { + unsigned long long num_sectors; /* num of sectors in volume */ + unsigned int num_clusters; /* num of clusters in volume */ + unsigned int cluster_size; /* cluster size in bytes */ + unsigned int cluster_size_bits; + unsigned int sect_per_clus; /* cluster size in sectors */ + unsigned int sect_per_clus_bits; + unsigned long long FAT1_start_sector; /* FAT1 start sector */ + unsigned long long FAT2_start_sector; /* FAT2 start sector */ + unsigned long long data_start_sector; /* data area start sector */ + unsigned int num_FAT_sectors; /* num of FAT sectors */ + unsigned int root_dir; /* root dir cluster */ + unsigned int dentries_per_clu; /* num of dentries per cluster */ + unsigned int vol_flag; /* volume dirty flag */ + struct buffer_head *pbr_bh; /* buffer_head of PBR sector */ + + unsigned int map_clu; /* allocation bitmap start cluster */ + unsigned int map_sectors; /* num of allocation bitmap sectors */ + struct buffer_head **vol_amap; /* allocation bitmap */ + + unsigned short *vol_utbl; /* upcase table */ + + unsigned int clu_srch_ptr; /* cluster search pointer */ + unsigned int used_clusters; /* number of used clusters */ + + unsigned long s_state; + struct mutex s_lock; /* superblock lock */ + struct exfat_mount_options options; + struct nls_table *nls_io; /* Charset used for input and display */ + struct ratelimit_state ratelimit; + + spinlock_t inode_hash_lock; + struct hlist_head inode_hashtable[EXFAT_HASH_SIZE]; + + struct rcu_head rcu; +}; + +/* + * EXFAT file system inode in-memory data + */ +struct exfat_inode_info { + struct exfat_chain dir; + int entry; + unsigned int type; + unsigned short attr; + unsigned int start_clu; + unsigned char flags; + /* + * the copy of low 32bit of i_version to check + * the validation of hint_stat. + */ + unsigned int version; + /* file offset or dentry index for readdir */ + loff_t rwoffset; + + /* hint for cluster last accessed */ + struct exfat_hint hint_bmap; + /* hint for entry index we try to lookup next time */ + struct exfat_hint hint_stat; + /* hint for first empty entry */ + struct exfat_hint_femp hint_femp; + + spinlock_t cache_lru_lock; + struct list_head cache_lru; + int nr_caches; + /* for avoiding the race between alloc and free */ + unsigned int cache_valid_id; + + /* + * NOTE: i_size_ondisk is 64bits, so must hold ->inode_lock to access. + * physically allocated size. + */ + loff_t i_size_ondisk; + /* block-aligned i_size (used in cont_write_begin) */ + loff_t i_size_aligned; + /* on-disk position of directory entry or 0 */ + loff_t i_pos; + /* hash by i_location */ + struct hlist_node i_hash_fat; + /* protect bmap against truncate */ + struct rw_semaphore truncate_lock; + struct inode vfs_inode; + /* File creation time */ + struct timespec64 i_crtime; +}; + +static inline struct exfat_sb_info *EXFAT_SB(struct super_block *sb) +{ + return sb->s_fs_info; +} + +static inline struct exfat_inode_info *EXFAT_I(struct inode *inode) +{ + return container_of(inode, struct exfat_inode_info, vfs_inode); +} + +/* + * If ->i_mode can't hold 0222 (i.e. ATTR_RO), we use ->i_attrs to + * save ATTR_RO instead of ->i_mode. + * + * If it's directory and !sbi->options.rodir, ATTR_RO isn't read-only + * bit, it's just used as flag for app. + */ +static inline int exfat_mode_can_hold_ro(struct inode *inode) +{ + struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb); + + if (S_ISDIR(inode->i_mode)) + return 0; + + if ((~sbi->options.fs_fmask) & 0222) + return 1; + return 0; +} + +/* Convert attribute bits and a mask to the UNIX mode. */ +static inline mode_t exfat_make_mode(struct exfat_sb_info *sbi, + unsigned short attr, mode_t mode) +{ + if ((attr & ATTR_READONLY) && !(attr & ATTR_SUBDIR)) + mode &= ~0222; + + if (attr & ATTR_SUBDIR) + return (mode & ~sbi->options.fs_dmask) | S_IFDIR; + + return (mode & ~sbi->options.fs_fmask) | S_IFREG; +} + +/* Return the FAT attribute byte for this inode */ +static inline unsigned short exfat_make_attr(struct inode *inode) +{ + unsigned short attr = EXFAT_I(inode)->attr; + + if (S_ISDIR(inode->i_mode)) + attr |= ATTR_SUBDIR; + if (exfat_mode_can_hold_ro(inode) && !(inode->i_mode & 0222)) + attr |= ATTR_READONLY; + return attr; +} + +static inline void exfat_save_attr(struct inode *inode, unsigned short attr) +{ + if (exfat_mode_can_hold_ro(inode)) + EXFAT_I(inode)->attr = attr & (ATTR_RWMASK | ATTR_READONLY); + else + EXFAT_I(inode)->attr = attr & ATTR_RWMASK; +} + +static inline bool exfat_is_last_sector_in_cluster(struct exfat_sb_info *sbi, + sector_t sec) +{ + return ((sec - sbi->data_start_sector + 1) & + ((1 << sbi->sect_per_clus_bits) - 1)) == 0; +} + +static inline sector_t exfat_cluster_to_sector(struct exfat_sb_info *sbi, + unsigned int clus) +{ + return ((clus - EXFAT_RESERVED_CLUSTERS) << sbi->sect_per_clus_bits) + + sbi->data_start_sector; +} + +static inline int exfat_sector_to_cluster(struct exfat_sb_info *sbi, + sector_t sec) +{ + return ((sec - sbi->data_start_sector) >> sbi->sect_per_clus_bits) + + EXFAT_RESERVED_CLUSTERS; +} + +/* super.c */ +int exfat_set_vol_flags(struct super_block *sb, unsigned short new_flag); + +/* fatent.c */ +#define exfat_get_next_cluster(sb, pclu) exfat_ent_get(sb, *(pclu), pclu) + +int exfat_alloc_cluster(struct inode *inode, unsigned int num_alloc, + struct exfat_chain *p_chain); +int exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain); +int exfat_ent_get(struct super_block *sb, unsigned int loc, + unsigned int *content); +int exfat_ent_set(struct super_block *sb, unsigned int loc, + unsigned int content); +int exfat_count_ext_entries(struct super_block *sb, struct exfat_chain *p_dir, + int entry, struct exfat_dentry *p_entry); +int exfat_chain_cont_cluster(struct super_block *sb, unsigned int chain, + unsigned int len); +int exfat_zeroed_cluster(struct inode *dir, unsigned int clu); +int exfat_find_last_cluster(struct super_block *sb, struct exfat_chain *p_chain, + unsigned int *ret_clu); +int exfat_count_num_clusters(struct super_block *sb, + struct exfat_chain *p_chain, unsigned int *ret_count); + +/* balloc.c */ +int exfat_load_bitmap(struct super_block *sb); +void exfat_free_bitmap(struct exfat_sb_info *sbi); +int exfat_set_bitmap(struct inode *inode, unsigned int clu); +void exfat_clear_bitmap(struct inode *inode, unsigned int clu); +unsigned int exfat_find_free_bitmap(struct super_block *sb, unsigned int clu); +int exfat_count_used_clusters(struct super_block *sb, unsigned int *ret_count); + +/* file.c */ +extern const struct file_operations exfat_file_operations; +int __exfat_truncate(struct inode *inode, loff_t new_size); +void exfat_truncate(struct inode *inode, loff_t size); +int exfat_setattr(struct dentry *dentry, struct iattr *attr); +int exfat_getattr(const struct path *path, struct kstat *stat, + unsigned int request_mask, unsigned int query_flags); + +/* namei.c */ +extern const struct dentry_operations exfat_dentry_ops; +extern const struct dentry_operations exfat_utf8_dentry_ops; + +/* cache.c */ +int exfat_cache_init(void); +void exfat_cache_shutdown(void); +void exfat_cache_init_inode(struct inode *inode); +void exfat_cache_inval_inode(struct inode *inode); +int exfat_get_cluster(struct inode *inode, unsigned int cluster, + unsigned int *fclus, unsigned int *dclus, + unsigned int *last_dclus, int allow_eof); + +/* dir.c */ +extern const struct inode_operations exfat_dir_inode_operations; +extern const struct file_operations exfat_dir_operations; +unsigned int exfat_get_entry_type(struct exfat_dentry *p_entry); +int exfat_init_dir_entry(struct inode *inode, struct exfat_chain *p_dir, + int entry, unsigned int type, unsigned int start_clu, + unsigned long long size); +int exfat_init_ext_entry(struct inode *inode, struct exfat_chain *p_dir, + int entry, int num_entries, struct exfat_uni_name *p_uniname); +int exfat_remove_entries(struct inode *inode, struct exfat_chain *p_dir, + int entry, int order, int num_entries); +int exfat_update_dir_chksum(struct inode *inode, struct exfat_chain *p_dir, + int entry); +int exfat_update_dir_chksum_with_entry_set(struct super_block *sb, + struct exfat_entry_set_cache *es, int sync); +int exfat_calc_num_entries(struct exfat_uni_name *p_uniname); +int exfat_find_dir_entry(struct super_block *sb, struct exfat_inode_info *ei, + struct exfat_chain *p_dir, struct exfat_uni_name *p_uniname, + int num_entries, unsigned int type); +int exfat_alloc_new_dir(struct inode *inode, struct exfat_chain *clu); +int exfat_find_location(struct super_block *sb, struct exfat_chain *p_dir, + int entry, sector_t *sector, int *offset); +struct exfat_dentry *exfat_get_dentry(struct super_block *sb, + struct exfat_chain *p_dir, int entry, struct buffer_head **bh, + sector_t *sector); +struct exfat_entry_set_cache *exfat_get_dentry_set(struct super_block *sb, + struct exfat_chain *p_dir, int entry, unsigned int type, + struct exfat_dentry **file_ep); +int exfat_count_dir_entries(struct super_block *sb, struct exfat_chain *p_dir); + +/* inode.c */ +extern const struct inode_operations exfat_file_inode_operations; +void exfat_sync_inode(struct inode *inode); +struct inode *exfat_build_inode(struct super_block *sb, + struct exfat_dir_entry *info, loff_t i_pos); +void exfat_hash_inode(struct inode *inode, loff_t i_pos); +void exfat_unhash_inode(struct inode *inode); +struct inode *exfat_iget(struct super_block *sb, loff_t i_pos); +int exfat_write_inode(struct inode *inode, struct writeback_control *wbc); +void exfat_evict_inode(struct inode *inode); +int exfat_block_truncate_page(struct inode *inode, loff_t from); + +/* exfat/nls.c */ +unsigned short exfat_toupper(struct super_block *sb, unsigned short a); +int exfat_uniname_ncmp(struct super_block *sb, unsigned short *a, + unsigned short *b, unsigned int len); +int exfat_utf16_to_nls(struct super_block *sb, + struct exfat_uni_name *uniname, unsigned char *p_cstring, + int len); +int exfat_nls_to_utf16(struct super_block *sb, + const unsigned char *p_cstring, const int len, + struct exfat_uni_name *uniname, int *p_lossy); +int exfat_create_upcase_table(struct super_block *sb); +void exfat_free_upcase_table(struct exfat_sb_info *sbi); +unsigned short exfat_high_surrogate(unicode_t u); +unsigned short exfat_low_surrogate(unicode_t u); + +/* exfat/misc.c */ +void __exfat_fs_error(struct super_block *sb, int report, const char *fmt, ...) + __printf(3, 4) __cold; +#define exfat_fs_error(sb, fmt, args...) \ + __exfat_fs_error(sb, 1, fmt, ## args) +#define exfat_fs_error_ratelimit(sb, fmt, args...) \ + __exfat_fs_error(sb, __ratelimit(&EXFAT_SB(sb)->ratelimit), \ + fmt, ## args) +void exfat_msg(struct super_block *sb, const char *lv, const char *fmt, ...) + __printf(3, 4) __cold; +void exfat_get_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts, + u8 tz, __le16 time, __le16 date, u8 time_ms); +void exfat_set_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts, + u8 *tz, __le16 *time, __le16 *date, u8 *time_ms); +unsigned short exfat_calc_chksum_2byte(void *data, int len, + unsigned short chksum, int type); +void exfat_update_bh(struct super_block *sb, struct buffer_head *bh, int sync); +void exfat_chain_set(struct exfat_chain *ec, unsigned int dir, + unsigned int size, unsigned char flags); +void exfat_chain_dup(struct exfat_chain *dup, struct exfat_chain *ec); + +#endif /* !_EXFAT_FS_H */ diff --git a/exfat_raw.h b/exfat_raw.h new file mode 100644 index 000000000000..2a841010e649 --- /dev/null +++ b/exfat_raw.h @@ -0,0 +1,184 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + */ + +#ifndef _EXFAT_RAW_H +#define _EXFAT_RAW_H + +#include + +#define PBR_SIGNATURE 0xAA55 + +#define EXFAT_MAX_FILE_LEN 255 + +#define VOL_CLEAN 0x0000 +#define VOL_DIRTY 0x0002 + +#define EXFAT_EOF_CLUSTER 0xFFFFFFFFu +#define EXFAT_BAD_CLUSTER 0xFFFFFFF7u +#define EXFAT_FREE_CLUSTER 0 +/* Cluster 0, 1 are reserved, the first cluster is 2 in the cluster heap. */ +#define EXFAT_RESERVED_CLUSTERS 2 +#define EXFAT_FIRST_CLUSTER 2 +#define EXFAT_DATA_CLUSTER_COUNT(sbi) \ + ((sbi)->num_clusters - EXFAT_RESERVED_CLUSTERS) + +/* AllocationPossible and NoFatChain field in GeneralSecondaryFlags Field */ +#define ALLOC_FAT_CHAIN 0x01 +#define ALLOC_NO_FAT_CHAIN 0x03 + +#define DENTRY_SIZE 32 /* directory entry size */ +#define DENTRY_SIZE_BITS 5 +/* exFAT allows 8388608(256MB) directory entries */ +#define MAX_EXFAT_DENTRIES 8388608 + +/* dentry types */ +#define EXFAT_UNUSED 0x00 /* end of directory */ +#define EXFAT_DELETE (~0x80) +#define IS_EXFAT_DELETED(x) ((x) < 0x80) /* deleted file (0x01~0x7F) */ +#define EXFAT_INVAL 0x80 /* invalid value */ +#define EXFAT_BITMAP 0x81 /* allocation bitmap */ +#define EXFAT_UPCASE 0x82 /* upcase table */ +#define EXFAT_VOLUME 0x83 /* volume label */ +#define EXFAT_FILE 0x85 /* file or dir */ +#define EXFAT_GUID 0xA0 +#define EXFAT_PADDING 0xA1 +#define EXFAT_ACLTAB 0xA2 +#define EXFAT_STREAM 0xC0 /* stream entry */ +#define EXFAT_NAME 0xC1 /* file name entry */ +#define EXFAT_ACL 0xC2 /* stream entry */ + +#define IS_EXFAT_CRITICAL_PRI(x) (x < 0xA0) +#define IS_EXFAT_BENIGN_PRI(x) (x < 0xC0) +#define IS_EXFAT_CRITICAL_SEC(x) (x < 0xE0) + +/* checksum types */ +#define CS_DIR_ENTRY 0 +#define CS_PBR_SECTOR 1 +#define CS_DEFAULT 2 + +/* file attributes */ +#define ATTR_READONLY 0x0001 +#define ATTR_HIDDEN 0x0002 +#define ATTR_SYSTEM 0x0004 +#define ATTR_VOLUME 0x0008 +#define ATTR_SUBDIR 0x0010 +#define ATTR_ARCHIVE 0x0020 + +#define ATTR_RWMASK (ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUME | \ + ATTR_SUBDIR | ATTR_ARCHIVE) + +#define PBR64_JUMP_BOOT_LEN 3 +#define PBR64_OEM_NAME_LEN 8 +#define PBR64_RESERVED_LEN 53 + +#define EXFAT_FILE_NAME_LEN 15 + +/* EXFAT BIOS parameter block (64 bytes) */ +struct bpb64 { + __u8 jmp_boot[PBR64_JUMP_BOOT_LEN]; + __u8 oem_name[PBR64_OEM_NAME_LEN]; + __u8 res_zero[PBR64_RESERVED_LEN]; +} __packed; + +/* EXFAT EXTEND BIOS parameter block (56 bytes) */ +struct bsx64 { + __le64 vol_offset; + __le64 vol_length; + __le32 fat_offset; + __le32 fat_length; + __le32 clu_offset; + __le32 clu_count; + __le32 root_cluster; + __le32 vol_serial; + __u8 fs_version[2]; + __le16 vol_flags; + __u8 sect_size_bits; + __u8 sect_per_clus_bits; + __u8 num_fats; + __u8 phy_drv_no; + __u8 perc_in_use; + __u8 reserved2[7]; +} __packed; + +/* EXFAT PBR[BPB+BSX] (120 bytes) */ +struct pbr64 { + struct bpb64 bpb; + struct bsx64 bsx; +} __packed; + +/* Common PBR[Partition Boot Record] (512 bytes) */ +struct pbr { + union { + __u8 raw[64]; + struct bpb64 f64; + } bpb; + union { + __u8 raw[56]; + struct bsx64 f64; + } bsx; + __u8 boot_code[390]; + __le16 signature; +} __packed; + +struct exfat_dentry { + __u8 type; + union { + struct { + __u8 num_ext; + __le16 checksum; + __le16 attr; + __le16 reserved1; + __le16 create_time; + __le16 create_date; + __le16 modify_time; + __le16 modify_date; + __le16 access_time; + __le16 access_date; + __u8 create_time_ms; + __u8 modify_time_ms; + __u8 create_tz; + __u8 modify_tz; + __u8 access_tz; + __u8 reserved2[7]; + } __packed file; /* file directory entry */ + struct { + __u8 flags; + __u8 reserved1; + __u8 name_len; + __le16 name_hash; + __le16 reserved2; + __le64 valid_size; + __le32 reserved3; + __le32 start_clu; + __le64 size; + } __packed stream; /* stream extension directory entry */ + struct { + __u8 flags; + __le16 unicode_0_14[EXFAT_FILE_NAME_LEN]; + } __packed name; /* file name directory entry */ + struct { + __u8 flags; + __u8 reserved[18]; + __le32 start_clu; + __le64 size; + } __packed bitmap; /* allocation bitmap directory entry */ + struct { + __u8 reserved1[3]; + __le32 checksum; + __u8 reserved2[12]; + __le32 start_clu; + __le64 size; + } __packed upcase; /* up-case table directory entry */ + } __packed dentry; +} __packed; + +#define EXFAT_TZ_VALID (1 << 7) + +/* Jan 1 GMT 00:00:00 1980 */ +#define EXFAT_MIN_TIMESTAMP_SECS 315532800LL +/* Dec 31 GMT 23:59:59 2107 */ +#define EXFAT_MAX_TIMESTAMP_SECS 4354819199LL + +#endif /* !_EXFAT_RAW_H */ From 6d63a9999f9385d7d4c27c407eadf9458c6526e4 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Mon, 2 Mar 2020 15:21:33 +0900 Subject: [PATCH 035/592] exfat: add super block operations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds the implementation of superblock operations for exfat. Signed-off-by: Namjae Jeon Signed-off-by: Sungjong Seo Reviewed-by: Pali Rohár Reviewed-by: Christoph Hellwig Reviewed-by: Arnd Bergmann Signed-off-by: Al Viro Signed-off-by: Park Ju Hyung --- super.c | 728 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 728 insertions(+) create mode 100644 super.c diff --git a/super.c b/super.c new file mode 100644 index 000000000000..f06e0b53e393 --- /dev/null +++ b/super.c @@ -0,0 +1,728 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "exfat_raw.h" +#include "exfat_fs.h" + +static char exfat_default_iocharset[] = CONFIG_EXFAT_DEFAULT_IOCHARSET; +static struct kmem_cache *exfat_inode_cachep; + +static void exfat_free_iocharset(struct exfat_sb_info *sbi) +{ + if (sbi->options.iocharset != exfat_default_iocharset) + kfree(sbi->options.iocharset); +} + +static void exfat_delayed_free(struct rcu_head *p) +{ + struct exfat_sb_info *sbi = container_of(p, struct exfat_sb_info, rcu); + + unload_nls(sbi->nls_io); + exfat_free_iocharset(sbi); + exfat_free_upcase_table(sbi); + kfree(sbi); +} + +static void exfat_put_super(struct super_block *sb) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + + mutex_lock(&sbi->s_lock); + if (test_and_clear_bit(EXFAT_SB_DIRTY, &sbi->s_state)) + sync_blockdev(sb->s_bdev); + exfat_set_vol_flags(sb, VOL_CLEAN); + exfat_free_bitmap(sbi); + mutex_unlock(&sbi->s_lock); + + call_rcu(&sbi->rcu, exfat_delayed_free); +} + +static int exfat_sync_fs(struct super_block *sb, int wait) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + int err = 0; + + /* If there are some dirty buffers in the bdev inode */ + mutex_lock(&sbi->s_lock); + if (test_and_clear_bit(EXFAT_SB_DIRTY, &sbi->s_state)) { + sync_blockdev(sb->s_bdev); + if (exfat_set_vol_flags(sb, VOL_CLEAN)) + err = -EIO; + } + mutex_unlock(&sbi->s_lock); + return err; +} + +static int exfat_statfs(struct dentry *dentry, struct kstatfs *buf) +{ + struct super_block *sb = dentry->d_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + unsigned long long id = huge_encode_dev(sb->s_bdev->bd_dev); + + if (sbi->used_clusters == EXFAT_CLUSTERS_UNTRACKED) { + mutex_lock(&sbi->s_lock); + if (exfat_count_used_clusters(sb, &sbi->used_clusters)) { + mutex_unlock(&sbi->s_lock); + return -EIO; + } + mutex_unlock(&sbi->s_lock); + } + + buf->f_type = sb->s_magic; + buf->f_bsize = sbi->cluster_size; + buf->f_blocks = sbi->num_clusters - 2; /* clu 0 & 1 */ + buf->f_bfree = buf->f_blocks - sbi->used_clusters; + buf->f_bavail = buf->f_bfree; + buf->f_fsid.val[0] = (unsigned int)id; + buf->f_fsid.val[1] = (unsigned int)(id >> 32); + /* Unicode utf16 255 characters */ + buf->f_namelen = EXFAT_MAX_FILE_LEN * NLS_MAX_CHARSET_SIZE; + return 0; +} + +int exfat_set_vol_flags(struct super_block *sb, unsigned short new_flag) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct pbr64 *bpb; + bool sync = 0; + + /* flags are not changed */ + if (sbi->vol_flag == new_flag) + return 0; + + sbi->vol_flag = new_flag; + + /* skip updating volume dirty flag, + * if this volume has been mounted with read-only + */ + if (sb_rdonly(sb)) + return 0; + + if (!sbi->pbr_bh) { + sbi->pbr_bh = sb_bread(sb, 0); + if (!sbi->pbr_bh) { + exfat_msg(sb, KERN_ERR, "failed to read boot sector"); + return -ENOMEM; + } + } + + bpb = (struct pbr64 *)sbi->pbr_bh->b_data; + bpb->bsx.vol_flags = cpu_to_le16(new_flag); + + if (new_flag == VOL_DIRTY && !buffer_dirty(sbi->pbr_bh)) + sync = true; + else + sync = false; + + set_buffer_uptodate(sbi->pbr_bh); + mark_buffer_dirty(sbi->pbr_bh); + + if (sync) + sync_dirty_buffer(sbi->pbr_bh); + return 0; +} + +static int exfat_show_options(struct seq_file *m, struct dentry *root) +{ + struct super_block *sb = root->d_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct exfat_mount_options *opts = &sbi->options; + + /* Show partition info */ + if (!uid_eq(opts->fs_uid, GLOBAL_ROOT_UID)) + seq_printf(m, ",uid=%u", + from_kuid_munged(&init_user_ns, opts->fs_uid)); + if (!gid_eq(opts->fs_gid, GLOBAL_ROOT_GID)) + seq_printf(m, ",gid=%u", + from_kgid_munged(&init_user_ns, opts->fs_gid)); + seq_printf(m, ",fmask=%04o,dmask=%04o", opts->fs_fmask, opts->fs_dmask); + if (opts->allow_utime) + seq_printf(m, ",allow_utime=%04o", opts->allow_utime); + if (opts->utf8) + seq_puts(m, ",iocharset=utf8"); + else if (sbi->nls_io) + seq_printf(m, ",iocharset=%s", sbi->nls_io->charset); + seq_printf(m, ",bps=%ld", sb->s_blocksize); + if (opts->errors == EXFAT_ERRORS_CONT) + seq_puts(m, ",errors=continue"); + else if (opts->errors == EXFAT_ERRORS_PANIC) + seq_puts(m, ",errors=panic"); + else + seq_puts(m, ",errors=remount-ro"); + if (opts->discard) + seq_puts(m, ",discard"); + if (opts->time_offset) + seq_printf(m, ",time_offset=%d", opts->time_offset); + return 0; +} + +static struct inode *exfat_alloc_inode(struct super_block *sb) +{ + struct exfat_inode_info *ei; + + ei = kmem_cache_alloc(exfat_inode_cachep, GFP_NOFS); + if (!ei) + return NULL; + + init_rwsem(&ei->truncate_lock); + return &ei->vfs_inode; +} + +static void exfat_free_inode(struct inode *inode) +{ + kmem_cache_free(exfat_inode_cachep, EXFAT_I(inode)); +} + +static const struct super_operations exfat_sops = { + .alloc_inode = exfat_alloc_inode, + .free_inode = exfat_free_inode, + .write_inode = exfat_write_inode, + .evict_inode = exfat_evict_inode, + .put_super = exfat_put_super, + .sync_fs = exfat_sync_fs, + .statfs = exfat_statfs, + .show_options = exfat_show_options, +}; + +enum { + Opt_uid, + Opt_gid, + Opt_umask, + Opt_dmask, + Opt_fmask, + Opt_allow_utime, + Opt_charset, + Opt_errors, + Opt_discard, + Opt_time_offset, +}; + +static const struct fs_parameter_spec exfat_param_specs[] = { + fsparam_u32("uid", Opt_uid), + fsparam_u32("gid", Opt_gid), + fsparam_u32oct("umask", Opt_umask), + fsparam_u32oct("dmask", Opt_dmask), + fsparam_u32oct("fmask", Opt_fmask), + fsparam_u32oct("allow_utime", Opt_allow_utime), + fsparam_string("iocharset", Opt_charset), + fsparam_enum("errors", Opt_errors), + fsparam_flag("discard", Opt_discard), + fsparam_s32("time_offset", Opt_time_offset), + {} +}; + +static const struct fs_parameter_enum exfat_param_enums[] = { + { Opt_errors, "continue", EXFAT_ERRORS_CONT }, + { Opt_errors, "panic", EXFAT_ERRORS_PANIC }, + { Opt_errors, "remount-ro", EXFAT_ERRORS_RO }, + {} +}; + +static const struct fs_parameter_description exfat_parameters = { + .name = "exfat", + .specs = exfat_param_specs, + .enums = exfat_param_enums, +}; + +static int exfat_parse_param(struct fs_context *fc, struct fs_parameter *param) +{ + struct exfat_sb_info *sbi = fc->s_fs_info; + struct exfat_mount_options *opts = &sbi->options; + struct fs_parse_result result; + int opt; + + opt = fs_parse(fc, &exfat_parameters, param, &result); + if (opt < 0) + return opt; + + switch (opt) { + case Opt_uid: + opts->fs_uid = make_kuid(current_user_ns(), result.uint_32); + break; + case Opt_gid: + opts->fs_gid = make_kgid(current_user_ns(), result.uint_32); + break; + case Opt_umask: + opts->fs_fmask = result.uint_32; + opts->fs_dmask = result.uint_32; + break; + case Opt_dmask: + opts->fs_dmask = result.uint_32; + break; + case Opt_fmask: + opts->fs_fmask = result.uint_32; + break; + case Opt_allow_utime: + opts->allow_utime = result.uint_32 & 0022; + break; + case Opt_charset: + exfat_free_iocharset(sbi); + opts->iocharset = kstrdup(param->string, GFP_KERNEL); + if (!opts->iocharset) + return -ENOMEM; + break; + case Opt_errors: + opts->errors = result.uint_32; + break; + case Opt_discard: + opts->discard = 1; + break; + case Opt_time_offset: + /* + * Make the limit 24 just in case someone invents something + * unusual. + */ + if (result.int_32 < -24 * 60 || result.int_32 > 24 * 60) + return -EINVAL; + opts->time_offset = result.int_32; + break; + default: + return -EINVAL; + } + + return 0; +} + +static void exfat_hash_init(struct super_block *sb) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + int i; + + spin_lock_init(&sbi->inode_hash_lock); + for (i = 0; i < EXFAT_HASH_SIZE; i++) + INIT_HLIST_HEAD(&sbi->inode_hashtable[i]); +} + +static int exfat_read_root(struct inode *inode) +{ + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct exfat_inode_info *ei = EXFAT_I(inode); + struct exfat_chain cdir; + int num_subdirs, num_clu = 0; + + exfat_chain_set(&ei->dir, sbi->root_dir, 0, ALLOC_FAT_CHAIN); + ei->entry = -1; + ei->start_clu = sbi->root_dir; + ei->flags = ALLOC_FAT_CHAIN; + ei->type = TYPE_DIR; + ei->version = 0; + ei->rwoffset = 0; + ei->hint_bmap.off = EXFAT_EOF_CLUSTER; + ei->hint_stat.eidx = 0; + ei->hint_stat.clu = sbi->root_dir; + ei->hint_femp.eidx = EXFAT_HINT_NONE; + + exfat_chain_set(&cdir, sbi->root_dir, 0, ALLOC_FAT_CHAIN); + if (exfat_count_num_clusters(sb, &cdir, &num_clu)) + return -EIO; + i_size_write(inode, num_clu << sbi->cluster_size_bits); + + num_subdirs = exfat_count_dir_entries(sb, &cdir); + if (num_subdirs < 0) + return -EIO; + set_nlink(inode, num_subdirs + EXFAT_MIN_SUBDIR); + + inode->i_uid = sbi->options.fs_uid; + inode->i_gid = sbi->options.fs_gid; + inode_inc_iversion(inode); + inode->i_generation = 0; + inode->i_mode = exfat_make_mode(sbi, ATTR_SUBDIR, 0777); + inode->i_op = &exfat_dir_inode_operations; + inode->i_fop = &exfat_dir_operations; + + inode->i_blocks = ((i_size_read(inode) + (sbi->cluster_size - 1)) + & ~(sbi->cluster_size - 1)) >> inode->i_blkbits; + EXFAT_I(inode)->i_pos = ((loff_t)sbi->root_dir << 32) | 0xffffffff; + EXFAT_I(inode)->i_size_aligned = i_size_read(inode); + EXFAT_I(inode)->i_size_ondisk = i_size_read(inode); + + exfat_save_attr(inode, ATTR_SUBDIR); + inode->i_mtime = inode->i_atime = inode->i_ctime = ei->i_crtime = + current_time(inode); + exfat_cache_init_inode(inode); + return 0; +} + +static struct pbr *exfat_read_pbr_with_logical_sector(struct super_block *sb, + struct buffer_head **prev_bh) +{ + struct pbr *p_pbr = (struct pbr *) (*prev_bh)->b_data; + unsigned short logical_sect = 0; + + logical_sect = 1 << p_pbr->bsx.f64.sect_size_bits; + + if (!is_power_of_2(logical_sect) || + logical_sect < 512 || logical_sect > 4096) { + exfat_msg(sb, KERN_ERR, "bogus logical sector size %u", + logical_sect); + return NULL; + } + + if (logical_sect < sb->s_blocksize) { + exfat_msg(sb, KERN_ERR, + "logical sector size too small for device (logical sector size = %u)", + logical_sect); + return NULL; + } + + if (logical_sect > sb->s_blocksize) { + struct buffer_head *bh = NULL; + + __brelse(*prev_bh); + *prev_bh = NULL; + + if (!sb_set_blocksize(sb, logical_sect)) { + exfat_msg(sb, KERN_ERR, + "unable to set blocksize %u", logical_sect); + return NULL; + } + bh = sb_bread(sb, 0); + if (!bh) { + exfat_msg(sb, KERN_ERR, + "unable to read boot sector (logical sector size = %lu)", + sb->s_blocksize); + return NULL; + } + + *prev_bh = bh; + p_pbr = (struct pbr *) bh->b_data; + } + return p_pbr; +} + +/* mount the file system volume */ +static int __exfat_fill_super(struct super_block *sb) +{ + int ret; + struct pbr *p_pbr; + struct pbr64 *p_bpb; + struct buffer_head *bh; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + + /* set block size to read super block */ + sb_min_blocksize(sb, 512); + + /* read boot sector */ + bh = sb_bread(sb, 0); + if (!bh) { + exfat_msg(sb, KERN_ERR, "unable to read boot sector"); + return -EIO; + } + + /* PRB is read */ + p_pbr = (struct pbr *)bh->b_data; + + /* check the validity of PBR */ + if (le16_to_cpu((p_pbr->signature)) != PBR_SIGNATURE) { + exfat_msg(sb, KERN_ERR, "invalid boot record signature"); + ret = -EINVAL; + goto free_bh; + } + + + /* check logical sector size */ + p_pbr = exfat_read_pbr_with_logical_sector(sb, &bh); + if (!p_pbr) { + ret = -EIO; + goto free_bh; + } + + /* + * res_zero field must be filled with zero to prevent mounting + * from FAT volume. + */ + if (memchr_inv(p_pbr->bpb.f64.res_zero, 0, + sizeof(p_pbr->bpb.f64.res_zero))) { + ret = -EINVAL; + goto free_bh; + } + + p_bpb = (struct pbr64 *)p_pbr; + if (!p_bpb->bsx.num_fats) { + exfat_msg(sb, KERN_ERR, "bogus number of FAT structure"); + ret = -EINVAL; + goto free_bh; + } + + sbi->sect_per_clus = 1 << p_bpb->bsx.sect_per_clus_bits; + sbi->sect_per_clus_bits = p_bpb->bsx.sect_per_clus_bits; + sbi->cluster_size_bits = sbi->sect_per_clus_bits + sb->s_blocksize_bits; + sbi->cluster_size = 1 << sbi->cluster_size_bits; + sbi->num_FAT_sectors = le32_to_cpu(p_bpb->bsx.fat_length); + sbi->FAT1_start_sector = le32_to_cpu(p_bpb->bsx.fat_offset); + sbi->FAT2_start_sector = p_bpb->bsx.num_fats == 1 ? + sbi->FAT1_start_sector : + sbi->FAT1_start_sector + sbi->num_FAT_sectors; + sbi->data_start_sector = le32_to_cpu(p_bpb->bsx.clu_offset); + sbi->num_sectors = le64_to_cpu(p_bpb->bsx.vol_length); + /* because the cluster index starts with 2 */ + sbi->num_clusters = le32_to_cpu(p_bpb->bsx.clu_count) + + EXFAT_RESERVED_CLUSTERS; + + sbi->root_dir = le32_to_cpu(p_bpb->bsx.root_cluster); + sbi->dentries_per_clu = 1 << + (sbi->cluster_size_bits - DENTRY_SIZE_BITS); + + sbi->vol_flag = le16_to_cpu(p_bpb->bsx.vol_flags); + sbi->clu_srch_ptr = EXFAT_FIRST_CLUSTER; + sbi->used_clusters = EXFAT_CLUSTERS_UNTRACKED; + + if (le16_to_cpu(p_bpb->bsx.vol_flags) & VOL_DIRTY) { + sbi->vol_flag |= VOL_DIRTY; + exfat_msg(sb, KERN_WARNING, + "Volume was not properly unmounted. Some data may be corrupt. Please run fsck."); + } + + /* exFAT file size is limited by a disk volume size */ + sb->s_maxbytes = (u64)(sbi->num_clusters - EXFAT_RESERVED_CLUSTERS) << + sbi->cluster_size_bits; + + ret = exfat_create_upcase_table(sb); + if (ret) { + exfat_msg(sb, KERN_ERR, "failed to load upcase table"); + goto free_bh; + } + + ret = exfat_load_bitmap(sb); + if (ret) { + exfat_msg(sb, KERN_ERR, "failed to load alloc-bitmap"); + goto free_upcase_table; + } + + ret = exfat_count_used_clusters(sb, &sbi->used_clusters); + if (ret) { + exfat_msg(sb, KERN_ERR, "failed to scan clusters"); + goto free_alloc_bitmap; + } + + return 0; + +free_alloc_bitmap: + exfat_free_bitmap(sbi); +free_upcase_table: + exfat_free_upcase_table(sbi); +free_bh: + brelse(bh); + return ret; +} + +static int exfat_fill_super(struct super_block *sb, struct fs_context *fc) +{ + struct exfat_sb_info *sbi = sb->s_fs_info; + struct exfat_mount_options *opts = &sbi->options; + struct inode *root_inode; + int err; + + if (opts->allow_utime == (unsigned short)-1) + opts->allow_utime = ~opts->fs_dmask & 0022; + + if (opts->discard) { + struct request_queue *q = bdev_get_queue(sb->s_bdev); + + if (!blk_queue_discard(q)) + exfat_msg(sb, KERN_WARNING, + "mounting with \"discard\" option, but the device does not support discard"); + opts->discard = 0; + } + + sb->s_flags |= SB_NODIRATIME; + sb->s_magic = EXFAT_SUPER_MAGIC; + sb->s_op = &exfat_sops; + + sb->s_time_gran = 1; + sb->s_time_min = EXFAT_MIN_TIMESTAMP_SECS; + sb->s_time_max = EXFAT_MAX_TIMESTAMP_SECS; + + err = __exfat_fill_super(sb); + if (err) { + exfat_msg(sb, KERN_ERR, "failed to recognize exfat type"); + goto check_nls_io; + } + + /* set up enough so that it can read an inode */ + exfat_hash_init(sb); + + if (!strcmp(sbi->options.iocharset, "utf8")) + opts->utf8 = 1; + else { + sbi->nls_io = load_nls(sbi->options.iocharset); + if (!sbi->nls_io) { + exfat_msg(sb, KERN_ERR, "IO charset %s not found", + sbi->options.iocharset); + err = -EINVAL; + goto free_table; + } + } + + if (sbi->options.utf8) + sb->s_d_op = &exfat_utf8_dentry_ops; + else + sb->s_d_op = &exfat_dentry_ops; + + root_inode = new_inode(sb); + if (!root_inode) { + exfat_msg(sb, KERN_ERR, "failed to allocate root inode."); + err = -ENOMEM; + goto free_table; + } + + root_inode->i_ino = EXFAT_ROOT_INO; + inode_set_iversion(root_inode, 1); + err = exfat_read_root(root_inode); + if (err) { + exfat_msg(sb, KERN_ERR, "failed to initialize root inode."); + goto put_inode; + } + + exfat_hash_inode(root_inode, EXFAT_I(root_inode)->i_pos); + insert_inode_hash(root_inode); + + sb->s_root = d_make_root(root_inode); + if (!sb->s_root) { + exfat_msg(sb, KERN_ERR, "failed to get the root dentry"); + err = -ENOMEM; + goto put_inode; + } + + return 0; + +put_inode: + iput(root_inode); + sb->s_root = NULL; + +free_table: + exfat_free_upcase_table(sbi); + exfat_free_bitmap(sbi); + +check_nls_io: + unload_nls(sbi->nls_io); + exfat_free_iocharset(sbi); + sb->s_fs_info = NULL; + kfree(sbi); + return err; +} + +static int exfat_get_tree(struct fs_context *fc) +{ + return get_tree_bdev(fc, exfat_fill_super); +} + +static void exfat_free(struct fs_context *fc) +{ + kfree(fc->s_fs_info); +} + +static const struct fs_context_operations exfat_context_ops = { + .parse_param = exfat_parse_param, + .get_tree = exfat_get_tree, + .free = exfat_free, +}; + +static int exfat_init_fs_context(struct fs_context *fc) +{ + struct exfat_sb_info *sbi; + + sbi = kzalloc(sizeof(struct exfat_sb_info), GFP_KERNEL); + if (!sbi) + return -ENOMEM; + + mutex_init(&sbi->s_lock); + ratelimit_state_init(&sbi->ratelimit, DEFAULT_RATELIMIT_INTERVAL, + DEFAULT_RATELIMIT_BURST); + + sbi->options.fs_uid = current_uid(); + sbi->options.fs_gid = current_gid(); + sbi->options.fs_fmask = current->fs->umask; + sbi->options.fs_dmask = current->fs->umask; + sbi->options.allow_utime = -1; + sbi->options.iocharset = exfat_default_iocharset; + sbi->options.errors = EXFAT_ERRORS_RO; + + fc->s_fs_info = sbi; + fc->ops = &exfat_context_ops; + return 0; +} + +static struct file_system_type exfat_fs_type = { + .owner = THIS_MODULE, + .name = "exfat", + .init_fs_context = exfat_init_fs_context, + .parameters = &exfat_parameters, + .kill_sb = kill_block_super, + .fs_flags = FS_REQUIRES_DEV, +}; + +static void exfat_inode_init_once(void *foo) +{ + struct exfat_inode_info *ei = (struct exfat_inode_info *)foo; + + INIT_HLIST_NODE(&ei->i_hash_fat); + inode_init_once(&ei->vfs_inode); +} + +static int __init init_exfat_fs(void) +{ + int err; + + err = exfat_cache_init(); + if (err) + return err; + + exfat_inode_cachep = kmem_cache_create("exfat_inode_cache", + sizeof(struct exfat_inode_info), + 0, SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, + exfat_inode_init_once); + if (!exfat_inode_cachep) { + err = -ENOMEM; + goto shutdown_cache; + } + + err = register_filesystem(&exfat_fs_type); + if (err) + goto destroy_cache; + + return 0; + +destroy_cache: + kmem_cache_destroy(exfat_inode_cachep); +shutdown_cache: + exfat_cache_shutdown(); + return err; +} + +static void __exit exit_exfat_fs(void) +{ + /* + * Make sure all delayed rcu free inodes are flushed before we + * destroy cache. + */ + rcu_barrier(); + kmem_cache_destroy(exfat_inode_cachep); + unregister_filesystem(&exfat_fs_type); + exfat_cache_shutdown(); +} + +module_init(init_exfat_fs); +module_exit(exit_exfat_fs); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("exFAT filesystem support"); +MODULE_AUTHOR("Samsung Electronics Co., Ltd."); From 3da82bd8f080caa5d8ba0641c7e15357b6c70d17 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Mon, 2 Mar 2020 15:21:34 +0900 Subject: [PATCH 036/592] exfat: add inode operations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds the implementation of inode operations for exfat. Signed-off-by: Namjae Jeon Signed-off-by: Sungjong Seo Reviewed-by: Pali Rohár Reviewed-by: Christoph Hellwig Signed-off-by: Al Viro Signed-off-by: Park Ju Hyung --- inode.c | 671 ++++++++++++++++++++++++++ namei.c | 1448 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 2119 insertions(+) create mode 100644 inode.c create mode 100644 namei.c diff --git a/inode.c b/inode.c new file mode 100644 index 000000000000..06887492f54b --- /dev/null +++ b/inode.c @@ -0,0 +1,671 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "exfat_raw.h" +#include "exfat_fs.h" + +static int __exfat_write_inode(struct inode *inode, int sync) +{ + int ret = -EIO; + unsigned long long on_disk_size; + struct exfat_dentry *ep, *ep2; + struct exfat_entry_set_cache *es = NULL; + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct exfat_inode_info *ei = EXFAT_I(inode); + bool is_dir = (ei->type == TYPE_DIR) ? true : false; + + if (inode->i_ino == EXFAT_ROOT_INO) + return 0; + + /* + * If the indode is already unlinked, there is no need for updating it. + */ + if (ei->dir.dir == DIR_DELETED) + return 0; + + if (is_dir && ei->dir.dir == sbi->root_dir && ei->entry == -1) + return 0; + + exfat_set_vol_flags(sb, VOL_DIRTY); + + /* get the directory entry of given file or directory */ + es = exfat_get_dentry_set(sb, &(ei->dir), ei->entry, ES_ALL_ENTRIES, + &ep); + if (!es) + return -EIO; + ep2 = ep + 1; + + ep->dentry.file.attr = cpu_to_le16(exfat_make_attr(inode)); + + /* set FILE_INFO structure using the acquired struct exfat_dentry */ + exfat_set_entry_time(sbi, &ei->i_crtime, + &ep->dentry.file.create_tz, + &ep->dentry.file.create_time, + &ep->dentry.file.create_date, + &ep->dentry.file.create_time_ms); + exfat_set_entry_time(sbi, &inode->i_mtime, + &ep->dentry.file.modify_tz, + &ep->dentry.file.modify_time, + &ep->dentry.file.modify_date, + &ep->dentry.file.modify_time_ms); + exfat_set_entry_time(sbi, &inode->i_atime, + &ep->dentry.file.access_tz, + &ep->dentry.file.access_time, + &ep->dentry.file.access_date, + NULL); + + /* File size should be zero if there is no cluster allocated */ + on_disk_size = i_size_read(inode); + + if (ei->start_clu == EXFAT_EOF_CLUSTER) + on_disk_size = 0; + + ep2->dentry.stream.valid_size = cpu_to_le64(on_disk_size); + ep2->dentry.stream.size = ep2->dentry.stream.valid_size; + + ret = exfat_update_dir_chksum_with_entry_set(sb, es, sync); + kfree(es); + return ret; +} + +int exfat_write_inode(struct inode *inode, struct writeback_control *wbc) +{ + int ret; + + mutex_lock(&EXFAT_SB(inode->i_sb)->s_lock); + ret = __exfat_write_inode(inode, wbc->sync_mode == WB_SYNC_ALL); + mutex_unlock(&EXFAT_SB(inode->i_sb)->s_lock); + + return ret; +} + +void exfat_sync_inode(struct inode *inode) +{ + lockdep_assert_held(&EXFAT_SB(inode->i_sb)->s_lock); + __exfat_write_inode(inode, 1); +} + +/* + * Input: inode, (logical) clu_offset, target allocation area + * Output: errcode, cluster number + * *clu = (~0), if it's unable to allocate a new cluster + */ +static int exfat_map_cluster(struct inode *inode, unsigned int clu_offset, + unsigned int *clu, int create) +{ + int ret, modified = false; + unsigned int last_clu; + struct exfat_chain new_clu; + struct exfat_dentry *ep; + struct exfat_entry_set_cache *es = NULL; + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct exfat_inode_info *ei = EXFAT_I(inode); + unsigned int local_clu_offset = clu_offset; + unsigned int num_to_be_allocated = 0, num_clusters = 0; + + ei->rwoffset = EXFAT_CLU_TO_B(clu_offset, sbi); + + if (EXFAT_I(inode)->i_size_ondisk > 0) + num_clusters = + EXFAT_B_TO_CLU_ROUND_UP(EXFAT_I(inode)->i_size_ondisk, + sbi); + + if (clu_offset >= num_clusters) + num_to_be_allocated = clu_offset - num_clusters + 1; + + if (!create && (num_to_be_allocated > 0)) { + *clu = EXFAT_EOF_CLUSTER; + return 0; + } + + *clu = last_clu = ei->start_clu; + + if (ei->flags == ALLOC_NO_FAT_CHAIN) { + if (clu_offset > 0 && *clu != EXFAT_EOF_CLUSTER) { + last_clu += clu_offset - 1; + + if (clu_offset == num_clusters) + *clu = EXFAT_EOF_CLUSTER; + else + *clu += clu_offset; + } + } else if (ei->type == TYPE_FILE) { + unsigned int fclus = 0; + int err = exfat_get_cluster(inode, clu_offset, + &fclus, clu, &last_clu, 1); + if (err) + return -EIO; + + clu_offset -= fclus; + } else { + /* hint information */ + if (clu_offset > 0 && ei->hint_bmap.off != EXFAT_EOF_CLUSTER && + ei->hint_bmap.off > 0 && clu_offset >= ei->hint_bmap.off) { + clu_offset -= ei->hint_bmap.off; + /* hint_bmap.clu should be valid */ + WARN_ON(ei->hint_bmap.clu < 2); + *clu = ei->hint_bmap.clu; + } + + while (clu_offset > 0 && *clu != EXFAT_EOF_CLUSTER) { + last_clu = *clu; + if (exfat_get_next_cluster(sb, clu)) + return -EIO; + clu_offset--; + } + } + + if (*clu == EXFAT_EOF_CLUSTER) { + exfat_set_vol_flags(sb, VOL_DIRTY); + + new_clu.dir = (last_clu == EXFAT_EOF_CLUSTER) ? + EXFAT_EOF_CLUSTER : last_clu + 1; + new_clu.size = 0; + new_clu.flags = ei->flags; + + /* allocate a cluster */ + if (num_to_be_allocated < 1) { + /* Broken FAT (i_sze > allocated FAT) */ + exfat_fs_error(sb, "broken FAT chain."); + return -EIO; + } + + ret = exfat_alloc_cluster(inode, num_to_be_allocated, &new_clu); + if (ret) + return ret; + + if (new_clu.dir == EXFAT_EOF_CLUSTER || + new_clu.dir == EXFAT_FREE_CLUSTER) { + exfat_fs_error(sb, + "bogus cluster new allocated (last_clu : %u, new_clu : %u)", + last_clu, new_clu.dir); + return -EIO; + } + + /* append to the FAT chain */ + if (last_clu == EXFAT_EOF_CLUSTER) { + if (new_clu.flags == ALLOC_FAT_CHAIN) + ei->flags = ALLOC_FAT_CHAIN; + ei->start_clu = new_clu.dir; + modified = true; + } else { + if (new_clu.flags != ei->flags) { + /* no-fat-chain bit is disabled, + * so fat-chain should be synced with + * alloc-bitmap + */ + exfat_chain_cont_cluster(sb, ei->start_clu, + num_clusters); + ei->flags = ALLOC_FAT_CHAIN; + modified = true; + } + if (new_clu.flags == ALLOC_FAT_CHAIN) + if (exfat_ent_set(sb, last_clu, new_clu.dir)) + return -EIO; + } + + num_clusters += num_to_be_allocated; + *clu = new_clu.dir; + + if (ei->dir.dir != DIR_DELETED) { + es = exfat_get_dentry_set(sb, &(ei->dir), ei->entry, + ES_ALL_ENTRIES, &ep); + if (!es) + return -EIO; + /* get stream entry */ + ep++; + + /* update directory entry */ + if (modified) { + if (ep->dentry.stream.flags != ei->flags) + ep->dentry.stream.flags = ei->flags; + + if (le32_to_cpu(ep->dentry.stream.start_clu) != + ei->start_clu) + ep->dentry.stream.start_clu = + cpu_to_le32(ei->start_clu); + + ep->dentry.stream.valid_size = + cpu_to_le64(i_size_read(inode)); + ep->dentry.stream.size = + ep->dentry.stream.valid_size; + } + + if (exfat_update_dir_chksum_with_entry_set(sb, es, + inode_needs_sync(inode))) + return -EIO; + kfree(es); + + } /* end of if != DIR_DELETED */ + + inode->i_blocks += + num_to_be_allocated << sbi->sect_per_clus_bits; + + /* + * Move *clu pointer along FAT chains (hole care) because the + * caller of this function expect *clu to be the last cluster. + * This only works when num_to_be_allocated >= 2, + * *clu = (the first cluster of the allocated chain) => + * (the last cluster of ...) + */ + if (ei->flags == ALLOC_NO_FAT_CHAIN) { + *clu += num_to_be_allocated - 1; + } else { + while (num_to_be_allocated > 1) { + if (exfat_get_next_cluster(sb, clu)) + return -EIO; + num_to_be_allocated--; + } + } + + } + + /* hint information */ + ei->hint_bmap.off = local_clu_offset; + ei->hint_bmap.clu = *clu; + + return 0; +} + +static int exfat_map_new_buffer(struct exfat_inode_info *ei, + struct buffer_head *bh, loff_t pos) +{ + if (buffer_delay(bh) && pos > ei->i_size_aligned) + return -EIO; + set_buffer_new(bh); + + /* + * Adjust i_size_aligned if i_size_ondisk is bigger than it. + */ + if (ei->i_size_ondisk > ei->i_size_aligned) + ei->i_size_aligned = ei->i_size_ondisk; + return 0; +} + +static int exfat_get_block(struct inode *inode, sector_t iblock, + struct buffer_head *bh_result, int create) +{ + struct exfat_inode_info *ei = EXFAT_I(inode); + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + unsigned long max_blocks = bh_result->b_size >> inode->i_blkbits; + int err = 0; + unsigned long mapped_blocks = 0; + unsigned int cluster, sec_offset; + sector_t last_block; + sector_t phys = 0; + loff_t pos; + + mutex_lock(&sbi->s_lock); + last_block = EXFAT_B_TO_BLK_ROUND_UP(i_size_read(inode), sb); + if (iblock >= last_block && !create) + goto done; + + /* Is this block already allocated? */ + err = exfat_map_cluster(inode, iblock >> sbi->sect_per_clus_bits, + &cluster, create); + if (err) { + if (err != -ENOSPC) + exfat_fs_error_ratelimit(sb, + "failed to bmap (inode : %p iblock : %llu, err : %d)", + inode, (unsigned long long)iblock, err); + goto unlock_ret; + } + + if (cluster == EXFAT_EOF_CLUSTER) + goto done; + + /* sector offset in cluster */ + sec_offset = iblock & (sbi->sect_per_clus - 1); + + phys = exfat_cluster_to_sector(sbi, cluster) + sec_offset; + mapped_blocks = sbi->sect_per_clus - sec_offset; + max_blocks = min(mapped_blocks, max_blocks); + + /* Treat newly added block / cluster */ + if (iblock < last_block) + create = 0; + + if (create || buffer_delay(bh_result)) { + pos = EXFAT_BLK_TO_B((iblock + 1), sb); + if (ei->i_size_ondisk < pos) + ei->i_size_ondisk = pos; + } + + if (create) { + err = exfat_map_new_buffer(ei, bh_result, pos); + if (err) { + exfat_fs_error(sb, + "requested for bmap out of range(pos : (%llu) > i_size_aligned(%llu)\n", + pos, ei->i_size_aligned); + goto unlock_ret; + } + } + + if (buffer_delay(bh_result)) + clear_buffer_delay(bh_result); + map_bh(bh_result, sb, phys); +done: + bh_result->b_size = EXFAT_BLK_TO_B(max_blocks, sb); +unlock_ret: + mutex_unlock(&sbi->s_lock); + return err; +} + +static int exfat_readpage(struct file *file, struct page *page) +{ + return mpage_readpage(page, exfat_get_block); +} + +static int exfat_readpages(struct file *file, struct address_space *mapping, + struct list_head *pages, unsigned int nr_pages) +{ + return mpage_readpages(mapping, pages, nr_pages, exfat_get_block); +} + +static int exfat_writepage(struct page *page, struct writeback_control *wbc) +{ + return block_write_full_page(page, exfat_get_block, wbc); +} + +static int exfat_writepages(struct address_space *mapping, + struct writeback_control *wbc) +{ + return mpage_writepages(mapping, wbc, exfat_get_block); +} + +static void exfat_write_failed(struct address_space *mapping, loff_t to) +{ + struct inode *inode = mapping->host; + + if (to > i_size_read(inode)) { + truncate_pagecache(inode, i_size_read(inode)); + exfat_truncate(inode, EXFAT_I(inode)->i_size_aligned); + } +} + +static int exfat_write_begin(struct file *file, struct address_space *mapping, + loff_t pos, unsigned int len, unsigned int flags, + struct page **pagep, void **fsdata) +{ + int ret; + + *pagep = NULL; + ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata, + exfat_get_block, + &EXFAT_I(mapping->host)->i_size_ondisk); + + if (ret < 0) + exfat_write_failed(mapping, pos+len); + + return ret; +} + +static int exfat_write_end(struct file *file, struct address_space *mapping, + loff_t pos, unsigned int len, unsigned int copied, + struct page *pagep, void *fsdata) +{ + struct inode *inode = mapping->host; + struct exfat_inode_info *ei = EXFAT_I(inode); + int err; + + err = generic_write_end(file, mapping, pos, len, copied, pagep, fsdata); + + if (EXFAT_I(inode)->i_size_aligned < i_size_read(inode)) { + exfat_fs_error(inode->i_sb, + "invalid size(size(%llu) > aligned(%llu)\n", + i_size_read(inode), EXFAT_I(inode)->i_size_aligned); + return -EIO; + } + + if (err < len) + exfat_write_failed(mapping, pos+len); + + if (!(err < 0) && !(ei->attr & ATTR_ARCHIVE)) { + inode->i_mtime = inode->i_ctime = current_time(inode); + ei->attr |= ATTR_ARCHIVE; + mark_inode_dirty(inode); + } + + return err; +} + +static ssize_t exfat_direct_IO(struct kiocb *iocb, struct iov_iter *iter) +{ + struct address_space *mapping = iocb->ki_filp->f_mapping; + struct inode *inode = mapping->host; + loff_t size = iocb->ki_pos + iov_iter_count(iter); + int rw = iov_iter_rw(iter); + ssize_t ret; + + if (rw == WRITE) { + /* + * FIXME: blockdev_direct_IO() doesn't use ->write_begin(), + * so we need to update the ->i_size_aligned to block boundary. + * + * But we must fill the remaining area or hole by nul for + * updating ->i_size_aligned + * + * Return 0, and fallback to normal buffered write. + */ + if (EXFAT_I(inode)->i_size_aligned < size) + return 0; + } + + /* + * Need to use the DIO_LOCKING for avoiding the race + * condition of exfat_get_block() and ->truncate(). + */ + ret = blockdev_direct_IO(iocb, inode, iter, exfat_get_block); + if (ret < 0 && (rw & WRITE)) + exfat_write_failed(mapping, size); + return ret; +} + +static sector_t exfat_aop_bmap(struct address_space *mapping, sector_t block) +{ + sector_t blocknr; + + /* exfat_get_cluster() assumes the requested blocknr isn't truncated. */ + down_read(&EXFAT_I(mapping->host)->truncate_lock); + blocknr = generic_block_bmap(mapping, block, exfat_get_block); + up_read(&EXFAT_I(mapping->host)->truncate_lock); + return blocknr; +} + +/* + * exfat_block_truncate_page() zeroes out a mapping from file offset `from' + * up to the end of the block which corresponds to `from'. + * This is required during truncate to physically zeroout the tail end + * of that block so it doesn't yield old data if the file is later grown. + * Also, avoid causing failure from fsx for cases of "data past EOF" + */ +int exfat_block_truncate_page(struct inode *inode, loff_t from) +{ + return block_truncate_page(inode->i_mapping, from, exfat_get_block); +} + +static const struct address_space_operations exfat_aops = { + .readpage = exfat_readpage, + .readpages = exfat_readpages, + .writepage = exfat_writepage, + .writepages = exfat_writepages, + .write_begin = exfat_write_begin, + .write_end = exfat_write_end, + .direct_IO = exfat_direct_IO, + .bmap = exfat_aop_bmap +}; + +static inline unsigned long exfat_hash(loff_t i_pos) +{ + return hash_32(i_pos, EXFAT_HASH_BITS); +} + +void exfat_hash_inode(struct inode *inode, loff_t i_pos) +{ + struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb); + struct hlist_head *head = sbi->inode_hashtable + exfat_hash(i_pos); + + spin_lock(&sbi->inode_hash_lock); + EXFAT_I(inode)->i_pos = i_pos; + hlist_add_head(&EXFAT_I(inode)->i_hash_fat, head); + spin_unlock(&sbi->inode_hash_lock); +} + +void exfat_unhash_inode(struct inode *inode) +{ + struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb); + + spin_lock(&sbi->inode_hash_lock); + hlist_del_init(&EXFAT_I(inode)->i_hash_fat); + EXFAT_I(inode)->i_pos = 0; + spin_unlock(&sbi->inode_hash_lock); +} + +struct inode *exfat_iget(struct super_block *sb, loff_t i_pos) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct exfat_inode_info *info; + struct hlist_head *head = sbi->inode_hashtable + exfat_hash(i_pos); + struct inode *inode = NULL; + + spin_lock(&sbi->inode_hash_lock); + hlist_for_each_entry(info, head, i_hash_fat) { + WARN_ON(info->vfs_inode.i_sb != sb); + + if (i_pos != info->i_pos) + continue; + inode = igrab(&info->vfs_inode); + if (inode) + break; + } + spin_unlock(&sbi->inode_hash_lock); + return inode; +} + +/* doesn't deal with root inode */ +static int exfat_fill_inode(struct inode *inode, struct exfat_dir_entry *info) +{ + struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb); + struct exfat_inode_info *ei = EXFAT_I(inode); + loff_t size = info->size; + + memcpy(&ei->dir, &info->dir, sizeof(struct exfat_chain)); + ei->entry = info->entry; + ei->attr = info->attr; + ei->start_clu = info->start_clu; + ei->flags = info->flags; + ei->type = info->type; + + ei->version = 0; + ei->hint_stat.eidx = 0; + ei->hint_stat.clu = info->start_clu; + ei->hint_femp.eidx = EXFAT_HINT_NONE; + ei->rwoffset = 0; + ei->hint_bmap.off = EXFAT_EOF_CLUSTER; + ei->i_pos = 0; + + inode->i_uid = sbi->options.fs_uid; + inode->i_gid = sbi->options.fs_gid; + inode_inc_iversion(inode); + inode->i_generation = prandom_u32(); + + if (info->attr & ATTR_SUBDIR) { /* directory */ + inode->i_generation &= ~1; + inode->i_mode = exfat_make_mode(sbi, info->attr, 0777); + inode->i_op = &exfat_dir_inode_operations; + inode->i_fop = &exfat_dir_operations; + set_nlink(inode, info->num_subdirs); + } else { /* regular file */ + inode->i_generation |= 1; + inode->i_mode = exfat_make_mode(sbi, info->attr, 0777); + inode->i_op = &exfat_file_inode_operations; + inode->i_fop = &exfat_file_operations; + inode->i_mapping->a_ops = &exfat_aops; + inode->i_mapping->nrpages = 0; + } + + i_size_write(inode, size); + + /* ondisk and aligned size should be aligned with block size */ + if (size & (inode->i_sb->s_blocksize - 1)) { + size |= (inode->i_sb->s_blocksize - 1); + size++; + } + + ei->i_size_aligned = size; + ei->i_size_ondisk = size; + + exfat_save_attr(inode, info->attr); + + inode->i_blocks = ((i_size_read(inode) + (sbi->cluster_size - 1)) & + ~(sbi->cluster_size - 1)) >> inode->i_blkbits; + inode->i_mtime = info->mtime; + inode->i_ctime = info->mtime; + ei->i_crtime = info->crtime; + inode->i_atime = info->atime; + + exfat_cache_init_inode(inode); + + return 0; +} + +struct inode *exfat_build_inode(struct super_block *sb, + struct exfat_dir_entry *info, loff_t i_pos) +{ + struct inode *inode; + int err; + + inode = exfat_iget(sb, i_pos); + if (inode) + goto out; + inode = new_inode(sb); + if (!inode) { + inode = ERR_PTR(-ENOMEM); + goto out; + } + inode->i_ino = iunique(sb, EXFAT_ROOT_INO); + inode_set_iversion(inode, 1); + err = exfat_fill_inode(inode, info); + if (err) { + iput(inode); + inode = ERR_PTR(err); + goto out; + } + exfat_hash_inode(inode, i_pos); + insert_inode_hash(inode); +out: + return inode; +} + +void exfat_evict_inode(struct inode *inode) +{ + truncate_inode_pages(&inode->i_data, 0); + + if (!inode->i_nlink) { + i_size_write(inode, 0); + mutex_lock(&EXFAT_SB(inode->i_sb)->s_lock); + __exfat_truncate(inode, 0); + mutex_unlock(&EXFAT_SB(inode->i_sb)->s_lock); + } + + invalidate_inode_buffers(inode); + clear_inode(inode); + exfat_cache_inval_inode(inode); + exfat_unhash_inode(inode); +} diff --git a/namei.c b/namei.c new file mode 100644 index 000000000000..a8681d91f569 --- /dev/null +++ b/namei.c @@ -0,0 +1,1448 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + */ + +#include +#include +#include +#include +#include + +#include "exfat_raw.h" +#include "exfat_fs.h" + +static inline unsigned long exfat_d_version(struct dentry *dentry) +{ + return (unsigned long) dentry->d_fsdata; +} + +static inline void exfat_d_version_set(struct dentry *dentry, + unsigned long version) +{ + dentry->d_fsdata = (void *) version; +} + +/* + * If new entry was created in the parent, it could create the 8.3 alias (the + * shortname of logname). So, the parent may have the negative-dentry which + * matches the created 8.3 alias. + * + * If it happened, the negative dentry isn't actually negative anymore. So, + * drop it. + */ +static int exfat_d_revalidate(struct dentry *dentry, unsigned int flags) +{ + int ret; + + if (flags & LOOKUP_RCU) + return -ECHILD; + + /* + * This is not negative dentry. Always valid. + * + * Note, rename() to existing directory entry will have ->d_inode, and + * will use existing name which isn't specified name by user. + * + * We may be able to drop this positive dentry here. But dropping + * positive dentry isn't good idea. So it's unsupported like + * rename("filename", "FILENAME") for now. + */ + if (d_really_is_positive(dentry)) + return 1; + + /* + * Drop the negative dentry, in order to make sure to use the case + * sensitive name which is specified by user if this is for creation. + */ + if (flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET)) + return 0; + + spin_lock(&dentry->d_lock); + ret = inode_eq_iversion(d_inode(dentry->d_parent), + exfat_d_version(dentry)); + spin_unlock(&dentry->d_lock); + return ret; +} + +/* returns the length of a struct qstr, ignoring trailing dots */ +static unsigned int exfat_striptail_len(unsigned int len, const char *name) +{ + while (len && name[len - 1] == '.') + len--; + return len; +} + +/* + * Compute the hash for the exfat name corresponding to the dentry. If the name + * is invalid, we leave the hash code unchanged so that the existing dentry can + * be used. The exfat fs routines will return ENOENT or EINVAL as appropriate. + */ +static int exfat_d_hash(const struct dentry *dentry, struct qstr *qstr) +{ + struct super_block *sb = dentry->d_sb; + struct nls_table *t = EXFAT_SB(sb)->nls_io; + const unsigned char *name = qstr->name; + unsigned int len = exfat_striptail_len(qstr->len, qstr->name); + unsigned long hash = init_name_hash(dentry); + int i, charlen; + wchar_t c; + + for (i = 0; i < len; i += charlen) { + charlen = t->char2uni(&name[i], len - i, &c); + if (charlen < 0) + return charlen; + hash = partial_name_hash(exfat_toupper(sb, c), hash); + } + + qstr->hash = end_name_hash(hash); + return 0; +} + +static int exfat_d_cmp(const struct dentry *dentry, unsigned int len, + const char *str, const struct qstr *name) +{ + struct super_block *sb = dentry->d_sb; + struct nls_table *t = EXFAT_SB(sb)->nls_io; + unsigned int alen = exfat_striptail_len(name->len, name->name); + unsigned int blen = exfat_striptail_len(len, str); + wchar_t c1, c2; + int charlen, i; + + if (alen != blen) + return 1; + + for (i = 0; i < len; i += charlen) { + charlen = t->char2uni(&name->name[i], alen - i, &c1); + if (charlen < 0) + return 1; + if (charlen != t->char2uni(&str[i], blen - i, &c2)) + return 1; + + if (exfat_toupper(sb, c1) != exfat_toupper(sb, c2)) + return 1; + } + + return 0; +} + +const struct dentry_operations exfat_dentry_ops = { + .d_revalidate = exfat_d_revalidate, + .d_hash = exfat_d_hash, + .d_compare = exfat_d_cmp, +}; + +static int exfat_utf8_d_hash(const struct dentry *dentry, struct qstr *qstr) +{ + struct super_block *sb = dentry->d_sb; + const unsigned char *name = qstr->name; + unsigned int len = exfat_striptail_len(qstr->len, qstr->name); + unsigned long hash = init_name_hash(dentry); + int i, charlen; + unicode_t u; + + for (i = 0; i < len; i += charlen) { + charlen = utf8_to_utf32(&name[i], len - i, &u); + if (charlen < 0) + return charlen; + + /* + * Convert to UTF-16: code points above U+FFFF are encoded as + * surrogate pairs. + * exfat_toupper() works only for code points up to the U+FFFF. + */ + if (u > 0xFFFF) { + hash = partial_name_hash(exfat_high_surrogate(u), hash); + hash = partial_name_hash(exfat_low_surrogate(u), hash); + } else { + hash = partial_name_hash(exfat_toupper(sb, u), hash); + } + } + + qstr->hash = end_name_hash(hash); + return 0; +} + +static int exfat_utf8_d_cmp(const struct dentry *dentry, unsigned int len, + const char *str, const struct qstr *name) +{ + struct super_block *sb = dentry->d_sb; + unsigned int alen = exfat_striptail_len(name->len, name->name); + unsigned int blen = exfat_striptail_len(len, str); + unicode_t u_a, u_b; + int charlen, i; + + if (alen != blen) + return 1; + + for (i = 0; i < alen; i += charlen) { + charlen = utf8_to_utf32(&name->name[i], alen - i, &u_a); + if (charlen < 0) + return 1; + if (charlen != utf8_to_utf32(&str[i], blen - i, &u_b)) + return 1; + + if (u_a <= 0xFFFF && u_b <= 0xFFFF) { + if (exfat_toupper(sb, u_a) != exfat_toupper(sb, u_b)) + return 1; + } else if (u_a > 0xFFFF && u_b > 0xFFFF) { + if (exfat_low_surrogate(u_a) != + exfat_low_surrogate(u_b) || + exfat_high_surrogate(u_a) != + exfat_high_surrogate(u_b)) + return 1; + } else { + return 1; + } + } + + return 0; +} + +const struct dentry_operations exfat_utf8_dentry_ops = { + .d_revalidate = exfat_d_revalidate, + .d_hash = exfat_utf8_d_hash, + .d_compare = exfat_utf8_d_cmp, +}; + +/* used only in search empty_slot() */ +#define CNT_UNUSED_NOHIT (-1) +#define CNT_UNUSED_HIT (-2) +/* search EMPTY CONTINUOUS "num_entries" entries */ +static int exfat_search_empty_slot(struct super_block *sb, + struct exfat_hint_femp *hint_femp, struct exfat_chain *p_dir, + int num_entries) +{ + int i, dentry, num_empty = 0; + int dentries_per_clu; + unsigned int type; + struct exfat_chain clu; + struct exfat_dentry *ep; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct buffer_head *bh; + + dentries_per_clu = sbi->dentries_per_clu; + + if (hint_femp->eidx != EXFAT_HINT_NONE) { + dentry = hint_femp->eidx; + if (num_entries <= hint_femp->count) { + hint_femp->eidx = EXFAT_HINT_NONE; + return dentry; + } + + exfat_chain_dup(&clu, &hint_femp->cur); + } else { + exfat_chain_dup(&clu, p_dir); + dentry = 0; + } + + while (clu.dir != EXFAT_EOF_CLUSTER) { + i = dentry & (dentries_per_clu - 1); + + for (; i < dentries_per_clu; i++, dentry++) { + ep = exfat_get_dentry(sb, &clu, i, &bh, NULL); + if (!ep) + return -EIO; + type = exfat_get_entry_type(ep); + brelse(bh); + + if (type == TYPE_UNUSED || type == TYPE_DELETED) { + num_empty++; + if (hint_femp->eidx == EXFAT_HINT_NONE) { + hint_femp->eidx = dentry; + hint_femp->count = CNT_UNUSED_NOHIT; + exfat_chain_set(&hint_femp->cur, + clu.dir, clu.size, clu.flags); + } + + if (type == TYPE_UNUSED && + hint_femp->count != CNT_UNUSED_HIT) + hint_femp->count = CNT_UNUSED_HIT; + } else { + if (hint_femp->eidx != EXFAT_HINT_NONE && + hint_femp->count == CNT_UNUSED_HIT) { + /* unused empty group means + * an empty group which includes + * unused dentry + */ + exfat_fs_error(sb, + "found bogus dentry(%d) beyond unused empty group(%d) (start_clu : %u, cur_clu : %u)", + dentry, hint_femp->eidx, + p_dir->dir, clu.dir); + return -EIO; + } + + num_empty = 0; + hint_femp->eidx = EXFAT_HINT_NONE; + } + + if (num_empty >= num_entries) { + /* found and invalidate hint_femp */ + hint_femp->eidx = EXFAT_HINT_NONE; + return (dentry - (num_entries - 1)); + } + } + + if (clu.flags == ALLOC_NO_FAT_CHAIN) { + if (--clu.size > 0) + clu.dir++; + else + clu.dir = EXFAT_EOF_CLUSTER; + } else { + if (exfat_get_next_cluster(sb, &clu.dir)) + return -EIO; + } + } + + return -ENOSPC; +} + +static int exfat_check_max_dentries(struct inode *inode) +{ + if (EXFAT_B_TO_DEN(i_size_read(inode)) >= MAX_EXFAT_DENTRIES) { + /* + * exFAT spec allows a dir to grow upto 8388608(256MB) + * dentries + */ + return -ENOSPC; + } + return 0; +} + +/* find empty directory entry. + * if there isn't any empty slot, expand cluster chain. + */ +static int exfat_find_empty_entry(struct inode *inode, + struct exfat_chain *p_dir, int num_entries) +{ + int dentry; + unsigned int ret, last_clu; + sector_t sector; + loff_t size = 0; + struct exfat_chain clu; + struct exfat_dentry *ep = NULL; + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct exfat_inode_info *ei = EXFAT_I(inode); + struct exfat_hint_femp hint_femp; + + hint_femp.eidx = EXFAT_HINT_NONE; + + if (ei->hint_femp.eidx != EXFAT_HINT_NONE) { + memcpy(&hint_femp, &ei->hint_femp, + sizeof(struct exfat_hint_femp)); + ei->hint_femp.eidx = EXFAT_HINT_NONE; + } + + while ((dentry = exfat_search_empty_slot(sb, &hint_femp, p_dir, + num_entries)) < 0) { + if (dentry == -EIO) + break; + + if (exfat_check_max_dentries(inode)) + return -ENOSPC; + + /* we trust p_dir->size regardless of FAT type */ + if (exfat_find_last_cluster(sb, p_dir, &last_clu)) + return -EIO; + + /* + * Allocate new cluster to this directory + */ + exfat_chain_set(&clu, last_clu + 1, 0, p_dir->flags); + + /* allocate a cluster */ + ret = exfat_alloc_cluster(inode, 1, &clu); + if (ret) + return ret; + + if (exfat_zeroed_cluster(inode, clu.dir)) + return -EIO; + + /* append to the FAT chain */ + if (clu.flags != p_dir->flags) { + /* no-fat-chain bit is disabled, + * so fat-chain should be synced with alloc-bitmap + */ + exfat_chain_cont_cluster(sb, p_dir->dir, p_dir->size); + p_dir->flags = ALLOC_FAT_CHAIN; + hint_femp.cur.flags = ALLOC_FAT_CHAIN; + } + + if (clu.flags == ALLOC_FAT_CHAIN) + if (exfat_ent_set(sb, last_clu, clu.dir)) + return -EIO; + + if (hint_femp.eidx == EXFAT_HINT_NONE) { + /* the special case that new dentry + * should be allocated from the start of new cluster + */ + hint_femp.eidx = EXFAT_B_TO_DEN_IDX(p_dir->size, sbi); + hint_femp.count = sbi->dentries_per_clu; + + exfat_chain_set(&hint_femp.cur, clu.dir, 0, clu.flags); + } + hint_femp.cur.size++; + p_dir->size++; + size = EXFAT_CLU_TO_B(p_dir->size, sbi); + + /* update the directory entry */ + if (p_dir->dir != sbi->root_dir) { + struct buffer_head *bh; + + ep = exfat_get_dentry(sb, + &(ei->dir), ei->entry + 1, &bh, §or); + if (!ep) + return -EIO; + + ep->dentry.stream.valid_size = cpu_to_le64(size); + ep->dentry.stream.size = ep->dentry.stream.valid_size; + ep->dentry.stream.flags = p_dir->flags; + exfat_update_bh(sb, bh, IS_DIRSYNC(inode)); + brelse(bh); + if (exfat_update_dir_chksum(inode, &(ei->dir), + ei->entry)) + return -EIO; + } + + /* directory inode should be updated in here */ + i_size_write(inode, size); + EXFAT_I(inode)->i_size_ondisk += sbi->cluster_size; + EXFAT_I(inode)->i_size_aligned += sbi->cluster_size; + EXFAT_I(inode)->flags = p_dir->flags; + inode->i_blocks += 1 << sbi->sect_per_clus_bits; + } + + return dentry; +} + +/* + * Name Resolution Functions : + * Zero if it was successful; otherwise nonzero. + */ +static int __exfat_resolve_path(struct inode *inode, const unsigned char *path, + struct exfat_chain *p_dir, struct exfat_uni_name *p_uniname, + int lookup) +{ + int namelen; + int lossy = NLS_NAME_NO_LOSSY; + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct exfat_inode_info *ei = EXFAT_I(inode); + + /* strip all trailing periods */ + namelen = exfat_striptail_len(strlen(path), path); + if (!namelen) + return -ENOENT; + + if (strlen(path) > (MAX_NAME_LENGTH * MAX_CHARSET_SIZE)) + return -ENAMETOOLONG; + + /* + * strip all leading spaces : + * "MS windows 7" supports leading spaces. + * So we should skip this preprocessing for compatibility. + */ + + /* file name conversion : + * If lookup case, we allow bad-name for compatibility. + */ + namelen = exfat_nls_to_utf16(sb, path, namelen, p_uniname, + &lossy); + if (namelen < 0) + return namelen; /* return error value */ + + if ((lossy && !lookup) || !namelen) + return -EINVAL; + + exfat_chain_set(p_dir, ei->start_clu, + EXFAT_B_TO_CLU(i_size_read(inode), sbi), ei->flags); + + return 0; +} + +static inline int exfat_resolve_path(struct inode *inode, + const unsigned char *path, struct exfat_chain *dir, + struct exfat_uni_name *uni) +{ + return __exfat_resolve_path(inode, path, dir, uni, 0); +} + +static inline int exfat_resolve_path_for_lookup(struct inode *inode, + const unsigned char *path, struct exfat_chain *dir, + struct exfat_uni_name *uni) +{ + return __exfat_resolve_path(inode, path, dir, uni, 1); +} + +static inline loff_t exfat_make_i_pos(struct exfat_dir_entry *info) +{ + return ((loff_t) info->dir.dir << 32) | (info->entry & 0xffffffff); +} + +static int exfat_add_entry(struct inode *inode, const char *path, + struct exfat_chain *p_dir, unsigned int type, + struct exfat_dir_entry *info) +{ + int ret, dentry, num_entries; + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct exfat_uni_name uniname; + struct exfat_chain clu; + int clu_size = 0; + unsigned int start_clu = EXFAT_FREE_CLUSTER; + + ret = exfat_resolve_path(inode, path, p_dir, &uniname); + if (ret) + goto out; + + num_entries = exfat_calc_num_entries(&uniname); + if (num_entries < 0) { + ret = num_entries; + goto out; + } + + /* exfat_find_empty_entry must be called before alloc_cluster() */ + dentry = exfat_find_empty_entry(inode, p_dir, num_entries); + if (dentry < 0) { + ret = dentry; /* -EIO or -ENOSPC */ + goto out; + } + + if (type == TYPE_DIR) { + ret = exfat_alloc_new_dir(inode, &clu); + if (ret) + goto out; + start_clu = clu.dir; + clu_size = sbi->cluster_size; + } + + /* update the directory entry */ + /* fill the dos name directory entry information of the created file. + * the first cluster is not determined yet. (0) + */ + ret = exfat_init_dir_entry(inode, p_dir, dentry, type, + start_clu, clu_size); + if (ret) + goto out; + + ret = exfat_init_ext_entry(inode, p_dir, dentry, num_entries, &uniname); + if (ret) + goto out; + + memcpy(&info->dir, p_dir, sizeof(struct exfat_chain)); + info->entry = dentry; + info->flags = ALLOC_NO_FAT_CHAIN; + info->type = type; + + if (type == TYPE_FILE) { + info->attr = ATTR_ARCHIVE; + info->start_clu = EXFAT_EOF_CLUSTER; + info->size = 0; + info->num_subdirs = 0; + } else { + int count; + struct exfat_chain cdir; + + info->attr = ATTR_SUBDIR; + info->start_clu = start_clu; + info->size = clu_size; + + exfat_chain_set(&cdir, info->start_clu, + EXFAT_B_TO_CLU(info->size, sbi), info->flags); + count = exfat_count_dir_entries(sb, &cdir); + if (count < 0) + return -EIO; + info->num_subdirs = count + EXFAT_MIN_SUBDIR; + } + memset(&info->crtime, 0, sizeof(info->crtime)); + memset(&info->mtime, 0, sizeof(info->mtime)); + memset(&info->atime, 0, sizeof(info->atime)); +out: + return ret; +} + +static int exfat_create(struct inode *dir, struct dentry *dentry, umode_t mode, + bool excl) +{ + struct super_block *sb = dir->i_sb; + struct inode *inode; + struct exfat_chain cdir; + struct exfat_dir_entry info; + loff_t i_pos; + int err; + + mutex_lock(&EXFAT_SB(sb)->s_lock); + exfat_set_vol_flags(sb, VOL_DIRTY); + err = exfat_add_entry(dir, dentry->d_name.name, &cdir, TYPE_FILE, + &info); + exfat_set_vol_flags(sb, VOL_CLEAN); + if (err) + goto unlock; + + inode_inc_iversion(dir); + dir->i_ctime = dir->i_mtime = current_time(dir); + if (IS_DIRSYNC(dir)) + exfat_sync_inode(dir); + else + mark_inode_dirty(dir); + + i_pos = exfat_make_i_pos(&info); + inode = exfat_build_inode(sb, &info, i_pos); + if (IS_ERR(inode)) + goto unlock; + + inode_inc_iversion(inode); + inode->i_mtime = inode->i_atime = inode->i_ctime = + EXFAT_I(inode)->i_crtime = current_time(inode); + /* timestamp is already written, so mark_inode_dirty() is unneeded. */ + + d_instantiate(dentry, inode); +unlock: + mutex_unlock(&EXFAT_SB(sb)->s_lock); + return err; +} + +/* lookup a file */ +static int exfat_find(struct inode *dir, struct qstr *qname, + struct exfat_dir_entry *info) +{ + int ret, dentry, num_entries, count; + struct exfat_chain cdir; + struct exfat_uni_name uni_name; + struct exfat_dentry *ep, *ep2; + struct exfat_entry_set_cache *es = NULL; + struct super_block *sb = dir->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct exfat_inode_info *ei = EXFAT_I(dir); + + if (qname->len == 0) + return -ENOENT; + + /* check the validity of directory name in the given pathname */ + ret = exfat_resolve_path_for_lookup(dir, qname->name, &cdir, &uni_name); + if (ret) + return ret; + + num_entries = exfat_calc_num_entries(&uni_name); + if (num_entries < 0) + return num_entries; + + /* check the validation of hint_stat and initialize it if required */ + if (ei->version != (inode_peek_iversion_raw(dir) & 0xffffffff)) { + ei->hint_stat.clu = cdir.dir; + ei->hint_stat.eidx = 0; + ei->version = (inode_peek_iversion_raw(dir) & 0xffffffff); + ei->hint_femp.eidx = EXFAT_HINT_NONE; + } + + /* search the file name for directories */ + dentry = exfat_find_dir_entry(sb, ei, &cdir, &uni_name, + num_entries, TYPE_ALL); + + if ((dentry < 0) && (dentry != -EEXIST)) + return dentry; /* -error value */ + + memcpy(&info->dir, &cdir.dir, sizeof(struct exfat_chain)); + info->entry = dentry; + info->num_subdirs = 0; + + /* root directory itself */ + if (unlikely(dentry == -EEXIST)) { + int num_clu = 0; + + info->type = TYPE_DIR; + info->attr = ATTR_SUBDIR; + info->flags = ALLOC_FAT_CHAIN; + info->start_clu = sbi->root_dir; + memset(&info->crtime, 0, sizeof(info->crtime)); + memset(&info->mtime, 0, sizeof(info->mtime)); + memset(&info->atime, 0, sizeof(info->atime)); + + exfat_chain_set(&cdir, sbi->root_dir, 0, ALLOC_FAT_CHAIN); + if (exfat_count_num_clusters(sb, &cdir, &num_clu)) + return -EIO; + info->size = num_clu << sbi->cluster_size_bits; + + count = exfat_count_dir_entries(sb, &cdir); + if (count < 0) + return -EIO; + + info->num_subdirs = count; + } else { + es = exfat_get_dentry_set(sb, &cdir, dentry, ES_2_ENTRIES, &ep); + if (!es) + return -EIO; + ep2 = ep + 1; + + info->type = exfat_get_entry_type(ep); + info->attr = le16_to_cpu(ep->dentry.file.attr); + info->size = le64_to_cpu(ep2->dentry.stream.valid_size); + if ((info->type == TYPE_FILE) && (info->size == 0)) { + info->flags = ALLOC_NO_FAT_CHAIN; + info->start_clu = EXFAT_EOF_CLUSTER; + } else { + info->flags = ep2->dentry.stream.flags; + info->start_clu = + le32_to_cpu(ep2->dentry.stream.start_clu); + } + + if (ei->start_clu == EXFAT_FREE_CLUSTER) { + exfat_fs_error(sb, + "non-zero size file starts with zero cluster (size : %llu, p_dir : %u, entry : 0x%08x)", + i_size_read(dir), ei->dir.dir, ei->entry); + return -EIO; + } + + exfat_get_entry_time(sbi, &info->crtime, + ep->dentry.file.create_tz, + ep->dentry.file.create_time, + ep->dentry.file.create_date, + ep->dentry.file.create_time_ms); + exfat_get_entry_time(sbi, &info->mtime, + ep->dentry.file.modify_tz, + ep->dentry.file.modify_time, + ep->dentry.file.modify_date, + ep->dentry.file.modify_time_ms); + exfat_get_entry_time(sbi, &info->atime, + ep->dentry.file.access_tz, + ep->dentry.file.access_time, + ep->dentry.file.access_date, + 0); + kfree(es); + + if (info->type == TYPE_DIR) { + exfat_chain_set(&cdir, info->start_clu, + EXFAT_B_TO_CLU(info->size, sbi), info->flags); + count = exfat_count_dir_entries(sb, &cdir); + if (count < 0) + return -EIO; + + info->num_subdirs = count + EXFAT_MIN_SUBDIR; + } + } + return 0; +} + +static int exfat_d_anon_disconn(struct dentry *dentry) +{ + return IS_ROOT(dentry) && (dentry->d_flags & DCACHE_DISCONNECTED); +} + +static struct dentry *exfat_lookup(struct inode *dir, struct dentry *dentry, + unsigned int flags) +{ + struct super_block *sb = dir->i_sb; + struct inode *inode; + struct dentry *alias; + struct exfat_dir_entry info; + int err; + loff_t i_pos; + mode_t i_mode; + + mutex_lock(&EXFAT_SB(sb)->s_lock); + err = exfat_find(dir, &dentry->d_name, &info); + if (err) { + if (err == -ENOENT) { + inode = NULL; + goto out; + } + goto unlock; + } + + i_pos = exfat_make_i_pos(&info); + inode = exfat_build_inode(sb, &info, i_pos); + if (IS_ERR(inode)) { + err = PTR_ERR(inode); + goto unlock; + } + + i_mode = inode->i_mode; + alias = d_find_alias(inode); + + /* + * Checking "alias->d_parent == dentry->d_parent" to make sure + * FS is not corrupted (especially double linked dir). + */ + if (alias && alias->d_parent == dentry->d_parent && + !exfat_d_anon_disconn(alias)) { + + /* + * Unhashed alias is able to exist because of revalidate() + * called by lookup_fast. You can easily make this status + * by calling create and lookup concurrently + * In such case, we reuse an alias instead of new dentry + */ + if (d_unhashed(alias)) { + WARN_ON(alias->d_name.hash_len != + dentry->d_name.hash_len); + exfat_msg(sb, KERN_INFO, + "rehashed a dentry(%p) in read lookup", alias); + d_drop(dentry); + d_rehash(alias); + } else if (!S_ISDIR(i_mode)) { + /* + * This inode has non anonymous-DCACHE_DISCONNECTED + * dentry. This means, the user did ->lookup() by an + * another name (longname vs 8.3 alias of it) in past. + * + * Switch to new one for reason of locality if possible. + */ + d_move(alias, dentry); + } + iput(inode); + mutex_unlock(&EXFAT_SB(sb)->s_lock); + return alias; + } + dput(alias); +out: + mutex_unlock(&EXFAT_SB(sb)->s_lock); + if (!inode) + exfat_d_version_set(dentry, inode_query_iversion(dir)); + + return d_splice_alias(inode, dentry); +unlock: + mutex_unlock(&EXFAT_SB(sb)->s_lock); + return ERR_PTR(err); +} + +/* remove an entry, BUT don't truncate */ +static int exfat_unlink(struct inode *dir, struct dentry *dentry) +{ + struct exfat_chain cdir; + struct exfat_dentry *ep; + struct super_block *sb = dir->i_sb; + struct inode *inode = dentry->d_inode; + struct exfat_inode_info *ei = EXFAT_I(inode); + struct buffer_head *bh; + sector_t sector; + int num_entries, entry, err = 0; + + mutex_lock(&EXFAT_SB(sb)->s_lock); + exfat_chain_dup(&cdir, &ei->dir); + entry = ei->entry; + if (ei->dir.dir == DIR_DELETED) { + exfat_msg(sb, KERN_ERR, "abnormal access to deleted dentry"); + err = -ENOENT; + goto unlock; + } + + ep = exfat_get_dentry(sb, &cdir, entry, &bh, §or); + if (!ep) { + err = -EIO; + goto unlock; + } + num_entries = exfat_count_ext_entries(sb, &cdir, entry, ep); + if (num_entries < 0) { + err = -EIO; + brelse(bh); + goto unlock; + } + num_entries++; + brelse(bh); + + exfat_set_vol_flags(sb, VOL_DIRTY); + /* update the directory entry */ + if (exfat_remove_entries(dir, &cdir, entry, 0, num_entries)) { + err = -EIO; + goto unlock; + } + + /* This doesn't modify ei */ + ei->dir.dir = DIR_DELETED; + exfat_set_vol_flags(sb, VOL_CLEAN); + + inode_inc_iversion(dir); + dir->i_mtime = dir->i_atime = current_time(dir); + if (IS_DIRSYNC(dir)) + exfat_sync_inode(dir); + else + mark_inode_dirty(dir); + + clear_nlink(inode); + inode->i_mtime = inode->i_atime = current_time(inode); + exfat_unhash_inode(inode); + exfat_d_version_set(dentry, inode_query_iversion(dir)); +unlock: + mutex_unlock(&EXFAT_SB(sb)->s_lock); + return err; +} + +static int exfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) +{ + struct super_block *sb = dir->i_sb; + struct inode *inode; + struct exfat_dir_entry info; + struct exfat_chain cdir; + loff_t i_pos; + int err; + + mutex_lock(&EXFAT_SB(sb)->s_lock); + exfat_set_vol_flags(sb, VOL_DIRTY); + err = exfat_add_entry(dir, dentry->d_name.name, &cdir, TYPE_DIR, + &info); + exfat_set_vol_flags(sb, VOL_CLEAN); + if (err) + goto unlock; + + inode_inc_iversion(dir); + dir->i_ctime = dir->i_mtime = current_time(dir); + if (IS_DIRSYNC(dir)) + exfat_sync_inode(dir); + else + mark_inode_dirty(dir); + inc_nlink(dir); + + i_pos = exfat_make_i_pos(&info); + inode = exfat_build_inode(sb, &info, i_pos); + if (IS_ERR(inode)) { + err = PTR_ERR(inode); + goto unlock; + } + + inode_inc_iversion(inode); + inode->i_mtime = inode->i_atime = inode->i_ctime = + EXFAT_I(inode)->i_crtime = current_time(inode); + /* timestamp is already written, so mark_inode_dirty() is unneeded. */ + + d_instantiate(dentry, inode); + +unlock: + mutex_unlock(&EXFAT_SB(sb)->s_lock); + return err; +} + +static int exfat_check_dir_empty(struct super_block *sb, + struct exfat_chain *p_dir) +{ + int i, dentries_per_clu; + unsigned int type; + struct exfat_chain clu; + struct exfat_dentry *ep; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct buffer_head *bh; + + dentries_per_clu = sbi->dentries_per_clu; + + exfat_chain_dup(&clu, p_dir); + + while (clu.dir != EXFAT_EOF_CLUSTER) { + for (i = 0; i < dentries_per_clu; i++) { + ep = exfat_get_dentry(sb, &clu, i, &bh, NULL); + if (!ep) + return -EIO; + type = exfat_get_entry_type(ep); + brelse(bh); + if (type == TYPE_UNUSED) + return 0; + + if (type != TYPE_FILE && type != TYPE_DIR) + continue; + + return -ENOTEMPTY; + } + + if (clu.flags == ALLOC_NO_FAT_CHAIN) { + if (--clu.size > 0) + clu.dir++; + else + clu.dir = EXFAT_EOF_CLUSTER; + } else { + if (exfat_get_next_cluster(sb, &(clu.dir))) + return -EIO; + } + } + + return 0; +} + +static int exfat_rmdir(struct inode *dir, struct dentry *dentry) +{ + struct inode *inode = dentry->d_inode; + struct exfat_dentry *ep; + struct exfat_chain cdir, clu_to_free; + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct exfat_inode_info *ei = EXFAT_I(inode); + struct buffer_head *bh; + sector_t sector; + int num_entries, entry, err; + + mutex_lock(&EXFAT_SB(inode->i_sb)->s_lock); + + exfat_chain_dup(&cdir, &ei->dir); + entry = ei->entry; + + if (ei->dir.dir == DIR_DELETED) { + exfat_msg(sb, KERN_ERR, "abnormal access to deleted dentry"); + err = -ENOENT; + goto unlock; + } + + exfat_set_vol_flags(sb, VOL_DIRTY); + exfat_chain_set(&clu_to_free, ei->start_clu, + EXFAT_B_TO_CLU_ROUND_UP(i_size_read(inode), sbi), ei->flags); + + err = exfat_check_dir_empty(sb, &clu_to_free); + if (err) { + if (err == -EIO) + exfat_msg(sb, KERN_ERR, + "failed to exfat_check_dir_empty : err(%d)", + err); + goto unlock; + } + + ep = exfat_get_dentry(sb, &cdir, entry, &bh, §or); + if (!ep) { + err = -EIO; + goto unlock; + } + + num_entries = exfat_count_ext_entries(sb, &cdir, entry, ep); + if (num_entries < 0) { + err = -EIO; + brelse(bh); + goto unlock; + } + num_entries++; + brelse(bh); + + err = exfat_remove_entries(dir, &cdir, entry, 0, num_entries); + if (err) { + exfat_msg(sb, KERN_ERR, + "failed to exfat_remove_entries : err(%d)", + err); + goto unlock; + } + ei->dir.dir = DIR_DELETED; + exfat_set_vol_flags(sb, VOL_CLEAN); + + inode_inc_iversion(dir); + dir->i_mtime = dir->i_atime = current_time(dir); + if (IS_DIRSYNC(dir)) + exfat_sync_inode(dir); + else + mark_inode_dirty(dir); + drop_nlink(dir); + + clear_nlink(inode); + inode->i_mtime = inode->i_atime = current_time(inode); + exfat_unhash_inode(inode); + exfat_d_version_set(dentry, inode_query_iversion(dir)); +unlock: + mutex_unlock(&EXFAT_SB(inode->i_sb)->s_lock); + return err; +} + +static int exfat_rename_file(struct inode *inode, struct exfat_chain *p_dir, + int oldentry, struct exfat_uni_name *p_uniname, + struct exfat_inode_info *ei) +{ + int ret, num_old_entries, num_new_entries; + sector_t sector_old, sector_new; + struct exfat_dentry *epold, *epnew; + struct super_block *sb = inode->i_sb; + struct buffer_head *new_bh, *old_bh; + int sync = IS_DIRSYNC(inode); + + epold = exfat_get_dentry(sb, p_dir, oldentry, &old_bh, §or_old); + if (!epold) + return -EIO; + + num_old_entries = exfat_count_ext_entries(sb, p_dir, oldentry, epold); + if (num_old_entries < 0) + return -EIO; + num_old_entries++; + + num_new_entries = exfat_calc_num_entries(p_uniname); + if (num_new_entries < 0) + return num_new_entries; + + if (num_old_entries < num_new_entries) { + int newentry; + + newentry = + exfat_find_empty_entry(inode, p_dir, num_new_entries); + if (newentry < 0) + return newentry; /* -EIO or -ENOSPC */ + + epnew = exfat_get_dentry(sb, p_dir, newentry, &new_bh, + §or_new); + if (!epnew) + return -EIO; + + memcpy(epnew, epold, DENTRY_SIZE); + if (exfat_get_entry_type(epnew) == TYPE_FILE) { + epnew->dentry.file.attr |= cpu_to_le16(ATTR_ARCHIVE); + ei->attr |= ATTR_ARCHIVE; + } + exfat_update_bh(sb, new_bh, sync); + brelse(old_bh); + brelse(new_bh); + + epold = exfat_get_dentry(sb, p_dir, oldentry + 1, &old_bh, + §or_old); + epnew = exfat_get_dentry(sb, p_dir, newentry + 1, &new_bh, + §or_new); + if (!epold || !epnew) + return -EIO; + + memcpy(epnew, epold, DENTRY_SIZE); + exfat_update_bh(sb, new_bh, sync); + brelse(old_bh); + brelse(new_bh); + + ret = exfat_init_ext_entry(inode, p_dir, newentry, + num_new_entries, p_uniname); + if (ret) + return ret; + + exfat_remove_entries(inode, p_dir, oldentry, 0, + num_old_entries); + ei->entry = newentry; + } else { + if (exfat_get_entry_type(epold) == TYPE_FILE) { + epold->dentry.file.attr |= cpu_to_le16(ATTR_ARCHIVE); + ei->attr |= ATTR_ARCHIVE; + } + exfat_update_bh(sb, old_bh, sync); + brelse(old_bh); + ret = exfat_init_ext_entry(inode, p_dir, oldentry, + num_new_entries, p_uniname); + if (ret) + return ret; + + exfat_remove_entries(inode, p_dir, oldentry, num_new_entries, + num_old_entries); + } + return 0; +} + +static int exfat_move_file(struct inode *inode, struct exfat_chain *p_olddir, + int oldentry, struct exfat_chain *p_newdir, + struct exfat_uni_name *p_uniname, struct exfat_inode_info *ei) +{ + int ret, newentry, num_new_entries, num_old_entries; + sector_t sector_mov, sector_new; + struct exfat_dentry *epmov, *epnew; + struct super_block *sb = inode->i_sb; + struct buffer_head *mov_bh, *new_bh; + + epmov = exfat_get_dentry(sb, p_olddir, oldentry, &mov_bh, §or_mov); + if (!epmov) + return -EIO; + + /* check if the source and target directory is the same */ + if (exfat_get_entry_type(epmov) == TYPE_DIR && + le32_to_cpu(epmov->dentry.stream.start_clu) == p_newdir->dir) + return -EINVAL; + + num_old_entries = exfat_count_ext_entries(sb, p_olddir, oldentry, + epmov); + if (num_old_entries < 0) + return -EIO; + num_old_entries++; + + num_new_entries = exfat_calc_num_entries(p_uniname); + if (num_new_entries < 0) + return num_new_entries; + + newentry = exfat_find_empty_entry(inode, p_newdir, num_new_entries); + if (newentry < 0) + return newentry; /* -EIO or -ENOSPC */ + + epnew = exfat_get_dentry(sb, p_newdir, newentry, &new_bh, §or_new); + if (!epnew) + return -EIO; + + memcpy(epnew, epmov, DENTRY_SIZE); + if (exfat_get_entry_type(epnew) == TYPE_FILE) { + epnew->dentry.file.attr |= cpu_to_le16(ATTR_ARCHIVE); + ei->attr |= ATTR_ARCHIVE; + } + exfat_update_bh(sb, new_bh, IS_DIRSYNC(inode)); + brelse(mov_bh); + brelse(new_bh); + + epmov = exfat_get_dentry(sb, p_olddir, oldentry + 1, &mov_bh, + §or_mov); + epnew = exfat_get_dentry(sb, p_newdir, newentry + 1, &new_bh, + §or_new); + if (!epmov || !epnew) + return -EIO; + + memcpy(epnew, epmov, DENTRY_SIZE); + exfat_update_bh(sb, new_bh, IS_DIRSYNC(inode)); + brelse(mov_bh); + brelse(new_bh); + + ret = exfat_init_ext_entry(inode, p_newdir, newentry, num_new_entries, + p_uniname); + if (ret) + return ret; + + exfat_remove_entries(inode, p_olddir, oldentry, 0, num_old_entries); + + exfat_chain_set(&ei->dir, p_newdir->dir, p_newdir->size, + p_newdir->flags); + + ei->entry = newentry; + return 0; +} + +static void exfat_update_parent_info(struct exfat_inode_info *ei, + struct inode *parent_inode) +{ + struct exfat_sb_info *sbi = EXFAT_SB(parent_inode->i_sb); + struct exfat_inode_info *parent_ei = EXFAT_I(parent_inode); + loff_t parent_isize = i_size_read(parent_inode); + + /* + * the problem that struct exfat_inode_info caches wrong parent info. + * + * because of flag-mismatch of ei->dir, + * there is abnormal traversing cluster chain. + */ + if (unlikely(parent_ei->flags != ei->dir.flags || + parent_isize != EXFAT_CLU_TO_B(ei->dir.size, sbi) || + parent_ei->start_clu != ei->dir.dir)) { + exfat_chain_set(&ei->dir, parent_ei->start_clu, + EXFAT_B_TO_CLU_ROUND_UP(parent_isize, sbi), + parent_ei->flags); + } +} + +/* rename or move a old file into a new file */ +static int __exfat_rename(struct inode *old_parent_inode, + struct exfat_inode_info *ei, struct inode *new_parent_inode, + struct dentry *new_dentry) +{ + int ret; + int dentry; + struct exfat_chain olddir, newdir; + struct exfat_chain *p_dir = NULL; + struct exfat_uni_name uni_name; + struct exfat_dentry *ep; + struct super_block *sb = old_parent_inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + const unsigned char *new_path = new_dentry->d_name.name; + struct inode *new_inode = new_dentry->d_inode; + int num_entries; + struct exfat_inode_info *new_ei = NULL; + unsigned int new_entry_type = TYPE_UNUSED; + int new_entry = 0; + struct buffer_head *old_bh, *new_bh = NULL; + + /* check the validity of pointer parameters */ + if (new_path == NULL || strlen(new_path) == 0) + return -EINVAL; + + if (ei->dir.dir == DIR_DELETED) { + exfat_msg(sb, KERN_ERR, + "abnormal access to deleted source dentry"); + return -ENOENT; + } + + exfat_update_parent_info(ei, old_parent_inode); + + exfat_chain_dup(&olddir, &ei->dir); + dentry = ei->entry; + + ep = exfat_get_dentry(sb, &olddir, dentry, &old_bh, NULL); + if (!ep) { + ret = -EIO; + goto out; + } + brelse(old_bh); + + /* check whether new dir is existing directory and empty */ + if (new_inode) { + ret = -EIO; + new_ei = EXFAT_I(new_inode); + + if (new_ei->dir.dir == DIR_DELETED) { + exfat_msg(sb, KERN_ERR, + "abnormal access to deleted target dentry"); + goto out; + } + + exfat_update_parent_info(new_ei, new_parent_inode); + + p_dir = &(new_ei->dir); + new_entry = new_ei->entry; + ep = exfat_get_dentry(sb, p_dir, new_entry, &new_bh, NULL); + if (!ep) + goto out; + + new_entry_type = exfat_get_entry_type(ep); + brelse(new_bh); + + /* if new_inode exists, update ei */ + if (new_entry_type == TYPE_DIR) { + struct exfat_chain new_clu; + + new_clu.dir = new_ei->start_clu; + new_clu.size = + EXFAT_B_TO_CLU_ROUND_UP(i_size_read(new_inode), + sbi); + new_clu.flags = new_ei->flags; + + ret = exfat_check_dir_empty(sb, &new_clu); + if (ret) + goto out; + } + } + + /* check the validity of directory name in the given new pathname */ + ret = exfat_resolve_path(new_parent_inode, new_path, &newdir, + &uni_name); + if (ret) + goto out; + + exfat_set_vol_flags(sb, VOL_DIRTY); + + if (olddir.dir == newdir.dir) + ret = exfat_rename_file(new_parent_inode, &olddir, dentry, + &uni_name, ei); + else + ret = exfat_move_file(new_parent_inode, &olddir, dentry, + &newdir, &uni_name, ei); + + if (!ret && new_inode) { + /* delete entries of new_dir */ + ep = exfat_get_dentry(sb, p_dir, new_entry, &new_bh, NULL); + if (!ep) { + ret = -EIO; + goto del_out; + } + + num_entries = exfat_count_ext_entries(sb, p_dir, new_entry, ep); + if (num_entries < 0) { + ret = -EIO; + goto del_out; + } + brelse(new_bh); + + if (exfat_remove_entries(new_inode, p_dir, new_entry, 0, + num_entries + 1)) { + ret = -EIO; + goto del_out; + } + + /* Free the clusters if new_inode is a dir(as if exfat_rmdir) */ + if (new_entry_type == TYPE_DIR) { + /* new_ei, new_clu_to_free */ + struct exfat_chain new_clu_to_free; + + exfat_chain_set(&new_clu_to_free, new_ei->start_clu, + EXFAT_B_TO_CLU_ROUND_UP(i_size_read(new_inode), + sbi), new_ei->flags); + + if (exfat_free_cluster(new_inode, &new_clu_to_free)) { + /* just set I/O error only */ + ret = -EIO; + } + + i_size_write(new_inode, 0); + new_ei->start_clu = EXFAT_EOF_CLUSTER; + new_ei->flags = ALLOC_NO_FAT_CHAIN; + } +del_out: + /* Update new_inode ei + * Prevent syncing removed new_inode + * (new_ei is already initialized above code ("if (new_inode)") + */ + new_ei->dir.dir = DIR_DELETED; + } + exfat_set_vol_flags(sb, VOL_CLEAN); +out: + return ret; +} + +static int exfat_rename(struct inode *old_dir, struct dentry *old_dentry, + struct inode *new_dir, struct dentry *new_dentry, + unsigned int flags) +{ + struct inode *old_inode, *new_inode; + struct super_block *sb = old_dir->i_sb; + loff_t i_pos; + int err; + + /* + * The VFS already checks for existence, so for local filesystems + * the RENAME_NOREPLACE implementation is equivalent to plain rename. + * Don't support any other flags + */ + if (flags & ~RENAME_NOREPLACE) + return -EINVAL; + + mutex_lock(&EXFAT_SB(sb)->s_lock); + old_inode = old_dentry->d_inode; + new_inode = new_dentry->d_inode; + + err = __exfat_rename(old_dir, EXFAT_I(old_inode), new_dir, new_dentry); + if (err) + goto unlock; + + inode_inc_iversion(new_dir); + new_dir->i_ctime = new_dir->i_mtime = new_dir->i_atime = + EXFAT_I(new_dir)->i_crtime = current_time(new_dir); + if (IS_DIRSYNC(new_dir)) + exfat_sync_inode(new_dir); + else + mark_inode_dirty(new_dir); + + i_pos = ((loff_t)EXFAT_I(old_inode)->dir.dir << 32) | + (EXFAT_I(old_inode)->entry & 0xffffffff); + exfat_unhash_inode(old_inode); + exfat_hash_inode(old_inode, i_pos); + if (IS_DIRSYNC(new_dir)) + exfat_sync_inode(old_inode); + else + mark_inode_dirty(old_inode); + + if (S_ISDIR(old_inode->i_mode) && old_dir != new_dir) { + drop_nlink(old_dir); + if (!new_inode) + inc_nlink(new_dir); + } + + inode_inc_iversion(old_dir); + old_dir->i_ctime = old_dir->i_mtime = current_time(old_dir); + if (IS_DIRSYNC(old_dir)) + exfat_sync_inode(old_dir); + else + mark_inode_dirty(old_dir); + + if (new_inode) { + exfat_unhash_inode(new_inode); + + /* skip drop_nlink if new_inode already has been dropped */ + if (new_inode->i_nlink) { + drop_nlink(new_inode); + if (S_ISDIR(new_inode->i_mode)) + drop_nlink(new_inode); + } else { + exfat_msg(sb, KERN_WARNING, + "abnormal access to an inode dropped"); + WARN_ON(new_inode->i_nlink == 0); + } + new_inode->i_ctime = EXFAT_I(new_inode)->i_crtime = + current_time(new_inode); + } + +unlock: + mutex_unlock(&EXFAT_SB(sb)->s_lock); + return err; +} + +const struct inode_operations exfat_dir_inode_operations = { + .create = exfat_create, + .lookup = exfat_lookup, + .unlink = exfat_unlink, + .mkdir = exfat_mkdir, + .rmdir = exfat_rmdir, + .rename = exfat_rename, + .setattr = exfat_setattr, + .getattr = exfat_getattr, +}; From b6bed5a012c57e67b9f4a9703bef0383777f0ac5 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Mon, 2 Mar 2020 15:21:35 +0900 Subject: [PATCH 037/592] exfat: add directory operations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds the implementation of directory operations for exfat. Signed-off-by: Namjae Jeon Signed-off-by: Sungjong Seo Reviewed-by: Pali Rohár Reviewed-by: Christoph Hellwig Signed-off-by: Al Viro Signed-off-by: Park Ju Hyung --- dir.c | 1238 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1238 insertions(+) create mode 100644 dir.c diff --git a/dir.c b/dir.c new file mode 100644 index 000000000000..4b91afb0f051 --- /dev/null +++ b/dir.c @@ -0,0 +1,1238 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + */ + +#include +#include +#include + +#include "exfat_raw.h" +#include "exfat_fs.h" + +static int exfat_extract_uni_name(struct exfat_dentry *ep, + unsigned short *uniname) +{ + int i, len = 0; + + for (i = 0; i < EXFAT_FILE_NAME_LEN; i++) { + *uniname = le16_to_cpu(ep->dentry.name.unicode_0_14[i]); + if (*uniname == 0x0) + return len; + uniname++; + len++; + } + + *uniname = 0x0; + return len; + +} + +static void exfat_get_uniname_from_ext_entry(struct super_block *sb, + struct exfat_chain *p_dir, int entry, unsigned short *uniname) +{ + int i; + struct exfat_dentry *ep; + struct exfat_entry_set_cache *es; + + es = exfat_get_dentry_set(sb, p_dir, entry, ES_ALL_ENTRIES, &ep); + if (!es) + return; + + if (es->num_entries < 3) + goto free_es; + + ep += 2; + + /* + * First entry : file entry + * Second entry : stream-extension entry + * Third entry : first file-name entry + * So, the index of first file-name dentry should start from 2. + */ + for (i = 2; i < es->num_entries; i++, ep++) { + /* end of name entry */ + if (exfat_get_entry_type(ep) != TYPE_EXTEND) + goto free_es; + + exfat_extract_uni_name(ep, uniname); + uniname += EXFAT_FILE_NAME_LEN; + } + +free_es: + kfree(es); +} + +/* read a directory entry from the opened directory */ +static int exfat_readdir(struct inode *inode, struct exfat_dir_entry *dir_entry) +{ + int i, dentries_per_clu, dentries_per_clu_bits = 0; + unsigned int type, clu_offset; + sector_t sector; + struct exfat_chain dir, clu; + struct exfat_uni_name uni_name; + struct exfat_dentry *ep; + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct exfat_inode_info *ei = EXFAT_I(inode); + unsigned int dentry = ei->rwoffset & 0xFFFFFFFF; + struct buffer_head *bh; + + /* check if the given file ID is opened */ + if (ei->type != TYPE_DIR) + return -EPERM; + + if (ei->entry == -1) + exfat_chain_set(&dir, sbi->root_dir, 0, ALLOC_FAT_CHAIN); + else + exfat_chain_set(&dir, ei->start_clu, + EXFAT_B_TO_CLU(i_size_read(inode), sbi), ei->flags); + + dentries_per_clu = sbi->dentries_per_clu; + dentries_per_clu_bits = ilog2(dentries_per_clu); + + clu_offset = dentry >> dentries_per_clu_bits; + exfat_chain_dup(&clu, &dir); + + if (clu.flags == ALLOC_NO_FAT_CHAIN) { + clu.dir += clu_offset; + clu.size -= clu_offset; + } else { + /* hint_information */ + if (clu_offset > 0 && ei->hint_bmap.off != EXFAT_EOF_CLUSTER && + ei->hint_bmap.off > 0 && clu_offset >= ei->hint_bmap.off) { + clu_offset -= ei->hint_bmap.off; + clu.dir = ei->hint_bmap.clu; + } + + while (clu_offset > 0) { + if (exfat_get_next_cluster(sb, &(clu.dir))) + return -EIO; + + clu_offset--; + } + } + + while (clu.dir != EXFAT_EOF_CLUSTER) { + i = dentry & (dentries_per_clu - 1); + + for ( ; i < dentries_per_clu; i++, dentry++) { + ep = exfat_get_dentry(sb, &clu, i, &bh, §or); + if (!ep) + return -EIO; + + type = exfat_get_entry_type(ep); + if (type == TYPE_UNUSED) { + brelse(bh); + break; + } + + if (type != TYPE_FILE && type != TYPE_DIR) { + brelse(bh); + continue; + } + + dir_entry->attr = le16_to_cpu(ep->dentry.file.attr); + exfat_get_entry_time(sbi, &dir_entry->crtime, + ep->dentry.file.create_tz, + ep->dentry.file.create_time, + ep->dentry.file.create_date, + ep->dentry.file.create_time_ms); + exfat_get_entry_time(sbi, &dir_entry->mtime, + ep->dentry.file.modify_tz, + ep->dentry.file.modify_time, + ep->dentry.file.modify_date, + ep->dentry.file.modify_time_ms); + exfat_get_entry_time(sbi, &dir_entry->atime, + ep->dentry.file.access_tz, + ep->dentry.file.access_time, + ep->dentry.file.access_date, + 0); + + *uni_name.name = 0x0; + exfat_get_uniname_from_ext_entry(sb, &dir, dentry, + uni_name.name); + exfat_utf16_to_nls(sb, &uni_name, + dir_entry->namebuf.lfn, + dir_entry->namebuf.lfnbuf_len); + brelse(bh); + + ep = exfat_get_dentry(sb, &clu, i + 1, &bh, NULL); + if (!ep) + return -EIO; + dir_entry->size = + le64_to_cpu(ep->dentry.stream.valid_size); + brelse(bh); + + ei->hint_bmap.off = dentry >> dentries_per_clu_bits; + ei->hint_bmap.clu = clu.dir; + + ei->rwoffset = ++dentry; + return 0; + } + + if (clu.flags == ALLOC_NO_FAT_CHAIN) { + if (--clu.size > 0) + clu.dir++; + else + clu.dir = EXFAT_EOF_CLUSTER; + } else { + if (exfat_get_next_cluster(sb, &(clu.dir))) + return -EIO; + } + } + + dir_entry->namebuf.lfn[0] = '\0'; + ei->rwoffset = dentry; + return 0; +} + +static void exfat_init_namebuf(struct exfat_dentry_namebuf *nb) +{ + nb->lfn = NULL; + nb->lfnbuf_len = 0; +} + +static int exfat_alloc_namebuf(struct exfat_dentry_namebuf *nb) +{ + nb->lfn = __getname(); + if (!nb->lfn) + return -ENOMEM; + nb->lfnbuf_len = MAX_VFSNAME_BUF_SIZE; + return 0; +} + +static void exfat_free_namebuf(struct exfat_dentry_namebuf *nb) +{ + if (!nb->lfn) + return; + + __putname(nb->lfn); + exfat_init_namebuf(nb); +} + +/* skip iterating emit_dots when dir is empty */ +#define ITER_POS_FILLED_DOTS (2) +static int exfat_iterate(struct file *filp, struct dir_context *ctx) +{ + struct inode *inode = filp->f_path.dentry->d_inode; + struct super_block *sb = inode->i_sb; + struct inode *tmp; + struct exfat_dir_entry de; + struct exfat_dentry_namebuf *nb = &(de.namebuf); + struct exfat_inode_info *ei = EXFAT_I(inode); + unsigned long inum; + loff_t cpos, i_pos; + int err = 0, fake_offset = 0; + + exfat_init_namebuf(nb); + mutex_lock(&EXFAT_SB(sb)->s_lock); + + cpos = ctx->pos; + if (!dir_emit_dots(filp, ctx)) + goto unlock; + + if (ctx->pos == ITER_POS_FILLED_DOTS) { + cpos = 0; + fake_offset = 1; + } + + if (cpos & (DENTRY_SIZE - 1)) { + err = -ENOENT; + goto unlock; + } + + /* name buffer should be allocated before use */ + err = exfat_alloc_namebuf(nb); + if (err) + goto unlock; +get_new: + ei->rwoffset = EXFAT_B_TO_DEN(cpos); + + if (cpos >= i_size_read(inode)) + goto end_of_dir; + + err = exfat_readdir(inode, &de); + if (err) { + /* + * At least we tried to read a sector. Move cpos to next sector + * position (should be aligned). + */ + if (err == -EIO) { + cpos += 1 << (sb->s_blocksize_bits); + cpos &= ~(sb->s_blocksize - 1); + } + + err = -EIO; + goto end_of_dir; + } + + cpos = EXFAT_DEN_TO_B(ei->rwoffset); + + if (!nb->lfn[0]) + goto end_of_dir; + + i_pos = ((loff_t)ei->start_clu << 32) | + ((ei->rwoffset - 1) & 0xffffffff); + tmp = exfat_iget(sb, i_pos); + if (tmp) { + inum = tmp->i_ino; + iput(tmp); + } else { + inum = iunique(sb, EXFAT_ROOT_INO); + } + + /* + * Before calling dir_emit(), sb_lock should be released. + * Because page fault can occur in dir_emit() when the size + * of buffer given from user is larger than one page size. + */ + mutex_unlock(&EXFAT_SB(sb)->s_lock); + if (!dir_emit(ctx, nb->lfn, strlen(nb->lfn), inum, + (de.attr & ATTR_SUBDIR) ? DT_DIR : DT_REG)) + goto out_unlocked; + mutex_lock(&EXFAT_SB(sb)->s_lock); + ctx->pos = cpos; + goto get_new; + +end_of_dir: + if (!cpos && fake_offset) + cpos = ITER_POS_FILLED_DOTS; + ctx->pos = cpos; +unlock: + mutex_unlock(&EXFAT_SB(sb)->s_lock); +out_unlocked: + /* + * To improve performance, free namebuf after unlock sb_lock. + * If namebuf is not allocated, this function do nothing + */ + exfat_free_namebuf(nb); + return err; +} + +const struct file_operations exfat_dir_operations = { + .llseek = generic_file_llseek, + .read = generic_read_dir, + .iterate = exfat_iterate, + .fsync = generic_file_fsync, +}; + +int exfat_alloc_new_dir(struct inode *inode, struct exfat_chain *clu) +{ + int ret; + + exfat_chain_set(clu, EXFAT_EOF_CLUSTER, 0, ALLOC_NO_FAT_CHAIN); + + ret = exfat_alloc_cluster(inode, 1, clu); + if (ret) + return ret; + + return exfat_zeroed_cluster(inode, clu->dir); +} + +int exfat_calc_num_entries(struct exfat_uni_name *p_uniname) +{ + int len; + + len = p_uniname->name_len; + if (len == 0) + return -EINVAL; + + /* 1 file entry + 1 stream entry + name entries */ + return ((len - 1) / EXFAT_FILE_NAME_LEN + 3); +} + +unsigned int exfat_get_entry_type(struct exfat_dentry *ep) +{ + if (ep->type == EXFAT_UNUSED) + return TYPE_UNUSED; + if (IS_EXFAT_DELETED(ep->type)) + return TYPE_DELETED; + if (ep->type == EXFAT_INVAL) + return TYPE_INVALID; + if (IS_EXFAT_CRITICAL_PRI(ep->type)) { + if (ep->type == EXFAT_BITMAP) + return TYPE_BITMAP; + if (ep->type == EXFAT_UPCASE) + return TYPE_UPCASE; + if (ep->type == EXFAT_VOLUME) + return TYPE_VOLUME; + if (ep->type == EXFAT_FILE) { + if (le16_to_cpu(ep->dentry.file.attr) & ATTR_SUBDIR) + return TYPE_DIR; + return TYPE_FILE; + } + return TYPE_CRITICAL_PRI; + } + if (IS_EXFAT_BENIGN_PRI(ep->type)) { + if (ep->type == EXFAT_GUID) + return TYPE_GUID; + if (ep->type == EXFAT_PADDING) + return TYPE_PADDING; + if (ep->type == EXFAT_ACLTAB) + return TYPE_ACLTAB; + return TYPE_BENIGN_PRI; + } + if (IS_EXFAT_CRITICAL_SEC(ep->type)) { + if (ep->type == EXFAT_STREAM) + return TYPE_STREAM; + if (ep->type == EXFAT_NAME) + return TYPE_EXTEND; + if (ep->type == EXFAT_ACL) + return TYPE_ACL; + return TYPE_CRITICAL_SEC; + } + return TYPE_BENIGN_SEC; +} + +static void exfat_set_entry_type(struct exfat_dentry *ep, unsigned int type) +{ + if (type == TYPE_UNUSED) { + ep->type = EXFAT_UNUSED; + } else if (type == TYPE_DELETED) { + ep->type &= EXFAT_DELETE; + } else if (type == TYPE_STREAM) { + ep->type = EXFAT_STREAM; + } else if (type == TYPE_EXTEND) { + ep->type = EXFAT_NAME; + } else if (type == TYPE_BITMAP) { + ep->type = EXFAT_BITMAP; + } else if (type == TYPE_UPCASE) { + ep->type = EXFAT_UPCASE; + } else if (type == TYPE_VOLUME) { + ep->type = EXFAT_VOLUME; + } else if (type == TYPE_DIR) { + ep->type = EXFAT_FILE; + ep->dentry.file.attr = cpu_to_le16(ATTR_SUBDIR); + } else if (type == TYPE_FILE) { + ep->type = EXFAT_FILE; + ep->dentry.file.attr = cpu_to_le16(ATTR_ARCHIVE); + } +} + +static void exfat_init_stream_entry(struct exfat_dentry *ep, + unsigned char flags, unsigned int start_clu, + unsigned long long size) +{ + exfat_set_entry_type(ep, TYPE_STREAM); + ep->dentry.stream.flags = flags; + ep->dentry.stream.start_clu = cpu_to_le32(start_clu); + ep->dentry.stream.valid_size = cpu_to_le64(size); + ep->dentry.stream.size = cpu_to_le64(size); +} + +static void exfat_init_name_entry(struct exfat_dentry *ep, + unsigned short *uniname) +{ + int i; + + exfat_set_entry_type(ep, TYPE_EXTEND); + ep->dentry.name.flags = 0x0; + + for (i = 0; i < EXFAT_FILE_NAME_LEN; i++) { + ep->dentry.name.unicode_0_14[i] = cpu_to_le16(*uniname); + if (*uniname == 0x0) + break; + uniname++; + } +} + +int exfat_init_dir_entry(struct inode *inode, struct exfat_chain *p_dir, + int entry, unsigned int type, unsigned int start_clu, + unsigned long long size) +{ + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct timespec64 ts = current_time(inode); + sector_t sector; + struct exfat_dentry *ep; + struct buffer_head *bh; + + /* + * We cannot use exfat_get_dentry_set here because file ep is not + * initialized yet. + */ + ep = exfat_get_dentry(sb, p_dir, entry, &bh, §or); + if (!ep) + return -EIO; + + exfat_set_entry_type(ep, type); + exfat_set_entry_time(sbi, &ts, + &ep->dentry.file.create_tz, + &ep->dentry.file.create_time, + &ep->dentry.file.create_date, + &ep->dentry.file.create_time_ms); + exfat_set_entry_time(sbi, &ts, + &ep->dentry.file.modify_tz, + &ep->dentry.file.modify_time, + &ep->dentry.file.modify_date, + &ep->dentry.file.modify_time_ms); + exfat_set_entry_time(sbi, &ts, + &ep->dentry.file.access_tz, + &ep->dentry.file.access_time, + &ep->dentry.file.access_date, + NULL); + + exfat_update_bh(sb, bh, IS_DIRSYNC(inode)); + brelse(bh); + + ep = exfat_get_dentry(sb, p_dir, entry + 1, &bh, §or); + if (!ep) + return -EIO; + + exfat_init_stream_entry(ep, + (type == TYPE_FILE) ? ALLOC_FAT_CHAIN : ALLOC_NO_FAT_CHAIN, + start_clu, size); + exfat_update_bh(sb, bh, IS_DIRSYNC(inode)); + brelse(bh); + + return 0; +} + +int exfat_update_dir_chksum(struct inode *inode, struct exfat_chain *p_dir, + int entry) +{ + struct super_block *sb = inode->i_sb; + int ret = 0; + int i, num_entries; + sector_t sector; + unsigned short chksum; + struct exfat_dentry *ep, *fep; + struct buffer_head *fbh, *bh; + + fep = exfat_get_dentry(sb, p_dir, entry, &fbh, §or); + if (!fep) + return -EIO; + + num_entries = fep->dentry.file.num_ext + 1; + chksum = exfat_calc_chksum_2byte(fep, DENTRY_SIZE, 0, CS_DIR_ENTRY); + + for (i = 1; i < num_entries; i++) { + ep = exfat_get_dentry(sb, p_dir, entry + i, &bh, NULL); + if (!ep) { + ret = -EIO; + goto release_fbh; + } + chksum = exfat_calc_chksum_2byte(ep, DENTRY_SIZE, chksum, + CS_DEFAULT); + brelse(bh); + } + + fep->dentry.file.checksum = cpu_to_le16(chksum); + exfat_update_bh(sb, fbh, IS_DIRSYNC(inode)); +release_fbh: + brelse(fbh); + return ret; +} + +int exfat_init_ext_entry(struct inode *inode, struct exfat_chain *p_dir, + int entry, int num_entries, struct exfat_uni_name *p_uniname) +{ + struct super_block *sb = inode->i_sb; + int i; + sector_t sector; + unsigned short *uniname = p_uniname->name; + struct exfat_dentry *ep; + struct buffer_head *bh; + int sync = IS_DIRSYNC(inode); + + ep = exfat_get_dentry(sb, p_dir, entry, &bh, §or); + if (!ep) + return -EIO; + + ep->dentry.file.num_ext = (unsigned char)(num_entries - 1); + exfat_update_bh(sb, bh, sync); + brelse(bh); + + ep = exfat_get_dentry(sb, p_dir, entry + 1, &bh, §or); + if (!ep) + return -EIO; + + ep->dentry.stream.name_len = p_uniname->name_len; + ep->dentry.stream.name_hash = cpu_to_le16(p_uniname->name_hash); + exfat_update_bh(sb, bh, sync); + brelse(bh); + + for (i = EXFAT_FIRST_CLUSTER; i < num_entries; i++) { + ep = exfat_get_dentry(sb, p_dir, entry + i, &bh, §or); + if (!ep) + return -EIO; + + exfat_init_name_entry(ep, uniname); + exfat_update_bh(sb, bh, sync); + brelse(bh); + uniname += EXFAT_FILE_NAME_LEN; + } + + exfat_update_dir_chksum(inode, p_dir, entry); + return 0; +} + +int exfat_remove_entries(struct inode *inode, struct exfat_chain *p_dir, + int entry, int order, int num_entries) +{ + struct super_block *sb = inode->i_sb; + int i; + sector_t sector; + struct exfat_dentry *ep; + struct buffer_head *bh; + + for (i = order; i < num_entries; i++) { + ep = exfat_get_dentry(sb, p_dir, entry + i, &bh, §or); + if (!ep) + return -EIO; + + exfat_set_entry_type(ep, TYPE_DELETED); + exfat_update_bh(sb, bh, IS_DIRSYNC(inode)); + brelse(bh); + } + + return 0; +} + +int exfat_update_dir_chksum_with_entry_set(struct super_block *sb, + struct exfat_entry_set_cache *es, int sync) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct buffer_head *bh; + sector_t sec = es->sector; + unsigned int off = es->offset; + int chksum_type = CS_DIR_ENTRY, i, num_entries = es->num_entries; + unsigned int buf_off = (off - es->offset); + unsigned int remaining_byte_in_sector, copy_entries, clu; + unsigned short chksum = 0; + + for (i = 0; i < num_entries; i++) { + chksum = exfat_calc_chksum_2byte(&es->entries[i], DENTRY_SIZE, + chksum, chksum_type); + chksum_type = CS_DEFAULT; + } + + es->entries[0].dentry.file.checksum = cpu_to_le16(chksum); + + while (num_entries) { + /* write per sector base */ + remaining_byte_in_sector = (1 << sb->s_blocksize_bits) - off; + copy_entries = min_t(int, + EXFAT_B_TO_DEN(remaining_byte_in_sector), + num_entries); + bh = sb_bread(sb, sec); + if (!bh) + goto err_out; + memcpy(bh->b_data + off, + (unsigned char *)&es->entries[0] + buf_off, + EXFAT_DEN_TO_B(copy_entries)); + exfat_update_bh(sb, bh, sync); + brelse(bh); + num_entries -= copy_entries; + + if (num_entries) { + /* get next sector */ + if (exfat_is_last_sector_in_cluster(sbi, sec)) { + clu = exfat_sector_to_cluster(sbi, sec); + if (es->alloc_flag == ALLOC_NO_FAT_CHAIN) + clu++; + else if (exfat_get_next_cluster(sb, &clu)) + goto err_out; + sec = exfat_cluster_to_sector(sbi, clu); + } else { + sec++; + } + off = 0; + buf_off += EXFAT_DEN_TO_B(copy_entries); + } + } + + return 0; +err_out: + return -EIO; +} + +static int exfat_walk_fat_chain(struct super_block *sb, + struct exfat_chain *p_dir, unsigned int byte_offset, + unsigned int *clu) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + unsigned int clu_offset; + unsigned int cur_clu; + + clu_offset = EXFAT_B_TO_CLU(byte_offset, sbi); + cur_clu = p_dir->dir; + + if (p_dir->flags == ALLOC_NO_FAT_CHAIN) { + cur_clu += clu_offset; + } else { + while (clu_offset > 0) { + if (exfat_get_next_cluster(sb, &cur_clu)) + return -EIO; + if (cur_clu == EXFAT_EOF_CLUSTER) { + exfat_fs_error(sb, + "invalid dentry access beyond EOF (clu : %u, eidx : %d)", + p_dir->dir, + EXFAT_B_TO_DEN(byte_offset)); + return -EIO; + } + clu_offset--; + } + } + + *clu = cur_clu; + return 0; +} + +int exfat_find_location(struct super_block *sb, struct exfat_chain *p_dir, + int entry, sector_t *sector, int *offset) +{ + int ret; + unsigned int off, clu = 0; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + + off = EXFAT_DEN_TO_B(entry); + + ret = exfat_walk_fat_chain(sb, p_dir, off, &clu); + if (ret) + return ret; + + /* byte offset in cluster */ + off = EXFAT_CLU_OFFSET(off, sbi); + + /* byte offset in sector */ + *offset = EXFAT_BLK_OFFSET(off, sb); + + /* sector offset in cluster */ + *sector = EXFAT_B_TO_BLK(off, sb); + *sector += exfat_cluster_to_sector(sbi, clu); + return 0; +} + +#define EXFAT_MAX_RA_SIZE (128*1024) +static int exfat_dir_readahead(struct super_block *sb, sector_t sec) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct buffer_head *bh; + unsigned int max_ra_count = EXFAT_MAX_RA_SIZE >> sb->s_blocksize_bits; + unsigned int page_ra_count = PAGE_SIZE >> sb->s_blocksize_bits; + unsigned int adj_ra_count = max(sbi->sect_per_clus, page_ra_count); + unsigned int ra_count = min(adj_ra_count, max_ra_count); + + /* Read-ahead is not required */ + if (sbi->sect_per_clus == 1) + return 0; + + if (sec < sbi->data_start_sector) { + exfat_msg(sb, KERN_ERR, + "requested sector is invalid(sect:%llu, root:%llu)", + (unsigned long long)sec, sbi->data_start_sector); + return -EIO; + } + + /* Not sector aligned with ra_count, resize ra_count to page size */ + if ((sec - sbi->data_start_sector) & (ra_count - 1)) + ra_count = page_ra_count; + + bh = sb_find_get_block(sb, sec); + if (!bh || !buffer_uptodate(bh)) { + unsigned int i; + + for (i = 0; i < ra_count; i++) + sb_breadahead(sb, (sector_t)(sec + i)); + } + brelse(bh); + return 0; +} + +struct exfat_dentry *exfat_get_dentry(struct super_block *sb, + struct exfat_chain *p_dir, int entry, struct buffer_head **bh, + sector_t *sector) +{ + unsigned int dentries_per_page = EXFAT_B_TO_DEN(PAGE_SIZE); + int off; + sector_t sec; + + if (p_dir->dir == DIR_DELETED) { + exfat_msg(sb, KERN_ERR, "abnormal access to deleted dentry\n"); + return NULL; + } + + if (exfat_find_location(sb, p_dir, entry, &sec, &off)) + return NULL; + + if (p_dir->dir != EXFAT_FREE_CLUSTER && + !(entry & (dentries_per_page - 1))) + exfat_dir_readahead(sb, sec); + + *bh = sb_bread(sb, sec); + if (!*bh) + return NULL; + + if (sector) + *sector = sec; + return (struct exfat_dentry *)((*bh)->b_data + off); +} + +enum exfat_validate_dentry_mode { + ES_MODE_STARTED, + ES_MODE_GET_FILE_ENTRY, + ES_MODE_GET_STRM_ENTRY, + ES_MODE_GET_NAME_ENTRY, + ES_MODE_GET_CRITICAL_SEC_ENTRY, +}; + +static bool exfat_validate_entry(unsigned int type, + enum exfat_validate_dentry_mode *mode) +{ + if (type == TYPE_UNUSED || type == TYPE_DELETED) + return false; + + switch (*mode) { + case ES_MODE_STARTED: + if (type != TYPE_FILE && type != TYPE_DIR) + return false; + *mode = ES_MODE_GET_FILE_ENTRY; + return true; + case ES_MODE_GET_FILE_ENTRY: + if (type != TYPE_STREAM) + return false; + *mode = ES_MODE_GET_STRM_ENTRY; + return true; + case ES_MODE_GET_STRM_ENTRY: + if (type != TYPE_EXTEND) + return false; + *mode = ES_MODE_GET_NAME_ENTRY; + return true; + case ES_MODE_GET_NAME_ENTRY: + if (type == TYPE_STREAM) + return false; + if (type != TYPE_EXTEND) { + if (!(type & TYPE_CRITICAL_SEC)) + return false; + *mode = ES_MODE_GET_CRITICAL_SEC_ENTRY; + } + return true; + case ES_MODE_GET_CRITICAL_SEC_ENTRY: + if (type == TYPE_EXTEND || type == TYPE_STREAM) + return false; + if ((type & TYPE_CRITICAL_SEC) != TYPE_CRITICAL_SEC) + return false; + return true; + default: + WARN_ON_ONCE(1); + return false; + } +} + +/* + * Returns a set of dentries for a file or dir. + * + * Note that this is a copy (dump) of dentries so that user should + * call write_entry_set() to apply changes made in this entry set + * to the real device. + * + * in: + * sb+p_dir+entry: indicates a file/dir + * type: specifies how many dentries should be included. + * out: + * file_ep: will point the first dentry(= file dentry) on success + * return: + * pointer of entry set on success, + * NULL on failure. + */ +struct exfat_entry_set_cache *exfat_get_dentry_set(struct super_block *sb, + struct exfat_chain *p_dir, int entry, unsigned int type, + struct exfat_dentry **file_ep) +{ + int ret; + unsigned int off, byte_offset, clu = 0; + unsigned int entry_type; + sector_t sec; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct exfat_entry_set_cache *es; + struct exfat_dentry *ep, *pos; + unsigned char num_entries; + enum exfat_validate_dentry_mode mode = ES_MODE_STARTED; + struct buffer_head *bh; + + if (p_dir->dir == DIR_DELETED) { + exfat_msg(sb, KERN_ERR, "access to deleted dentry\n"); + return NULL; + } + + byte_offset = EXFAT_DEN_TO_B(entry); + ret = exfat_walk_fat_chain(sb, p_dir, byte_offset, &clu); + if (ret) + return NULL; + + /* byte offset in cluster */ + byte_offset = EXFAT_CLU_OFFSET(byte_offset, sbi); + + /* byte offset in sector */ + off = EXFAT_BLK_OFFSET(byte_offset, sb); + + /* sector offset in cluster */ + sec = EXFAT_B_TO_BLK(byte_offset, sb); + sec += exfat_cluster_to_sector(sbi, clu); + + bh = sb_bread(sb, sec); + if (!bh) + return NULL; + + ep = (struct exfat_dentry *)(bh->b_data + off); + entry_type = exfat_get_entry_type(ep); + + if (entry_type != TYPE_FILE && entry_type != TYPE_DIR) + goto release_bh; + + num_entries = type == ES_ALL_ENTRIES ? + ep->dentry.file.num_ext + 1 : type; + es = kmalloc(struct_size(es, entries, num_entries), GFP_KERNEL); + if (!es) + goto release_bh; + + es->num_entries = num_entries; + es->sector = sec; + es->offset = off; + es->alloc_flag = p_dir->flags; + + pos = &es->entries[0]; + + while (num_entries) { + if (!exfat_validate_entry(exfat_get_entry_type(ep), &mode)) + goto free_es; + + /* copy dentry */ + memcpy(pos, ep, sizeof(struct exfat_dentry)); + + if (--num_entries == 0) + break; + + if (((off + DENTRY_SIZE) & (sb->s_blocksize - 1)) < + (off & (sb->s_blocksize - 1))) { + /* get the next sector */ + if (exfat_is_last_sector_in_cluster(sbi, sec)) { + if (es->alloc_flag == ALLOC_NO_FAT_CHAIN) + clu++; + else if (exfat_get_next_cluster(sb, &clu)) + goto free_es; + sec = exfat_cluster_to_sector(sbi, clu); + } else { + sec++; + } + + brelse(bh); + bh = sb_bread(sb, sec); + if (!bh) + goto free_es; + off = 0; + ep = (struct exfat_dentry *)bh->b_data; + } else { + ep++; + off += DENTRY_SIZE; + } + pos++; + } + + if (file_ep) + *file_ep = &es->entries[0]; + brelse(bh); + return es; + +free_es: + kfree(es); +release_bh: + brelse(bh); + return NULL; +} + +enum { + DIRENT_STEP_FILE, + DIRENT_STEP_STRM, + DIRENT_STEP_NAME, + DIRENT_STEP_SECD, +}; + +/* + * return values: + * >= 0 : return dir entiry position with the name in dir + * -EEXIST : (root dir, ".") it is the root dir itself + * -ENOENT : entry with the name does not exist + * -EIO : I/O error + */ +int exfat_find_dir_entry(struct super_block *sb, struct exfat_inode_info *ei, + struct exfat_chain *p_dir, struct exfat_uni_name *p_uniname, + int num_entries, unsigned int type) +{ + int i, rewind = 0, dentry = 0, end_eidx = 0, num_ext = 0, len; + int order, step, name_len = 0; + int dentries_per_clu, num_empty = 0; + unsigned int entry_type; + unsigned short *uniname = NULL; + struct exfat_chain clu; + struct exfat_hint *hint_stat = &ei->hint_stat; + struct exfat_hint_femp candi_empty; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + + dentries_per_clu = sbi->dentries_per_clu; + + exfat_chain_dup(&clu, p_dir); + + if (hint_stat->eidx) { + clu.dir = hint_stat->clu; + dentry = hint_stat->eidx; + end_eidx = dentry; + } + + candi_empty.eidx = EXFAT_HINT_NONE; +rewind: + order = 0; + step = DIRENT_STEP_FILE; + while (clu.dir != EXFAT_EOF_CLUSTER) { + i = dentry & (dentries_per_clu - 1); + for (; i < dentries_per_clu; i++, dentry++) { + struct exfat_dentry *ep; + struct buffer_head *bh; + + if (rewind && dentry == end_eidx) + goto not_found; + + ep = exfat_get_dentry(sb, &clu, i, &bh, NULL); + if (!ep) + return -EIO; + + entry_type = exfat_get_entry_type(ep); + + if (entry_type == TYPE_UNUSED || + entry_type == TYPE_DELETED) { + step = DIRENT_STEP_FILE; + + num_empty++; + if (candi_empty.eidx == EXFAT_HINT_NONE && + num_empty == 1) { + exfat_chain_set(&candi_empty.cur, + clu.dir, clu.size, clu.flags); + } + + if (candi_empty.eidx == EXFAT_HINT_NONE && + num_empty >= num_entries) { + candi_empty.eidx = + dentry - (num_empty - 1); + WARN_ON(candi_empty.eidx < 0); + candi_empty.count = num_empty; + + if (ei->hint_femp.eidx == + EXFAT_HINT_NONE || + candi_empty.eidx <= + ei->hint_femp.eidx) { + memcpy(&ei->hint_femp, + &candi_empty, + sizeof(candi_empty)); + } + } + + brelse(bh); + if (entry_type == TYPE_UNUSED) + goto not_found; + continue; + } + + num_empty = 0; + candi_empty.eidx = EXFAT_HINT_NONE; + + if (entry_type == TYPE_FILE || entry_type == TYPE_DIR) { + step = DIRENT_STEP_FILE; + if (type == TYPE_ALL || type == entry_type) { + num_ext = ep->dentry.file.num_ext; + step = DIRENT_STEP_STRM; + } + brelse(bh); + continue; + } + + if (entry_type == TYPE_STREAM) { + unsigned short name_hash; + + if (step != DIRENT_STEP_STRM) { + step = DIRENT_STEP_FILE; + brelse(bh); + continue; + } + step = DIRENT_STEP_FILE; + name_hash = le16_to_cpu( + ep->dentry.stream.name_hash); + if (p_uniname->name_hash == name_hash && + p_uniname->name_len == + ep->dentry.stream.name_len) { + step = DIRENT_STEP_NAME; + order = 1; + name_len = 0; + } + brelse(bh); + continue; + } + + brelse(bh); + if (entry_type == TYPE_EXTEND) { + unsigned short entry_uniname[16], unichar; + + if (step != DIRENT_STEP_NAME) { + step = DIRENT_STEP_FILE; + continue; + } + + if (++order == 2) + uniname = p_uniname->name; + else + uniname += EXFAT_FILE_NAME_LEN; + + len = exfat_extract_uni_name(ep, entry_uniname); + name_len += len; + + unichar = *(uniname+len); + *(uniname+len) = 0x0; + + if (exfat_uniname_ncmp(sb, uniname, + entry_uniname, len)) { + step = DIRENT_STEP_FILE; + } else if (p_uniname->name_len == name_len) { + if (order == num_ext) + goto found; + step = DIRENT_STEP_SECD; + } + + *(uniname+len) = unichar; + continue; + } + + if (entry_type & + (TYPE_CRITICAL_SEC | TYPE_BENIGN_SEC)) { + if (step == DIRENT_STEP_SECD) { + if (++order == num_ext) + goto found; + continue; + } + } + step = DIRENT_STEP_FILE; + } + + if (clu.flags == ALLOC_NO_FAT_CHAIN) { + if (--clu.size > 0) + clu.dir++; + else + clu.dir = EXFAT_EOF_CLUSTER; + } else { + if (exfat_get_next_cluster(sb, &clu.dir)) + return -EIO; + } + } + +not_found: + /* + * We started at not 0 index,so we should try to find target + * from 0 index to the index we started at. + */ + if (!rewind && end_eidx) { + rewind = 1; + dentry = 0; + clu.dir = p_dir->dir; + /* reset empty hint */ + num_empty = 0; + candi_empty.eidx = EXFAT_HINT_NONE; + goto rewind; + } + + /* initialized hint_stat */ + hint_stat->clu = p_dir->dir; + hint_stat->eidx = 0; + return -ENOENT; + +found: + /* next dentry we'll find is out of this cluster */ + if (!((dentry + 1) & (dentries_per_clu - 1))) { + int ret = 0; + + if (clu.flags == ALLOC_NO_FAT_CHAIN) { + if (--clu.size > 0) + clu.dir++; + else + clu.dir = EXFAT_EOF_CLUSTER; + } else { + ret = exfat_get_next_cluster(sb, &clu.dir); + } + + if (ret || clu.dir != EXFAT_EOF_CLUSTER) { + /* just initialized hint_stat */ + hint_stat->clu = p_dir->dir; + hint_stat->eidx = 0; + return (dentry - num_ext); + } + } + + hint_stat->clu = clu.dir; + hint_stat->eidx = dentry + 1; + return dentry - num_ext; +} + +int exfat_count_ext_entries(struct super_block *sb, struct exfat_chain *p_dir, + int entry, struct exfat_dentry *ep) +{ + int i, count = 0; + unsigned int type; + struct exfat_dentry *ext_ep; + struct buffer_head *bh; + + for (i = 0, entry++; i < ep->dentry.file.num_ext; i++, entry++) { + ext_ep = exfat_get_dentry(sb, p_dir, entry, &bh, NULL); + if (!ext_ep) + return -EIO; + + type = exfat_get_entry_type(ext_ep); + brelse(bh); + if (type == TYPE_EXTEND || type == TYPE_STREAM) + count++; + else + break; + } + return count; +} + +int exfat_count_dir_entries(struct super_block *sb, struct exfat_chain *p_dir) +{ + int i, count = 0; + int dentries_per_clu; + unsigned int entry_type; + struct exfat_chain clu; + struct exfat_dentry *ep; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct buffer_head *bh; + + dentries_per_clu = sbi->dentries_per_clu; + + exfat_chain_dup(&clu, p_dir); + + while (clu.dir != EXFAT_EOF_CLUSTER) { + for (i = 0; i < dentries_per_clu; i++) { + ep = exfat_get_dentry(sb, &clu, i, &bh, NULL); + if (!ep) + return -EIO; + entry_type = exfat_get_entry_type(ep); + brelse(bh); + + if (entry_type == TYPE_UNUSED) + return count; + if (entry_type != TYPE_DIR) + continue; + count++; + } + + if (clu.flags == ALLOC_NO_FAT_CHAIN) { + if (--clu.size > 0) + clu.dir++; + else + clu.dir = EXFAT_EOF_CLUSTER; + } else { + if (exfat_get_next_cluster(sb, &(clu.dir))) + return -EIO; + } + } + + return count; +} From a29a323deeb5f411e8542d18acc5a171856c57fb Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Mon, 2 Mar 2020 15:21:36 +0900 Subject: [PATCH 038/592] exfat: add file operations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds the implementation of file operations for exfat. Signed-off-by: Namjae Jeon Signed-off-by: Sungjong Seo Reviewed-by: Pali Rohár Reviewed-by: Christoph Hellwig Reviewed-by: Arnd Bergmann Signed-off-by: Al Viro Signed-off-by: Park Ju Hyung --- file.c | 360 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 360 insertions(+) create mode 100644 file.c diff --git a/file.c b/file.c new file mode 100644 index 000000000000..483f683757aa --- /dev/null +++ b/file.c @@ -0,0 +1,360 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + */ + +#include +#include +#include + +#include "exfat_raw.h" +#include "exfat_fs.h" + +static int exfat_cont_expand(struct inode *inode, loff_t size) +{ + struct address_space *mapping = inode->i_mapping; + loff_t start = i_size_read(inode), count = size - i_size_read(inode); + int err, err2; + + err = generic_cont_expand_simple(inode, size); + if (err) + return err; + + inode->i_ctime = inode->i_mtime = current_time(inode); + mark_inode_dirty(inode); + + if (!IS_SYNC(inode)) + return 0; + + err = filemap_fdatawrite_range(mapping, start, start + count - 1); + err2 = sync_mapping_buffers(mapping); + if (!err) + err = err2; + err2 = write_inode_now(inode, 1); + if (!err) + err = err2; + if (err) + return err; + + return filemap_fdatawait_range(mapping, start, start + count - 1); +} + +static bool exfat_allow_set_time(struct exfat_sb_info *sbi, struct inode *inode) +{ + mode_t allow_utime = sbi->options.allow_utime; + + if (!uid_eq(current_fsuid(), inode->i_uid)) { + if (in_group_p(inode->i_gid)) + allow_utime >>= 3; + if (allow_utime & MAY_WRITE) + return true; + } + + /* use a default check */ + return false; +} + +static int exfat_sanitize_mode(const struct exfat_sb_info *sbi, + struct inode *inode, umode_t *mode_ptr) +{ + mode_t i_mode, mask, perm; + + i_mode = inode->i_mode; + + mask = (S_ISREG(i_mode) || S_ISLNK(i_mode)) ? + sbi->options.fs_fmask : sbi->options.fs_dmask; + perm = *mode_ptr & ~(S_IFMT | mask); + + /* Of the r and x bits, all (subject to umask) must be present.*/ + if ((perm & 0555) != (i_mode & 0555)) + return -EPERM; + + if (exfat_mode_can_hold_ro(inode)) { + /* + * Of the w bits, either all (subject to umask) or none must + * be present. + */ + if ((perm & 0222) && ((perm & 0222) != (0222 & ~mask))) + return -EPERM; + } else { + /* + * If exfat_mode_can_hold_ro(inode) is false, can't change + * w bits. + */ + if ((perm & 0222) != (0222 & ~mask)) + return -EPERM; + } + + *mode_ptr &= S_IFMT | perm; + + return 0; +} + +/* resize the file length */ +int __exfat_truncate(struct inode *inode, loff_t new_size) +{ + unsigned int num_clusters_new, num_clusters_phys; + unsigned int last_clu = EXFAT_FREE_CLUSTER; + struct exfat_chain clu; + struct exfat_dentry *ep, *ep2; + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct exfat_inode_info *ei = EXFAT_I(inode); + struct exfat_entry_set_cache *es = NULL; + int evict = (ei->dir.dir == DIR_DELETED) ? 1 : 0; + + /* check if the given file ID is opened */ + if (ei->type != TYPE_FILE && ei->type != TYPE_DIR) + return -EPERM; + + exfat_set_vol_flags(sb, VOL_DIRTY); + + num_clusters_new = EXFAT_B_TO_CLU_ROUND_UP(i_size_read(inode), sbi); + num_clusters_phys = + EXFAT_B_TO_CLU_ROUND_UP(EXFAT_I(inode)->i_size_ondisk, sbi); + + exfat_chain_set(&clu, ei->start_clu, num_clusters_phys, ei->flags); + + if (new_size > 0) { + /* + * Truncate FAT chain num_clusters after the first cluster + * num_clusters = min(new, phys); + */ + unsigned int num_clusters = + min(num_clusters_new, num_clusters_phys); + + /* + * Follow FAT chain + * (defensive coding - works fine even with corrupted FAT table + */ + if (clu.flags == ALLOC_NO_FAT_CHAIN) { + clu.dir += num_clusters; + clu.size -= num_clusters; + } else { + while (num_clusters > 0) { + last_clu = clu.dir; + if (exfat_get_next_cluster(sb, &(clu.dir))) + return -EIO; + + num_clusters--; + clu.size--; + } + } + } else { + ei->flags = ALLOC_NO_FAT_CHAIN; + ei->start_clu = EXFAT_EOF_CLUSTER; + } + + i_size_write(inode, new_size); + + if (ei->type == TYPE_FILE) + ei->attr |= ATTR_ARCHIVE; + + /* update the directory entry */ + if (!evict) { + struct timespec64 ts; + + es = exfat_get_dentry_set(sb, &(ei->dir), ei->entry, + ES_ALL_ENTRIES, &ep); + if (!es) + return -EIO; + ep2 = ep + 1; + + ts = current_time(inode); + exfat_set_entry_time(sbi, &ts, + &ep->dentry.file.modify_tz, + &ep->dentry.file.modify_time, + &ep->dentry.file.modify_date, + &ep->dentry.file.modify_time_ms); + ep->dentry.file.attr = cpu_to_le16(ei->attr); + + /* File size should be zero if there is no cluster allocated */ + if (ei->start_clu == EXFAT_EOF_CLUSTER) { + ep->dentry.stream.valid_size = 0; + ep->dentry.stream.size = 0; + } else { + ep->dentry.stream.valid_size = cpu_to_le64(new_size); + ep->dentry.stream.size = ep->dentry.stream.valid_size; + } + + if (new_size == 0) { + /* Any directory can not be truncated to zero */ + WARN_ON(ei->type != TYPE_FILE); + + ep2->dentry.stream.flags = ALLOC_FAT_CHAIN; + ep2->dentry.stream.start_clu = EXFAT_FREE_CLUSTER; + } + + if (exfat_update_dir_chksum_with_entry_set(sb, es, + inode_needs_sync(inode))) + return -EIO; + kfree(es); + } + + /* cut off from the FAT chain */ + if (ei->flags == ALLOC_FAT_CHAIN && last_clu != EXFAT_FREE_CLUSTER && + last_clu != EXFAT_EOF_CLUSTER) { + if (exfat_ent_set(sb, last_clu, EXFAT_EOF_CLUSTER)) + return -EIO; + } + + /* invalidate cache and free the clusters */ + /* clear exfat cache */ + exfat_cache_inval_inode(inode); + + /* hint information */ + ei->hint_bmap.off = EXFAT_EOF_CLUSTER; + ei->hint_bmap.clu = EXFAT_EOF_CLUSTER; + if (ei->rwoffset > new_size) + ei->rwoffset = new_size; + + /* hint_stat will be used if this is directory. */ + ei->hint_stat.eidx = 0; + ei->hint_stat.clu = ei->start_clu; + ei->hint_femp.eidx = EXFAT_HINT_NONE; + + /* free the clusters */ + if (exfat_free_cluster(inode, &clu)) + return -EIO; + + exfat_set_vol_flags(sb, VOL_CLEAN); + + return 0; +} + +void exfat_truncate(struct inode *inode, loff_t size) +{ + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + unsigned int blocksize = 1 << inode->i_blkbits; + loff_t aligned_size; + int err; + + mutex_lock(&sbi->s_lock); + if (EXFAT_I(inode)->start_clu == 0) { + /* + * Empty start_clu != ~0 (not allocated) + */ + exfat_fs_error(sb, "tried to truncate zeroed cluster."); + goto write_size; + } + + err = __exfat_truncate(inode, i_size_read(inode)); + if (err) + goto write_size; + + inode->i_ctime = inode->i_mtime = current_time(inode); + if (IS_DIRSYNC(inode)) + exfat_sync_inode(inode); + else + mark_inode_dirty(inode); + + inode->i_blocks = ((i_size_read(inode) + (sbi->cluster_size - 1)) & + ~(sbi->cluster_size - 1)) >> inode->i_blkbits; +write_size: + aligned_size = i_size_read(inode); + if (aligned_size & (blocksize - 1)) { + aligned_size |= (blocksize - 1); + aligned_size++; + } + + if (EXFAT_I(inode)->i_size_ondisk > i_size_read(inode)) + EXFAT_I(inode)->i_size_ondisk = aligned_size; + + if (EXFAT_I(inode)->i_size_aligned > i_size_read(inode)) + EXFAT_I(inode)->i_size_aligned = aligned_size; + mutex_unlock(&sbi->s_lock); +} + +int exfat_getattr(const struct path *path, struct kstat *stat, + unsigned int request_mask, unsigned int query_flags) +{ + struct inode *inode = d_backing_inode(path->dentry); + struct exfat_inode_info *ei = EXFAT_I(inode); + + generic_fillattr(inode, stat); + stat->result_mask |= STATX_BTIME; + stat->btime.tv_sec = ei->i_crtime.tv_sec; + stat->btime.tv_nsec = ei->i_crtime.tv_nsec; + stat->blksize = EXFAT_SB(inode->i_sb)->cluster_size; + return 0; +} + +int exfat_setattr(struct dentry *dentry, struct iattr *attr) +{ + struct exfat_sb_info *sbi = EXFAT_SB(dentry->d_sb); + struct inode *inode = dentry->d_inode; + unsigned int ia_valid; + int error; + + if ((attr->ia_valid & ATTR_SIZE) && + attr->ia_size > i_size_read(inode)) { + error = exfat_cont_expand(inode, attr->ia_size); + if (error || attr->ia_valid == ATTR_SIZE) + return error; + attr->ia_valid &= ~ATTR_SIZE; + } + + /* Check for setting the inode time. */ + ia_valid = attr->ia_valid; + if ((ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET)) && + exfat_allow_set_time(sbi, inode)) { + attr->ia_valid &= ~(ATTR_MTIME_SET | ATTR_ATIME_SET | + ATTR_TIMES_SET); + } + + error = setattr_prepare(dentry, attr); + attr->ia_valid = ia_valid; + if (error) + goto out; + + if (((attr->ia_valid & ATTR_UID) && + !uid_eq(attr->ia_uid, sbi->options.fs_uid)) || + ((attr->ia_valid & ATTR_GID) && + !gid_eq(attr->ia_gid, sbi->options.fs_gid)) || + ((attr->ia_valid & ATTR_MODE) && + (attr->ia_mode & ~(S_IFREG | S_IFLNK | S_IFDIR | 0777)))) { + error = -EPERM; + goto out; + } + + /* + * We don't return -EPERM here. Yes, strange, but this is too + * old behavior. + */ + if (attr->ia_valid & ATTR_MODE) { + if (exfat_sanitize_mode(sbi, inode, &attr->ia_mode) < 0) + attr->ia_valid &= ~ATTR_MODE; + } + + if (attr->ia_valid & ATTR_SIZE) { + error = exfat_block_truncate_page(inode, attr->ia_size); + if (error) + goto out; + + down_write(&EXFAT_I(inode)->truncate_lock); + truncate_setsize(inode, attr->ia_size); + exfat_truncate(inode, attr->ia_size); + up_write(&EXFAT_I(inode)->truncate_lock); + } + + setattr_copy(inode, attr); + mark_inode_dirty(inode); + +out: + return error; +} + +const struct file_operations exfat_file_operations = { + .llseek = generic_file_llseek, + .read_iter = generic_file_read_iter, + .write_iter = generic_file_write_iter, + .mmap = generic_file_mmap, + .fsync = generic_file_fsync, + .splice_read = generic_file_splice_read, +}; + +const struct inode_operations exfat_file_inode_operations = { + .setattr = exfat_setattr, + .getattr = exfat_getattr, +}; From f2f2cd905e0a3bf2d5af37d0a1d876245674b503 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Mon, 2 Mar 2020 15:21:37 +0900 Subject: [PATCH 039/592] exfat: add fat entry operations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds the implementation of fat entry operations for exfat. Signed-off-by: Namjae Jeon Signed-off-by: Sungjong Seo Reviewed-by: Pali Rohár Reviewed-by: Christoph Hellwig Signed-off-by: Al Viro Signed-off-by: Park Ju Hyung --- fatent.c | 463 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 463 insertions(+) create mode 100644 fatent.c diff --git a/fatent.c b/fatent.c new file mode 100644 index 000000000000..a855b1769a96 --- /dev/null +++ b/fatent.c @@ -0,0 +1,463 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + */ + +#include +#include +#include + +#include "exfat_raw.h" +#include "exfat_fs.h" + +static int exfat_mirror_bh(struct super_block *sb, sector_t sec, + struct buffer_head *bh) +{ + struct buffer_head *c_bh; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + sector_t sec2; + int err = 0; + + if (sbi->FAT2_start_sector != sbi->FAT1_start_sector) { + sec2 = sec - sbi->FAT1_start_sector + sbi->FAT2_start_sector; + c_bh = sb_getblk(sb, sec2); + if (!c_bh) + return -ENOMEM; + memcpy(c_bh->b_data, bh->b_data, sb->s_blocksize); + set_buffer_uptodate(c_bh); + mark_buffer_dirty(c_bh); + if (sb->s_flags & SB_SYNCHRONOUS) + err = sync_dirty_buffer(c_bh); + brelse(c_bh); + } + + return err; +} + +static int __exfat_ent_get(struct super_block *sb, unsigned int loc, + unsigned int *content) +{ + unsigned int off; + sector_t sec; + struct buffer_head *bh; + + sec = FAT_ENT_OFFSET_SECTOR(sb, loc); + off = FAT_ENT_OFFSET_BYTE_IN_SECTOR(sb, loc); + + bh = sb_bread(sb, sec); + if (!bh) + return -EIO; + + *content = le32_to_cpu(*(__le32 *)(&bh->b_data[off])); + + /* remap reserved clusters to simplify code */ + if (*content > EXFAT_BAD_CLUSTER) + *content = EXFAT_EOF_CLUSTER; + + brelse(bh); + return 0; +} + +int exfat_ent_set(struct super_block *sb, unsigned int loc, + unsigned int content) +{ + unsigned int off; + sector_t sec; + __le32 *fat_entry; + struct buffer_head *bh; + + sec = FAT_ENT_OFFSET_SECTOR(sb, loc); + off = FAT_ENT_OFFSET_BYTE_IN_SECTOR(sb, loc); + + bh = sb_bread(sb, sec); + if (!bh) + return -EIO; + + fat_entry = (__le32 *)&(bh->b_data[off]); + *fat_entry = cpu_to_le32(content); + exfat_update_bh(sb, bh, sb->s_flags & SB_SYNCHRONOUS); + exfat_mirror_bh(sb, sec, bh); + brelse(bh); + return 0; +} + +static inline bool is_valid_cluster(struct exfat_sb_info *sbi, + unsigned int clus) +{ + if (clus < EXFAT_FIRST_CLUSTER || sbi->num_clusters <= clus) + return false; + return true; +} + +int exfat_ent_get(struct super_block *sb, unsigned int loc, + unsigned int *content) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + int err; + + if (!is_valid_cluster(sbi, loc)) { + exfat_fs_error(sb, "invalid access to FAT (entry 0x%08x)", + loc); + return -EIO; + } + + err = __exfat_ent_get(sb, loc, content); + if (err) { + exfat_fs_error(sb, + "failed to access to FAT (entry 0x%08x, err:%d)", + loc, err); + return err; + } + + if (*content == EXFAT_FREE_CLUSTER) { + exfat_fs_error(sb, + "invalid access to FAT free cluster (entry 0x%08x)", + loc); + return -EIO; + } + + if (*content == EXFAT_BAD_CLUSTER) { + exfat_fs_error(sb, + "invalid access to FAT bad cluster (entry 0x%08x)", + loc); + return -EIO; + } + + if (*content != EXFAT_EOF_CLUSTER && !is_valid_cluster(sbi, *content)) { + exfat_fs_error(sb, + "invalid access to FAT (entry 0x%08x) bogus content (0x%08x)", + loc, *content); + return -EIO; + } + + return 0; +} + +int exfat_chain_cont_cluster(struct super_block *sb, unsigned int chain, + unsigned int len) +{ + if (!len) + return 0; + + while (len > 1) { + if (exfat_ent_set(sb, chain, chain + 1)) + return -EIO; + chain++; + len--; + } + + if (exfat_ent_set(sb, chain, EXFAT_EOF_CLUSTER)) + return -EIO; + return 0; +} + +int exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain) +{ + unsigned int num_clusters = 0; + unsigned int clu; + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + + /* invalid cluster number */ + if (p_chain->dir == EXFAT_FREE_CLUSTER || + p_chain->dir == EXFAT_EOF_CLUSTER || + p_chain->dir < EXFAT_FIRST_CLUSTER) + return 0; + + /* no cluster to truncate */ + if (p_chain->size == 0) + return 0; + + /* check cluster validation */ + if (p_chain->dir < 2 && p_chain->dir >= sbi->num_clusters) { + exfat_msg(sb, KERN_ERR, "invalid start cluster (%u)", + p_chain->dir); + return -EIO; + } + + set_bit(EXFAT_SB_DIRTY, &sbi->s_state); + clu = p_chain->dir; + + if (p_chain->flags == ALLOC_NO_FAT_CHAIN) { + do { + exfat_clear_bitmap(inode, clu); + clu++; + + num_clusters++; + } while (num_clusters < p_chain->size); + } else { + do { + exfat_clear_bitmap(inode, clu); + + if (exfat_get_next_cluster(sb, &clu)) + goto dec_used_clus; + + num_clusters++; + } while (clu != EXFAT_EOF_CLUSTER); + } + +dec_used_clus: + sbi->used_clusters -= num_clusters; + return 0; +} + +int exfat_find_last_cluster(struct super_block *sb, struct exfat_chain *p_chain, + unsigned int *ret_clu) +{ + unsigned int clu, next; + unsigned int count = 0; + + next = p_chain->dir; + if (p_chain->flags == ALLOC_NO_FAT_CHAIN) { + *ret_clu = next + p_chain->size - 1; + return 0; + } + + do { + count++; + clu = next; + if (exfat_ent_get(sb, clu, &next)) + return -EIO; + } while (next != EXFAT_EOF_CLUSTER); + + if (p_chain->size != count) { + exfat_fs_error(sb, + "bogus directory size (clus : ondisk(%d) != counted(%d))", + p_chain->size, count); + return -EIO; + } + + *ret_clu = clu; + return 0; +} + +static inline int exfat_sync_bhs(struct buffer_head **bhs, int nr_bhs) +{ + int i, err = 0; + + for (i = 0; i < nr_bhs; i++) + write_dirty_buffer(bhs[i], 0); + + for (i = 0; i < nr_bhs; i++) { + wait_on_buffer(bhs[i]); + if (!err && !buffer_uptodate(bhs[i])) + err = -EIO; + } + return err; +} + +int exfat_zeroed_cluster(struct inode *dir, unsigned int clu) +{ + struct super_block *sb = dir->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct buffer_head *bhs[MAX_BUF_PER_PAGE]; + int nr_bhs = MAX_BUF_PER_PAGE; + sector_t blknr, last_blknr; + int err, i, n; + + blknr = exfat_cluster_to_sector(sbi, clu); + last_blknr = blknr + sbi->sect_per_clus; + + if (last_blknr > sbi->num_sectors && sbi->num_sectors > 0) { + exfat_fs_error_ratelimit(sb, + "%s: out of range(sect:%llu len:%u)", + __func__, (unsigned long long)blknr, + sbi->sect_per_clus); + return -EIO; + } + + /* Zeroing the unused blocks on this cluster */ + n = 0; + while (blknr < last_blknr) { + bhs[n] = sb_getblk(sb, blknr); + if (!bhs[n]) { + err = -ENOMEM; + goto release_bhs; + } + memset(bhs[n]->b_data, 0, sb->s_blocksize); + exfat_update_bh(sb, bhs[n], 0); + + n++; + blknr++; + + if (n == nr_bhs) { + if (IS_DIRSYNC(dir)) { + err = exfat_sync_bhs(bhs, n); + if (err) + goto release_bhs; + } + + for (i = 0; i < n; i++) + brelse(bhs[i]); + n = 0; + } + } + + if (IS_DIRSYNC(dir)) { + err = exfat_sync_bhs(bhs, n); + if (err) + goto release_bhs; + } + + for (i = 0; i < n; i++) + brelse(bhs[i]); + + return 0; + +release_bhs: + exfat_msg(sb, KERN_ERR, "failed zeroed sect %llu\n", + (unsigned long long)blknr); + for (i = 0; i < n; i++) + bforget(bhs[i]); + return err; +} + +int exfat_alloc_cluster(struct inode *inode, unsigned int num_alloc, + struct exfat_chain *p_chain) +{ + int ret = -ENOSPC; + unsigned int num_clusters = 0, total_cnt; + unsigned int hint_clu, new_clu, last_clu = EXFAT_EOF_CLUSTER; + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + + total_cnt = EXFAT_DATA_CLUSTER_COUNT(sbi); + + if (unlikely(total_cnt < sbi->used_clusters)) { + exfat_fs_error_ratelimit(sb, + "%s: invalid used clusters(t:%u,u:%u)\n", + __func__, total_cnt, sbi->used_clusters); + return -EIO; + } + + if (num_alloc > total_cnt - sbi->used_clusters) + return -ENOSPC; + + hint_clu = p_chain->dir; + /* find new cluster */ + if (hint_clu == EXFAT_EOF_CLUSTER) { + if (sbi->clu_srch_ptr < EXFAT_FIRST_CLUSTER) { + exfat_msg(sb, KERN_ERR, + "sbi->clu_srch_ptr is invalid (%u)\n", + sbi->clu_srch_ptr); + sbi->clu_srch_ptr = EXFAT_FIRST_CLUSTER; + } + + hint_clu = exfat_find_free_bitmap(sb, sbi->clu_srch_ptr); + if (hint_clu == EXFAT_EOF_CLUSTER) + return -ENOSPC; + } + + /* check cluster validation */ + if (hint_clu < EXFAT_FIRST_CLUSTER && hint_clu >= sbi->num_clusters) { + exfat_msg(sb, KERN_ERR, "hint_cluster is invalid (%u)\n", + hint_clu); + hint_clu = EXFAT_FIRST_CLUSTER; + if (p_chain->flags == ALLOC_NO_FAT_CHAIN) { + if (exfat_chain_cont_cluster(sb, p_chain->dir, + num_clusters)) + return -EIO; + p_chain->flags = ALLOC_FAT_CHAIN; + } + } + + set_bit(EXFAT_SB_DIRTY, &sbi->s_state); + + p_chain->dir = EXFAT_EOF_CLUSTER; + + while ((new_clu = exfat_find_free_bitmap(sb, hint_clu)) != + EXFAT_EOF_CLUSTER) { + if (new_clu != hint_clu && + p_chain->flags == ALLOC_NO_FAT_CHAIN) { + if (exfat_chain_cont_cluster(sb, p_chain->dir, + num_clusters)) { + ret = -EIO; + goto free_cluster; + } + p_chain->flags = ALLOC_FAT_CHAIN; + } + + /* update allocation bitmap */ + if (exfat_set_bitmap(inode, new_clu)) { + ret = -EIO; + goto free_cluster; + } + + num_clusters++; + + /* update FAT table */ + if (p_chain->flags == ALLOC_FAT_CHAIN) { + if (exfat_ent_set(sb, new_clu, EXFAT_EOF_CLUSTER)) { + ret = -EIO; + goto free_cluster; + } + } + + if (p_chain->dir == EXFAT_EOF_CLUSTER) { + p_chain->dir = new_clu; + } else if (p_chain->flags == ALLOC_FAT_CHAIN) { + if (exfat_ent_set(sb, last_clu, new_clu)) { + ret = -EIO; + goto free_cluster; + } + } + last_clu = new_clu; + + if (--num_alloc == 0) { + sbi->clu_srch_ptr = hint_clu; + sbi->used_clusters += num_clusters; + + p_chain->size += num_clusters; + return 0; + } + + hint_clu = new_clu + 1; + if (hint_clu >= sbi->num_clusters) { + hint_clu = EXFAT_FIRST_CLUSTER; + + if (p_chain->flags == ALLOC_NO_FAT_CHAIN) { + if (exfat_chain_cont_cluster(sb, p_chain->dir, + num_clusters)) { + ret = -EIO; + goto free_cluster; + } + p_chain->flags = ALLOC_FAT_CHAIN; + } + } + } +free_cluster: + if (num_clusters) + exfat_free_cluster(inode, p_chain); + return ret; +} + +int exfat_count_num_clusters(struct super_block *sb, + struct exfat_chain *p_chain, unsigned int *ret_count) +{ + unsigned int i, count; + unsigned int clu; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + + if (!p_chain->dir || p_chain->dir == EXFAT_EOF_CLUSTER) { + *ret_count = 0; + return 0; + } + + if (p_chain->flags == ALLOC_NO_FAT_CHAIN) { + *ret_count = p_chain->size; + return 0; + } + + clu = p_chain->dir; + count = 0; + for (i = EXFAT_FIRST_CLUSTER; i < sbi->num_clusters; i++) { + count++; + if (exfat_ent_get(sb, clu, &clu)) + return -EIO; + if (clu == EXFAT_EOF_CLUSTER) + break; + } + + *ret_count = count; + return 0; +} From 515d5e4dea5ee78f7dc87936583a068db250f7e1 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Mon, 2 Mar 2020 15:21:38 +0900 Subject: [PATCH 040/592] exfat: add bitmap operations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds the implementation of bitmap operations for exfat. Signed-off-by: Namjae Jeon Signed-off-by: Sungjong Seo Reviewed-by: Pali Rohár Reviewed-by: Christoph Hellwig Signed-off-by: Al Viro Signed-off-by: Park Ju Hyung --- balloc.c | 280 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 280 insertions(+) create mode 100644 balloc.c diff --git a/balloc.c b/balloc.c new file mode 100644 index 000000000000..6a04cc02565a --- /dev/null +++ b/balloc.c @@ -0,0 +1,280 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + */ + +#include +#include +#include + +#include "exfat_raw.h" +#include "exfat_fs.h" + +static const unsigned char free_bit[] = { + 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2,/* 0 ~ 19*/ + 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3,/* 20 ~ 39*/ + 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2,/* 40 ~ 59*/ + 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4,/* 60 ~ 79*/ + 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2,/* 80 ~ 99*/ + 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3,/*100 ~ 119*/ + 0, 1, 0, 2, 0, 1, 0, 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2,/*120 ~ 139*/ + 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5,/*140 ~ 159*/ + 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2,/*160 ~ 179*/ + 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3,/*180 ~ 199*/ + 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2,/*200 ~ 219*/ + 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4,/*220 ~ 239*/ + 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 /*240 ~ 254*/ +}; + +static const unsigned char used_bit[] = { + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3,/* 0 ~ 19*/ + 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4,/* 20 ~ 39*/ + 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5,/* 40 ~ 59*/ + 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,/* 60 ~ 79*/ + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4,/* 80 ~ 99*/ + 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6,/*100 ~ 119*/ + 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4,/*120 ~ 139*/ + 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,/*140 ~ 159*/ + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5,/*160 ~ 179*/ + 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5,/*180 ~ 199*/ + 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6,/*200 ~ 219*/ + 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,/*220 ~ 239*/ + 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 /*240 ~ 255*/ +}; + +/* + * Allocation Bitmap Management Functions + */ +static int exfat_allocate_bitmap(struct super_block *sb, + struct exfat_dentry *ep) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + long long map_size; + unsigned int i, need_map_size; + sector_t sector; + + sbi->map_clu = le32_to_cpu(ep->dentry.bitmap.start_clu); + map_size = le64_to_cpu(ep->dentry.bitmap.size); + need_map_size = ((EXFAT_DATA_CLUSTER_COUNT(sbi) - 1) / BITS_PER_BYTE) + + 1; + if (need_map_size != map_size) { + exfat_msg(sb, KERN_ERR, + "bogus allocation bitmap size(need : %u, cur : %lld)", + need_map_size, map_size); + /* + * Only allowed when bogus allocation + * bitmap size is large + */ + if (need_map_size > map_size) + return -EIO; + } + sbi->map_sectors = ((need_map_size - 1) >> + (sb->s_blocksize_bits)) + 1; + sbi->vol_amap = kmalloc_array(sbi->map_sectors, + sizeof(struct buffer_head *), GFP_KERNEL); + if (!sbi->vol_amap) + return -ENOMEM; + + sector = exfat_cluster_to_sector(sbi, sbi->map_clu); + for (i = 0; i < sbi->map_sectors; i++) { + sbi->vol_amap[i] = sb_bread(sb, sector + i); + if (!sbi->vol_amap[i]) { + /* release all buffers and free vol_amap */ + int j = 0; + + while (j < i) + brelse(sbi->vol_amap[j++]); + + kfree(sbi->vol_amap); + sbi->vol_amap = NULL; + return -EIO; + } + } + + sbi->pbr_bh = NULL; + return 0; +} + +int exfat_load_bitmap(struct super_block *sb) +{ + unsigned int i, type; + struct exfat_chain clu; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + + exfat_chain_set(&clu, sbi->root_dir, 0, ALLOC_FAT_CHAIN); + while (clu.dir != EXFAT_EOF_CLUSTER) { + for (i = 0; i < sbi->dentries_per_clu; i++) { + struct exfat_dentry *ep; + struct buffer_head *bh; + + ep = exfat_get_dentry(sb, &clu, i, &bh, NULL); + if (!ep) + return -EIO; + + type = exfat_get_entry_type(ep); + if (type == TYPE_UNUSED) + break; + if (type != TYPE_BITMAP) + continue; + if (ep->dentry.bitmap.flags == 0x0) { + int err; + + err = exfat_allocate_bitmap(sb, ep); + brelse(bh); + return err; + } + brelse(bh); + } + + if (exfat_get_next_cluster(sb, &clu.dir)) + return -EIO; + } + + return -EINVAL; +} + +void exfat_free_bitmap(struct exfat_sb_info *sbi) +{ + int i; + + brelse(sbi->pbr_bh); + + for (i = 0; i < sbi->map_sectors; i++) + __brelse(sbi->vol_amap[i]); + + kfree(sbi->vol_amap); +} + +/* + * If the value of "clu" is 0, it means cluster 2 which is the first cluster of + * the cluster heap. + */ +int exfat_set_bitmap(struct inode *inode, unsigned int clu) +{ + int i, b; + unsigned int ent_idx; + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + + WARN_ON(clu < EXFAT_FIRST_CLUSTER); + ent_idx = CLUSTER_TO_BITMAP_ENT(clu); + i = BITMAP_OFFSET_SECTOR_INDEX(sb, ent_idx); + b = BITMAP_OFFSET_BIT_IN_SECTOR(sb, ent_idx); + + set_bit_le(b, sbi->vol_amap[i]->b_data); + exfat_update_bh(sb, sbi->vol_amap[i], IS_DIRSYNC(inode)); + return 0; +} + +/* + * If the value of "clu" is 0, it means cluster 2 which is the first cluster of + * the cluster heap. + */ +void exfat_clear_bitmap(struct inode *inode, unsigned int clu) +{ + int i, b; + unsigned int ent_idx; + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct exfat_mount_options *opts = &sbi->options; + + WARN_ON(clu < EXFAT_FIRST_CLUSTER); + ent_idx = CLUSTER_TO_BITMAP_ENT(clu); + i = BITMAP_OFFSET_SECTOR_INDEX(sb, ent_idx); + b = BITMAP_OFFSET_BIT_IN_SECTOR(sb, ent_idx); + + clear_bit_le(b, sbi->vol_amap[i]->b_data); + exfat_update_bh(sb, sbi->vol_amap[i], IS_DIRSYNC(inode)); + + if (opts->discard) { + int ret_discard; + + ret_discard = sb_issue_discard(sb, + exfat_cluster_to_sector(sbi, clu + + EXFAT_RESERVED_CLUSTERS), + (1 << sbi->sect_per_clus_bits), GFP_NOFS, 0); + + if (ret_discard == -EOPNOTSUPP) { + exfat_msg(sb, KERN_ERR, + "discard not supported by device, disabling"); + opts->discard = 0; + } + } +} + +/* + * If the value of "clu" is 0, it means cluster 2 which is the first cluster of + * the cluster heap. + */ +unsigned int exfat_find_free_bitmap(struct super_block *sb, unsigned int clu) +{ + unsigned int i, map_i, map_b, ent_idx; + unsigned int clu_base, clu_free; + unsigned char k, clu_mask; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + + WARN_ON(clu < EXFAT_FIRST_CLUSTER); + ent_idx = CLUSTER_TO_BITMAP_ENT(clu); + clu_base = BITMAP_ENT_TO_CLUSTER(ent_idx & ~(BITS_PER_BYTE_MASK)); + clu_mask = IGNORED_BITS_REMAINED(clu, clu_base); + + map_i = BITMAP_OFFSET_SECTOR_INDEX(sb, ent_idx); + map_b = BITMAP_OFFSET_BYTE_IN_SECTOR(sb, ent_idx); + + for (i = EXFAT_FIRST_CLUSTER; i < sbi->num_clusters; + i += BITS_PER_BYTE) { + k = *(sbi->vol_amap[map_i]->b_data + map_b); + if (clu_mask > 0) { + k |= clu_mask; + clu_mask = 0; + } + if (k < 0xFF) { + clu_free = clu_base + free_bit[k]; + if (clu_free < sbi->num_clusters) + return clu_free; + } + clu_base += BITS_PER_BYTE; + + if (++map_b >= sb->s_blocksize || + clu_base >= sbi->num_clusters) { + if (++map_i >= sbi->map_sectors) { + clu_base = EXFAT_FIRST_CLUSTER; + map_i = 0; + } + map_b = 0; + } + } + + return EXFAT_EOF_CLUSTER; +} + +int exfat_count_used_clusters(struct super_block *sb, unsigned int *ret_count) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + unsigned int count = 0; + unsigned int i, map_i = 0, map_b = 0; + unsigned int total_clus = EXFAT_DATA_CLUSTER_COUNT(sbi); + unsigned int last_mask = total_clus & BITS_PER_BYTE_MASK; + unsigned char clu_bits; + const unsigned char last_bit_mask[] = {0, 0b00000001, 0b00000011, + 0b00000111, 0b00001111, 0b00011111, 0b00111111, 0b01111111}; + + total_clus &= ~last_mask; + for (i = 0; i < total_clus; i += BITS_PER_BYTE) { + clu_bits = *(sbi->vol_amap[map_i]->b_data + map_b); + count += used_bit[clu_bits]; + if (++map_b >= (unsigned int)sb->s_blocksize) { + map_i++; + map_b = 0; + } + } + + if (last_mask) { + clu_bits = *(sbi->vol_amap[map_i]->b_data + map_b); + clu_bits &= last_bit_mask[last_mask]; + count += used_bit[clu_bits]; + } + + *ret_count = count; + return 0; +} From 802bdb7817c5a3e243ab6f244ec0ef9e4e7553fb Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Mon, 2 Mar 2020 15:21:39 +0900 Subject: [PATCH 041/592] exfat: add exfat cache MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds the implementation of exfat cache. Signed-off-by: Namjae Jeon Signed-off-by: Sungjong Seo Reviewed-by: Pali Rohár Reviewed-by: Christoph Hellwig Signed-off-by: Al Viro Signed-off-by: Park Ju Hyung --- cache.c | 325 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 325 insertions(+) create mode 100644 cache.c diff --git a/cache.c b/cache.c new file mode 100644 index 000000000000..03d0824fc368 --- /dev/null +++ b/cache.c @@ -0,0 +1,325 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * linux/fs/fat/cache.c + * + * Written 1992,1993 by Werner Almesberger + * + * Mar 1999. AV. Changed cache, so that it uses the starting cluster instead + * of inode number. + * May 1999. AV. Fixed the bogosity with FAT32 (read "FAT28"). Fscking lusers. + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + */ + +#include +#include +#include + +#include "exfat_raw.h" +#include "exfat_fs.h" + +#define EXFAT_CACHE_VALID 0 +#define EXFAT_MAX_CACHE 16 + +struct exfat_cache { + struct list_head cache_list; + unsigned int nr_contig; /* number of contiguous clusters */ + unsigned int fcluster; /* cluster number in the file. */ + unsigned int dcluster; /* cluster number on disk. */ +}; + +struct exfat_cache_id { + unsigned int id; + unsigned int nr_contig; + unsigned int fcluster; + unsigned int dcluster; +}; + +static struct kmem_cache *exfat_cachep; + +static void exfat_cache_init_once(void *c) +{ + struct exfat_cache *cache = (struct exfat_cache *)c; + + INIT_LIST_HEAD(&cache->cache_list); +} + +int exfat_cache_init(void) +{ + exfat_cachep = kmem_cache_create("exfat_cache", + sizeof(struct exfat_cache), + 0, SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, + exfat_cache_init_once); + if (!exfat_cachep) + return -ENOMEM; + return 0; +} + +void exfat_cache_shutdown(void) +{ + if (!exfat_cachep) + return; + kmem_cache_destroy(exfat_cachep); +} + +void exfat_cache_init_inode(struct inode *inode) +{ + struct exfat_inode_info *ei = EXFAT_I(inode); + + spin_lock_init(&ei->cache_lru_lock); + ei->nr_caches = 0; + ei->cache_valid_id = EXFAT_CACHE_VALID + 1; + INIT_LIST_HEAD(&ei->cache_lru); +} + +static inline struct exfat_cache *exfat_cache_alloc(void) +{ + return kmem_cache_alloc(exfat_cachep, GFP_NOFS); +} + +static inline void exfat_cache_free(struct exfat_cache *cache) +{ + WARN_ON(!list_empty(&cache->cache_list)); + kmem_cache_free(exfat_cachep, cache); +} + +static inline void exfat_cache_update_lru(struct inode *inode, + struct exfat_cache *cache) +{ + struct exfat_inode_info *ei = EXFAT_I(inode); + + if (ei->cache_lru.next != &cache->cache_list) + list_move(&cache->cache_list, &ei->cache_lru); +} + +static unsigned int exfat_cache_lookup(struct inode *inode, + unsigned int fclus, struct exfat_cache_id *cid, + unsigned int *cached_fclus, unsigned int *cached_dclus) +{ + struct exfat_inode_info *ei = EXFAT_I(inode); + static struct exfat_cache nohit = { .fcluster = 0, }; + struct exfat_cache *hit = &nohit, *p; + unsigned int offset = EXFAT_EOF_CLUSTER; + + spin_lock(&ei->cache_lru_lock); + list_for_each_entry(p, &ei->cache_lru, cache_list) { + /* Find the cache of "fclus" or nearest cache. */ + if (p->fcluster <= fclus && hit->fcluster < p->fcluster) { + hit = p; + if (hit->fcluster + hit->nr_contig < fclus) { + offset = hit->nr_contig; + } else { + offset = fclus - hit->fcluster; + break; + } + } + } + if (hit != &nohit) { + exfat_cache_update_lru(inode, hit); + + cid->id = ei->cache_valid_id; + cid->nr_contig = hit->nr_contig; + cid->fcluster = hit->fcluster; + cid->dcluster = hit->dcluster; + *cached_fclus = cid->fcluster + offset; + *cached_dclus = cid->dcluster + offset; + } + spin_unlock(&ei->cache_lru_lock); + + return offset; +} + +static struct exfat_cache *exfat_cache_merge(struct inode *inode, + struct exfat_cache_id *new) +{ + struct exfat_inode_info *ei = EXFAT_I(inode); + struct exfat_cache *p; + + list_for_each_entry(p, &ei->cache_lru, cache_list) { + /* Find the same part as "new" in cluster-chain. */ + if (p->fcluster == new->fcluster) { + if (new->nr_contig > p->nr_contig) + p->nr_contig = new->nr_contig; + return p; + } + } + return NULL; +} + +static void exfat_cache_add(struct inode *inode, + struct exfat_cache_id *new) +{ + struct exfat_inode_info *ei = EXFAT_I(inode); + struct exfat_cache *cache, *tmp; + + if (new->fcluster == EXFAT_EOF_CLUSTER) /* dummy cache */ + return; + + spin_lock(&ei->cache_lru_lock); + if (new->id != EXFAT_CACHE_VALID && + new->id != ei->cache_valid_id) + goto unlock; /* this cache was invalidated */ + + cache = exfat_cache_merge(inode, new); + if (cache == NULL) { + if (ei->nr_caches < EXFAT_MAX_CACHE) { + ei->nr_caches++; + spin_unlock(&ei->cache_lru_lock); + + tmp = exfat_cache_alloc(); + if (!tmp) { + spin_lock(&ei->cache_lru_lock); + ei->nr_caches--; + spin_unlock(&ei->cache_lru_lock); + return; + } + + spin_lock(&ei->cache_lru_lock); + cache = exfat_cache_merge(inode, new); + if (cache != NULL) { + ei->nr_caches--; + exfat_cache_free(tmp); + goto out_update_lru; + } + cache = tmp; + } else { + struct list_head *p = ei->cache_lru.prev; + + cache = list_entry(p, + struct exfat_cache, cache_list); + } + cache->fcluster = new->fcluster; + cache->dcluster = new->dcluster; + cache->nr_contig = new->nr_contig; + } +out_update_lru: + exfat_cache_update_lru(inode, cache); +unlock: + spin_unlock(&ei->cache_lru_lock); +} + +/* + * Cache invalidation occurs rarely, thus the LRU chain is not updated. It + * fixes itself after a while. + */ +static void __exfat_cache_inval_inode(struct inode *inode) +{ + struct exfat_inode_info *ei = EXFAT_I(inode); + struct exfat_cache *cache; + + while (!list_empty(&ei->cache_lru)) { + cache = list_entry(ei->cache_lru.next, + struct exfat_cache, cache_list); + list_del_init(&cache->cache_list); + ei->nr_caches--; + exfat_cache_free(cache); + } + /* Update. The copy of caches before this id is discarded. */ + ei->cache_valid_id++; + if (ei->cache_valid_id == EXFAT_CACHE_VALID) + ei->cache_valid_id++; +} + +void exfat_cache_inval_inode(struct inode *inode) +{ + struct exfat_inode_info *ei = EXFAT_I(inode); + + spin_lock(&ei->cache_lru_lock); + __exfat_cache_inval_inode(inode); + spin_unlock(&ei->cache_lru_lock); +} + +static inline int cache_contiguous(struct exfat_cache_id *cid, + unsigned int dclus) +{ + cid->nr_contig++; + return cid->dcluster + cid->nr_contig == dclus; +} + +static inline void cache_init(struct exfat_cache_id *cid, + unsigned int fclus, unsigned int dclus) +{ + cid->id = EXFAT_CACHE_VALID; + cid->fcluster = fclus; + cid->dcluster = dclus; + cid->nr_contig = 0; +} + +int exfat_get_cluster(struct inode *inode, unsigned int cluster, + unsigned int *fclus, unsigned int *dclus, + unsigned int *last_dclus, int allow_eof) +{ + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + unsigned int limit = sbi->num_clusters; + struct exfat_inode_info *ei = EXFAT_I(inode); + struct exfat_cache_id cid; + unsigned int content; + + if (ei->start_clu == EXFAT_FREE_CLUSTER) { + exfat_fs_error(sb, + "invalid access to exfat cache (entry 0x%08x)", + ei->start_clu); + return -EIO; + } + + *fclus = 0; + *dclus = ei->start_clu; + *last_dclus = *dclus; + + /* + * Don`t use exfat_cache if zero offset or non-cluster allocation + */ + if (cluster == 0 || *dclus == EXFAT_EOF_CLUSTER) + return 0; + + cache_init(&cid, EXFAT_EOF_CLUSTER, EXFAT_EOF_CLUSTER); + + if (exfat_cache_lookup(inode, cluster, &cid, fclus, dclus) == + EXFAT_EOF_CLUSTER) { + /* + * dummy, always not contiguous + * This is reinitialized by cache_init(), later. + */ + WARN_ON(cid.id != EXFAT_CACHE_VALID || + cid.fcluster != EXFAT_EOF_CLUSTER || + cid.dcluster != EXFAT_EOF_CLUSTER || + cid.nr_contig != 0); + } + + if (*fclus == cluster) + return 0; + + while (*fclus < cluster) { + /* prevent the infinite loop of cluster chain */ + if (*fclus > limit) { + exfat_fs_error(sb, + "detected the cluster chain loop (i_pos %u)", + (*fclus)); + return -EIO; + } + + if (exfat_ent_get(sb, *dclus, &content)) + return -EIO; + + *last_dclus = *dclus; + *dclus = content; + (*fclus)++; + + if (content == EXFAT_EOF_CLUSTER) { + if (!allow_eof) { + exfat_fs_error(sb, + "invalid cluster chain (i_pos %u, last_clus 0x%08x is EOF)", + *fclus, (*last_dclus)); + return -EIO; + } + + break; + } + + if (!cache_contiguous(&cid, *dclus)) + cache_init(&cid, *fclus, *dclus); + } + + exfat_cache_add(inode, &cid); + return 0; +} From e395eef41746240f82b7b23d350834ecaed1607c Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Mon, 2 Mar 2020 15:21:40 +0900 Subject: [PATCH 042/592] exfat: add misc operations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds the implementation of misc operations for exfat. Signed-off-by: Namjae Jeon Signed-off-by: Sungjong Seo Reviewed-by: Arnd Bergmann Reviewed-by: Pali Rohár Reviewed-by: Christoph Hellwig Signed-off-by: Al Viro Signed-off-by: Park Ju Hyung --- misc.c | 163 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 misc.c diff --git a/misc.c b/misc.c new file mode 100644 index 000000000000..14a3300848f6 --- /dev/null +++ b/misc.c @@ -0,0 +1,163 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Written 1992,1993 by Werner Almesberger + * 22/11/2000 - Fixed fat_date_unix2dos for dates earlier than 01/01/1980 + * and date_dos2unix for date==0 by Igor Zhbanov(bsg@uniyar.ac.ru) + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + */ + +#include +#include +#include +#include + +#include "exfat_raw.h" +#include "exfat_fs.h" + +/* + * exfat_fs_error reports a file system problem that might indicate fa data + * corruption/inconsistency. Depending on 'errors' mount option the + * panic() is called, or error message is printed FAT and nothing is done, + * or filesystem is remounted read-only (default behavior). + * In case the file system is remounted read-only, it can be made writable + * again by remounting it. + */ +void __exfat_fs_error(struct super_block *sb, int report, const char *fmt, ...) +{ + struct exfat_mount_options *opts = &EXFAT_SB(sb)->options; + va_list args; + struct va_format vaf; + + if (report) { + va_start(args, fmt); + vaf.fmt = fmt; + vaf.va = &args; + exfat_msg(sb, KERN_ERR, "error, %pV\n", &vaf); + va_end(args); + } + + if (opts->errors == EXFAT_ERRORS_PANIC) { + panic("exFAT-fs (%s): fs panic from previous error\n", + sb->s_id); + } else if (opts->errors == EXFAT_ERRORS_RO && !sb_rdonly(sb)) { + sb->s_flags |= SB_RDONLY; + exfat_msg(sb, KERN_ERR, "Filesystem has been set read-only"); + } +} + +/* + * exfat_msg() - print preformated EXFAT specific messages. + * All logs except what uses exfat_fs_error() should be written by exfat_msg() + */ +void exfat_msg(struct super_block *sb, const char *level, const char *fmt, ...) +{ + struct va_format vaf; + va_list args; + + va_start(args, fmt); + vaf.fmt = fmt; + vaf.va = &args; + /* level means KERN_ pacility level */ + printk("%sexFAT-fs (%s): %pV\n", level, sb->s_id, &vaf); + va_end(args); +} + +#define SECS_PER_MIN (60) +#define TIMEZONE_SEC(x) ((x) * 15 * SECS_PER_MIN) + +static void exfat_adjust_tz(struct timespec64 *ts, u8 tz_off) +{ + if (tz_off <= 0x3F) + ts->tv_sec -= TIMEZONE_SEC(tz_off); + else /* 0x40 <= (tz_off & 0x7F) <=0x7F */ + ts->tv_sec += TIMEZONE_SEC(0x80 - tz_off); +} + +/* Convert a EXFAT time/date pair to a UNIX date (seconds since 1 1 70). */ +void exfat_get_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts, + u8 tz, __le16 time, __le16 date, u8 time_ms) +{ + u16 t = le16_to_cpu(time); + u16 d = le16_to_cpu(date); + + ts->tv_sec = mktime64(1980 + (d >> 9), d >> 5 & 0x000F, d & 0x001F, + t >> 11, (t >> 5) & 0x003F, (t & 0x001F) << 1); + + + /* time_ms field represent 0 ~ 199(1990 ms) */ + if (time_ms) { + ts->tv_sec += time_ms / 100; + ts->tv_nsec = (time_ms % 100) * 10 * NSEC_PER_MSEC; + } + + if (tz & EXFAT_TZ_VALID) + /* Adjust timezone to UTC0. */ + exfat_adjust_tz(ts, tz & ~EXFAT_TZ_VALID); + else + /* Convert from local time to UTC using time_offset. */ + ts->tv_sec -= sbi->options.time_offset * SECS_PER_MIN; +} + +/* Convert linear UNIX date to a EXFAT time/date pair. */ +void exfat_set_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts, + u8 *tz, __le16 *time, __le16 *date, u8 *time_ms) +{ + struct tm tm; + u16 t, d; + + time64_to_tm(ts->tv_sec, 0, &tm); + t = (tm.tm_hour << 11) | (tm.tm_min << 5) | (tm.tm_sec >> 1); + d = ((tm.tm_year - 80) << 9) | ((tm.tm_mon + 1) << 5) | tm.tm_mday; + + *time = cpu_to_le16(t); + *date = cpu_to_le16(d); + + /* time_ms field represent 0 ~ 199(1990 ms) */ + if (time_ms) + *time_ms = (tm.tm_sec & 1) * 100 + + ts->tv_nsec / (10 * NSEC_PER_MSEC); + + /* + * Record 00h value for OffsetFromUtc field and 1 value for OffsetValid + * to indicate that local time and UTC are the same. + */ + *tz = EXFAT_TZ_VALID; +} + +unsigned short exfat_calc_chksum_2byte(void *data, int len, + unsigned short chksum, int type) +{ + int i; + unsigned char *c = (unsigned char *)data; + + for (i = 0; i < len; i++, c++) { + if (((i == 2) || (i == 3)) && (type == CS_DIR_ENTRY)) + continue; + chksum = (((chksum & 1) << 15) | ((chksum & 0xFFFE) >> 1)) + + (unsigned short)*c; + } + return chksum; +} + +void exfat_update_bh(struct super_block *sb, struct buffer_head *bh, int sync) +{ + set_bit(EXFAT_SB_DIRTY, &EXFAT_SB(sb)->s_state); + set_buffer_uptodate(bh); + mark_buffer_dirty(bh); + + if (sync) + sync_dirty_buffer(bh); +} + +void exfat_chain_set(struct exfat_chain *ec, unsigned int dir, + unsigned int size, unsigned char flags) +{ + ec->dir = dir; + ec->size = size; + ec->flags = flags; +} + +void exfat_chain_dup(struct exfat_chain *dup, struct exfat_chain *ec) +{ + return exfat_chain_set(dup, ec->dir, ec->size, ec->flags); +} From eba44d3a40f82d1eeaa686d6b8460c73e9bccb3a Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Mon, 2 Mar 2020 15:21:41 +0900 Subject: [PATCH 043/592] exfat: add nls operations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds the implementation of nls operations for exfat. Signed-off-by: Namjae Jeon Signed-off-by: Sungjong Seo Reviewed-by: Pali Rohár Reviewed-by: Christoph Hellwig Signed-off-by: Al Viro Signed-off-by: Park Ju Hyung --- nls.c | 831 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 831 insertions(+) create mode 100644 nls.c diff --git a/nls.c b/nls.c new file mode 100644 index 000000000000..6d1c3ae130ff --- /dev/null +++ b/nls.c @@ -0,0 +1,831 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + */ + +#include +#include +#include +#include + +#include "exfat_raw.h" +#include "exfat_fs.h" + +/* Upcase tabel macro */ +#define EXFAT_NUM_UPCASE (2918) +#define UTBL_COUNT (0x10000) + +/* + * Upcase table in compressed format (7.2.5.1 Recommended Up-case Table + * in exfat specification, See: + * https://docs.microsoft.com/en-us/windows/win32/fileio/exfat-specification). + */ +static const unsigned short uni_def_upcase[EXFAT_NUM_UPCASE] = { + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, + 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, + 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, + 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, + 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, + 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, + 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, + 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, + 0x0060, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, + 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, + 0x0058, 0x0059, 0x005a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, + 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, + 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, + 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, + 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f, + 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, + 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, + 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, + 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf, + 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, + 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, + 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, + 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df, + 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, + 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, + 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00f7, + 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x0178, + 0x0100, 0x0100, 0x0102, 0x0102, 0x0104, 0x0104, 0x0106, 0x0106, + 0x0108, 0x0108, 0x010a, 0x010a, 0x010c, 0x010c, 0x010e, 0x010e, + 0x0110, 0x0110, 0x0112, 0x0112, 0x0114, 0x0114, 0x0116, 0x0116, + 0x0118, 0x0118, 0x011a, 0x011a, 0x011c, 0x011c, 0x011e, 0x011e, + 0x0120, 0x0120, 0x0122, 0x0122, 0x0124, 0x0124, 0x0126, 0x0126, + 0x0128, 0x0128, 0x012a, 0x012a, 0x012c, 0x012c, 0x012e, 0x012e, + 0x0130, 0x0131, 0x0132, 0x0132, 0x0134, 0x0134, 0x0136, 0x0136, + 0x0138, 0x0139, 0x0139, 0x013b, 0x013b, 0x013d, 0x013d, 0x013f, + 0x013f, 0x0141, 0x0141, 0x0143, 0x0143, 0x0145, 0x0145, 0x0147, + 0x0147, 0x0149, 0x014a, 0x014a, 0x014c, 0x014c, 0x014e, 0x014e, + 0x0150, 0x0150, 0x0152, 0x0152, 0x0154, 0x0154, 0x0156, 0x0156, + 0x0158, 0x0158, 0x015a, 0x015a, 0x015c, 0x015c, 0x015e, 0x015e, + 0x0160, 0x0160, 0x0162, 0x0162, 0x0164, 0x0164, 0x0166, 0x0166, + 0x0168, 0x0168, 0x016a, 0x016a, 0x016c, 0x016c, 0x016e, 0x016e, + 0x0170, 0x0170, 0x0172, 0x0172, 0x0174, 0x0174, 0x0176, 0x0176, + 0x0178, 0x0179, 0x0179, 0x017b, 0x017b, 0x017d, 0x017d, 0x017f, + 0x0243, 0x0181, 0x0182, 0x0182, 0x0184, 0x0184, 0x0186, 0x0187, + 0x0187, 0x0189, 0x018a, 0x018b, 0x018b, 0x018d, 0x018e, 0x018f, + 0x0190, 0x0191, 0x0191, 0x0193, 0x0194, 0x01f6, 0x0196, 0x0197, + 0x0198, 0x0198, 0x023d, 0x019b, 0x019c, 0x019d, 0x0220, 0x019f, + 0x01a0, 0x01a0, 0x01a2, 0x01a2, 0x01a4, 0x01a4, 0x01a6, 0x01a7, + 0x01a7, 0x01a9, 0x01aa, 0x01ab, 0x01ac, 0x01ac, 0x01ae, 0x01af, + 0x01af, 0x01b1, 0x01b2, 0x01b3, 0x01b3, 0x01b5, 0x01b5, 0x01b7, + 0x01b8, 0x01b8, 0x01ba, 0x01bb, 0x01bc, 0x01bc, 0x01be, 0x01f7, + 0x01c0, 0x01c1, 0x01c2, 0x01c3, 0x01c4, 0x01c5, 0x01c4, 0x01c7, + 0x01c8, 0x01c7, 0x01ca, 0x01cb, 0x01ca, 0x01cd, 0x01cd, 0x01cf, + 0x01cf, 0x01d1, 0x01d1, 0x01d3, 0x01d3, 0x01d5, 0x01d5, 0x01d7, + 0x01d7, 0x01d9, 0x01d9, 0x01db, 0x01db, 0x018e, 0x01de, 0x01de, + 0x01e0, 0x01e0, 0x01e2, 0x01e2, 0x01e4, 0x01e4, 0x01e6, 0x01e6, + 0x01e8, 0x01e8, 0x01ea, 0x01ea, 0x01ec, 0x01ec, 0x01ee, 0x01ee, + 0x01f0, 0x01f1, 0x01f2, 0x01f1, 0x01f4, 0x01f4, 0x01f6, 0x01f7, + 0x01f8, 0x01f8, 0x01fa, 0x01fa, 0x01fc, 0x01fc, 0x01fe, 0x01fe, + 0x0200, 0x0200, 0x0202, 0x0202, 0x0204, 0x0204, 0x0206, 0x0206, + 0x0208, 0x0208, 0x020a, 0x020a, 0x020c, 0x020c, 0x020e, 0x020e, + 0x0210, 0x0210, 0x0212, 0x0212, 0x0214, 0x0214, 0x0216, 0x0216, + 0x0218, 0x0218, 0x021a, 0x021a, 0x021c, 0x021c, 0x021e, 0x021e, + 0x0220, 0x0221, 0x0222, 0x0222, 0x0224, 0x0224, 0x0226, 0x0226, + 0x0228, 0x0228, 0x022a, 0x022a, 0x022c, 0x022c, 0x022e, 0x022e, + 0x0230, 0x0230, 0x0232, 0x0232, 0x0234, 0x0235, 0x0236, 0x0237, + 0x0238, 0x0239, 0x2c65, 0x023b, 0x023b, 0x023d, 0x2c66, 0x023f, + 0x0240, 0x0241, 0x0241, 0x0243, 0x0244, 0x0245, 0x0246, 0x0246, + 0x0248, 0x0248, 0x024a, 0x024a, 0x024c, 0x024c, 0x024e, 0x024e, + 0x0250, 0x0251, 0x0252, 0x0181, 0x0186, 0x0255, 0x0189, 0x018a, + 0x0258, 0x018f, 0x025a, 0x0190, 0x025c, 0x025d, 0x025e, 0x025f, + 0x0193, 0x0261, 0x0262, 0x0194, 0x0264, 0x0265, 0x0266, 0x0267, + 0x0197, 0x0196, 0x026a, 0x2c62, 0x026c, 0x026d, 0x026e, 0x019c, + 0x0270, 0x0271, 0x019d, 0x0273, 0x0274, 0x019f, 0x0276, 0x0277, + 0x0278, 0x0279, 0x027a, 0x027b, 0x027c, 0x2c64, 0x027e, 0x027f, + 0x01a6, 0x0281, 0x0282, 0x01a9, 0x0284, 0x0285, 0x0286, 0x0287, + 0x01ae, 0x0244, 0x01b1, 0x01b2, 0x0245, 0x028d, 0x028e, 0x028f, + 0x0290, 0x0291, 0x01b7, 0x0293, 0x0294, 0x0295, 0x0296, 0x0297, + 0x0298, 0x0299, 0x029a, 0x029b, 0x029c, 0x029d, 0x029e, 0x029f, + 0x02a0, 0x02a1, 0x02a2, 0x02a3, 0x02a4, 0x02a5, 0x02a6, 0x02a7, + 0x02a8, 0x02a9, 0x02aa, 0x02ab, 0x02ac, 0x02ad, 0x02ae, 0x02af, + 0x02b0, 0x02b1, 0x02b2, 0x02b3, 0x02b4, 0x02b5, 0x02b6, 0x02b7, + 0x02b8, 0x02b9, 0x02ba, 0x02bb, 0x02bc, 0x02bd, 0x02be, 0x02bf, + 0x02c0, 0x02c1, 0x02c2, 0x02c3, 0x02c4, 0x02c5, 0x02c6, 0x02c7, + 0x02c8, 0x02c9, 0x02ca, 0x02cb, 0x02cc, 0x02cd, 0x02ce, 0x02cf, + 0x02d0, 0x02d1, 0x02d2, 0x02d3, 0x02d4, 0x02d5, 0x02d6, 0x02d7, + 0x02d8, 0x02d9, 0x02da, 0x02db, 0x02dc, 0x02dd, 0x02de, 0x02df, + 0x02e0, 0x02e1, 0x02e2, 0x02e3, 0x02e4, 0x02e5, 0x02e6, 0x02e7, + 0x02e8, 0x02e9, 0x02ea, 0x02eb, 0x02ec, 0x02ed, 0x02ee, 0x02ef, + 0x02f0, 0x02f1, 0x02f2, 0x02f3, 0x02f4, 0x02f5, 0x02f6, 0x02f7, + 0x02f8, 0x02f9, 0x02fa, 0x02fb, 0x02fc, 0x02fd, 0x02fe, 0x02ff, + 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307, + 0x0308, 0x0309, 0x030a, 0x030b, 0x030c, 0x030d, 0x030e, 0x030f, + 0x0310, 0x0311, 0x0312, 0x0313, 0x0314, 0x0315, 0x0316, 0x0317, + 0x0318, 0x0319, 0x031a, 0x031b, 0x031c, 0x031d, 0x031e, 0x031f, + 0x0320, 0x0321, 0x0322, 0x0323, 0x0324, 0x0325, 0x0326, 0x0327, + 0x0328, 0x0329, 0x032a, 0x032b, 0x032c, 0x032d, 0x032e, 0x032f, + 0x0330, 0x0331, 0x0332, 0x0333, 0x0334, 0x0335, 0x0336, 0x0337, + 0x0338, 0x0339, 0x033a, 0x033b, 0x033c, 0x033d, 0x033e, 0x033f, + 0x0340, 0x0341, 0x0342, 0x0343, 0x0344, 0x0345, 0x0346, 0x0347, + 0x0348, 0x0349, 0x034a, 0x034b, 0x034c, 0x034d, 0x034e, 0x034f, + 0x0350, 0x0351, 0x0352, 0x0353, 0x0354, 0x0355, 0x0356, 0x0357, + 0x0358, 0x0359, 0x035a, 0x035b, 0x035c, 0x035d, 0x035e, 0x035f, + 0x0360, 0x0361, 0x0362, 0x0363, 0x0364, 0x0365, 0x0366, 0x0367, + 0x0368, 0x0369, 0x036a, 0x036b, 0x036c, 0x036d, 0x036e, 0x036f, + 0x0370, 0x0371, 0x0372, 0x0373, 0x0374, 0x0375, 0x0376, 0x0377, + 0x0378, 0x0379, 0x037a, 0x03fd, 0x03fe, 0x03ff, 0x037e, 0x037f, + 0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x0386, 0x0387, + 0x0388, 0x0389, 0x038a, 0x038b, 0x038c, 0x038d, 0x038e, 0x038f, + 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, + 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f, + 0x03a0, 0x03a1, 0x03a2, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7, + 0x03a8, 0x03a9, 0x03aa, 0x03ab, 0x0386, 0x0388, 0x0389, 0x038a, + 0x03b0, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, + 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f, + 0x03a0, 0x03a1, 0x03a3, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7, + 0x03a8, 0x03a9, 0x03aa, 0x03ab, 0x038c, 0x038e, 0x038f, 0x03cf, + 0x03d0, 0x03d1, 0x03d2, 0x03d3, 0x03d4, 0x03d5, 0x03d6, 0x03d7, + 0x03d8, 0x03d8, 0x03da, 0x03da, 0x03dc, 0x03dc, 0x03de, 0x03de, + 0x03e0, 0x03e0, 0x03e2, 0x03e2, 0x03e4, 0x03e4, 0x03e6, 0x03e6, + 0x03e8, 0x03e8, 0x03ea, 0x03ea, 0x03ec, 0x03ec, 0x03ee, 0x03ee, + 0x03f0, 0x03f1, 0x03f9, 0x03f3, 0x03f4, 0x03f5, 0x03f6, 0x03f7, + 0x03f7, 0x03f9, 0x03fa, 0x03fa, 0x03fc, 0x03fd, 0x03fe, 0x03ff, + 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, + 0x0408, 0x0409, 0x040a, 0x040b, 0x040c, 0x040d, 0x040e, 0x040f, + 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, + 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f, + 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, + 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f, + 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, + 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f, + 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, + 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f, + 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, + 0x0408, 0x0409, 0x040a, 0x040b, 0x040c, 0x040d, 0x040e, 0x040f, + 0x0460, 0x0460, 0x0462, 0x0462, 0x0464, 0x0464, 0x0466, 0x0466, + 0x0468, 0x0468, 0x046a, 0x046a, 0x046c, 0x046c, 0x046e, 0x046e, + 0x0470, 0x0470, 0x0472, 0x0472, 0x0474, 0x0474, 0x0476, 0x0476, + 0x0478, 0x0478, 0x047a, 0x047a, 0x047c, 0x047c, 0x047e, 0x047e, + 0x0480, 0x0480, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487, + 0x0488, 0x0489, 0x048a, 0x048a, 0x048c, 0x048c, 0x048e, 0x048e, + 0x0490, 0x0490, 0x0492, 0x0492, 0x0494, 0x0494, 0x0496, 0x0496, + 0x0498, 0x0498, 0x049a, 0x049a, 0x049c, 0x049c, 0x049e, 0x049e, + 0x04a0, 0x04a0, 0x04a2, 0x04a2, 0x04a4, 0x04a4, 0x04a6, 0x04a6, + 0x04a8, 0x04a8, 0x04aa, 0x04aa, 0x04ac, 0x04ac, 0x04ae, 0x04ae, + 0x04b0, 0x04b0, 0x04b2, 0x04b2, 0x04b4, 0x04b4, 0x04b6, 0x04b6, + 0x04b8, 0x04b8, 0x04ba, 0x04ba, 0x04bc, 0x04bc, 0x04be, 0x04be, + 0x04c0, 0x04c1, 0x04c1, 0x04c3, 0x04c3, 0x04c5, 0x04c5, 0x04c7, + 0x04c7, 0x04c9, 0x04c9, 0x04cb, 0x04cb, 0x04cd, 0x04cd, 0x04c0, + 0x04d0, 0x04d0, 0x04d2, 0x04d2, 0x04d4, 0x04d4, 0x04d6, 0x04d6, + 0x04d8, 0x04d8, 0x04da, 0x04da, 0x04dc, 0x04dc, 0x04de, 0x04de, + 0x04e0, 0x04e0, 0x04e2, 0x04e2, 0x04e4, 0x04e4, 0x04e6, 0x04e6, + 0x04e8, 0x04e8, 0x04ea, 0x04ea, 0x04ec, 0x04ec, 0x04ee, 0x04ee, + 0x04f0, 0x04f0, 0x04f2, 0x04f2, 0x04f4, 0x04f4, 0x04f6, 0x04f6, + 0x04f8, 0x04f8, 0x04fa, 0x04fa, 0x04fc, 0x04fc, 0x04fe, 0x04fe, + 0x0500, 0x0500, 0x0502, 0x0502, 0x0504, 0x0504, 0x0506, 0x0506, + 0x0508, 0x0508, 0x050a, 0x050a, 0x050c, 0x050c, 0x050e, 0x050e, + 0x0510, 0x0510, 0x0512, 0x0512, 0x0514, 0x0515, 0x0516, 0x0517, + 0x0518, 0x0519, 0x051a, 0x051b, 0x051c, 0x051d, 0x051e, 0x051f, + 0x0520, 0x0521, 0x0522, 0x0523, 0x0524, 0x0525, 0x0526, 0x0527, + 0x0528, 0x0529, 0x052a, 0x052b, 0x052c, 0x052d, 0x052e, 0x052f, + 0x0530, 0x0531, 0x0532, 0x0533, 0x0534, 0x0535, 0x0536, 0x0537, + 0x0538, 0x0539, 0x053a, 0x053b, 0x053c, 0x053d, 0x053e, 0x053f, + 0x0540, 0x0541, 0x0542, 0x0543, 0x0544, 0x0545, 0x0546, 0x0547, + 0x0548, 0x0549, 0x054a, 0x054b, 0x054c, 0x054d, 0x054e, 0x054f, + 0x0550, 0x0551, 0x0552, 0x0553, 0x0554, 0x0555, 0x0556, 0x0557, + 0x0558, 0x0559, 0x055a, 0x055b, 0x055c, 0x055d, 0x055e, 0x055f, + 0x0560, 0x0531, 0x0532, 0x0533, 0x0534, 0x0535, 0x0536, 0x0537, + 0x0538, 0x0539, 0x053a, 0x053b, 0x053c, 0x053d, 0x053e, 0x053f, + 0x0540, 0x0541, 0x0542, 0x0543, 0x0544, 0x0545, 0x0546, 0x0547, + 0x0548, 0x0549, 0x054a, 0x054b, 0x054c, 0x054d, 0x054e, 0x054f, + 0x0550, 0x0551, 0x0552, 0x0553, 0x0554, 0x0555, 0x0556, 0xffff, + 0x17f6, 0x2c63, 0x1d7e, 0x1d7f, 0x1d80, 0x1d81, 0x1d82, 0x1d83, + 0x1d84, 0x1d85, 0x1d86, 0x1d87, 0x1d88, 0x1d89, 0x1d8a, 0x1d8b, + 0x1d8c, 0x1d8d, 0x1d8e, 0x1d8f, 0x1d90, 0x1d91, 0x1d92, 0x1d93, + 0x1d94, 0x1d95, 0x1d96, 0x1d97, 0x1d98, 0x1d99, 0x1d9a, 0x1d9b, + 0x1d9c, 0x1d9d, 0x1d9e, 0x1d9f, 0x1da0, 0x1da1, 0x1da2, 0x1da3, + 0x1da4, 0x1da5, 0x1da6, 0x1da7, 0x1da8, 0x1da9, 0x1daa, 0x1dab, + 0x1dac, 0x1dad, 0x1dae, 0x1daf, 0x1db0, 0x1db1, 0x1db2, 0x1db3, + 0x1db4, 0x1db5, 0x1db6, 0x1db7, 0x1db8, 0x1db9, 0x1dba, 0x1dbb, + 0x1dbc, 0x1dbd, 0x1dbe, 0x1dbf, 0x1dc0, 0x1dc1, 0x1dc2, 0x1dc3, + 0x1dc4, 0x1dc5, 0x1dc6, 0x1dc7, 0x1dc8, 0x1dc9, 0x1dca, 0x1dcb, + 0x1dcc, 0x1dcd, 0x1dce, 0x1dcf, 0x1dd0, 0x1dd1, 0x1dd2, 0x1dd3, + 0x1dd4, 0x1dd5, 0x1dd6, 0x1dd7, 0x1dd8, 0x1dd9, 0x1dda, 0x1ddb, + 0x1ddc, 0x1ddd, 0x1dde, 0x1ddf, 0x1de0, 0x1de1, 0x1de2, 0x1de3, + 0x1de4, 0x1de5, 0x1de6, 0x1de7, 0x1de8, 0x1de9, 0x1dea, 0x1deb, + 0x1dec, 0x1ded, 0x1dee, 0x1def, 0x1df0, 0x1df1, 0x1df2, 0x1df3, + 0x1df4, 0x1df5, 0x1df6, 0x1df7, 0x1df8, 0x1df9, 0x1dfa, 0x1dfb, + 0x1dfc, 0x1dfd, 0x1dfe, 0x1dff, 0x1e00, 0x1e00, 0x1e02, 0x1e02, + 0x1e04, 0x1e04, 0x1e06, 0x1e06, 0x1e08, 0x1e08, 0x1e0a, 0x1e0a, + 0x1e0c, 0x1e0c, 0x1e0e, 0x1e0e, 0x1e10, 0x1e10, 0x1e12, 0x1e12, + 0x1e14, 0x1e14, 0x1e16, 0x1e16, 0x1e18, 0x1e18, 0x1e1a, 0x1e1a, + 0x1e1c, 0x1e1c, 0x1e1e, 0x1e1e, 0x1e20, 0x1e20, 0x1e22, 0x1e22, + 0x1e24, 0x1e24, 0x1e26, 0x1e26, 0x1e28, 0x1e28, 0x1e2a, 0x1e2a, + 0x1e2c, 0x1e2c, 0x1e2e, 0x1e2e, 0x1e30, 0x1e30, 0x1e32, 0x1e32, + 0x1e34, 0x1e34, 0x1e36, 0x1e36, 0x1e38, 0x1e38, 0x1e3a, 0x1e3a, + 0x1e3c, 0x1e3c, 0x1e3e, 0x1e3e, 0x1e40, 0x1e40, 0x1e42, 0x1e42, + 0x1e44, 0x1e44, 0x1e46, 0x1e46, 0x1e48, 0x1e48, 0x1e4a, 0x1e4a, + 0x1e4c, 0x1e4c, 0x1e4e, 0x1e4e, 0x1e50, 0x1e50, 0x1e52, 0x1e52, + 0x1e54, 0x1e54, 0x1e56, 0x1e56, 0x1e58, 0x1e58, 0x1e5a, 0x1e5a, + 0x1e5c, 0x1e5c, 0x1e5e, 0x1e5e, 0x1e60, 0x1e60, 0x1e62, 0x1e62, + 0x1e64, 0x1e64, 0x1e66, 0x1e66, 0x1e68, 0x1e68, 0x1e6a, 0x1e6a, + 0x1e6c, 0x1e6c, 0x1e6e, 0x1e6e, 0x1e70, 0x1e70, 0x1e72, 0x1e72, + 0x1e74, 0x1e74, 0x1e76, 0x1e76, 0x1e78, 0x1e78, 0x1e7a, 0x1e7a, + 0x1e7c, 0x1e7c, 0x1e7e, 0x1e7e, 0x1e80, 0x1e80, 0x1e82, 0x1e82, + 0x1e84, 0x1e84, 0x1e86, 0x1e86, 0x1e88, 0x1e88, 0x1e8a, 0x1e8a, + 0x1e8c, 0x1e8c, 0x1e8e, 0x1e8e, 0x1e90, 0x1e90, 0x1e92, 0x1e92, + 0x1e94, 0x1e94, 0x1e96, 0x1e97, 0x1e98, 0x1e99, 0x1e9a, 0x1e9b, + 0x1e9c, 0x1e9d, 0x1e9e, 0x1e9f, 0x1ea0, 0x1ea0, 0x1ea2, 0x1ea2, + 0x1ea4, 0x1ea4, 0x1ea6, 0x1ea6, 0x1ea8, 0x1ea8, 0x1eaa, 0x1eaa, + 0x1eac, 0x1eac, 0x1eae, 0x1eae, 0x1eb0, 0x1eb0, 0x1eb2, 0x1eb2, + 0x1eb4, 0x1eb4, 0x1eb6, 0x1eb6, 0x1eb8, 0x1eb8, 0x1eba, 0x1eba, + 0x1ebc, 0x1ebc, 0x1ebe, 0x1ebe, 0x1ec0, 0x1ec0, 0x1ec2, 0x1ec2, + 0x1ec4, 0x1ec4, 0x1ec6, 0x1ec6, 0x1ec8, 0x1ec8, 0x1eca, 0x1eca, + 0x1ecc, 0x1ecc, 0x1ece, 0x1ece, 0x1ed0, 0x1ed0, 0x1ed2, 0x1ed2, + 0x1ed4, 0x1ed4, 0x1ed6, 0x1ed6, 0x1ed8, 0x1ed8, 0x1eda, 0x1eda, + 0x1edc, 0x1edc, 0x1ede, 0x1ede, 0x1ee0, 0x1ee0, 0x1ee2, 0x1ee2, + 0x1ee4, 0x1ee4, 0x1ee6, 0x1ee6, 0x1ee8, 0x1ee8, 0x1eea, 0x1eea, + 0x1eec, 0x1eec, 0x1eee, 0x1eee, 0x1ef0, 0x1ef0, 0x1ef2, 0x1ef2, + 0x1ef4, 0x1ef4, 0x1ef6, 0x1ef6, 0x1ef8, 0x1ef8, 0x1efa, 0x1efb, + 0x1efc, 0x1efd, 0x1efe, 0x1eff, 0x1f08, 0x1f09, 0x1f0a, 0x1f0b, + 0x1f0c, 0x1f0d, 0x1f0e, 0x1f0f, 0x1f08, 0x1f09, 0x1f0a, 0x1f0b, + 0x1f0c, 0x1f0d, 0x1f0e, 0x1f0f, 0x1f18, 0x1f19, 0x1f1a, 0x1f1b, + 0x1f1c, 0x1f1d, 0x1f16, 0x1f17, 0x1f18, 0x1f19, 0x1f1a, 0x1f1b, + 0x1f1c, 0x1f1d, 0x1f1e, 0x1f1f, 0x1f28, 0x1f29, 0x1f2a, 0x1f2b, + 0x1f2c, 0x1f2d, 0x1f2e, 0x1f2f, 0x1f28, 0x1f29, 0x1f2a, 0x1f2b, + 0x1f2c, 0x1f2d, 0x1f2e, 0x1f2f, 0x1f38, 0x1f39, 0x1f3a, 0x1f3b, + 0x1f3c, 0x1f3d, 0x1f3e, 0x1f3f, 0x1f38, 0x1f39, 0x1f3a, 0x1f3b, + 0x1f3c, 0x1f3d, 0x1f3e, 0x1f3f, 0x1f48, 0x1f49, 0x1f4a, 0x1f4b, + 0x1f4c, 0x1f4d, 0x1f46, 0x1f47, 0x1f48, 0x1f49, 0x1f4a, 0x1f4b, + 0x1f4c, 0x1f4d, 0x1f4e, 0x1f4f, 0x1f50, 0x1f59, 0x1f52, 0x1f5b, + 0x1f54, 0x1f5d, 0x1f56, 0x1f5f, 0x1f58, 0x1f59, 0x1f5a, 0x1f5b, + 0x1f5c, 0x1f5d, 0x1f5e, 0x1f5f, 0x1f68, 0x1f69, 0x1f6a, 0x1f6b, + 0x1f6c, 0x1f6d, 0x1f6e, 0x1f6f, 0x1f68, 0x1f69, 0x1f6a, 0x1f6b, + 0x1f6c, 0x1f6d, 0x1f6e, 0x1f6f, 0x1fba, 0x1fbb, 0x1fc8, 0x1fc9, + 0x1fca, 0x1fcb, 0x1fda, 0x1fdb, 0x1ff8, 0x1ff9, 0x1fea, 0x1feb, + 0x1ffa, 0x1ffb, 0x1f7e, 0x1f7f, 0x1f88, 0x1f89, 0x1f8a, 0x1f8b, + 0x1f8c, 0x1f8d, 0x1f8e, 0x1f8f, 0x1f88, 0x1f89, 0x1f8a, 0x1f8b, + 0x1f8c, 0x1f8d, 0x1f8e, 0x1f8f, 0x1f98, 0x1f99, 0x1f9a, 0x1f9b, + 0x1f9c, 0x1f9d, 0x1f9e, 0x1f9f, 0x1f98, 0x1f99, 0x1f9a, 0x1f9b, + 0x1f9c, 0x1f9d, 0x1f9e, 0x1f9f, 0x1fa8, 0x1fa9, 0x1faa, 0x1fab, + 0x1fac, 0x1fad, 0x1fae, 0x1faf, 0x1fa8, 0x1fa9, 0x1faa, 0x1fab, + 0x1fac, 0x1fad, 0x1fae, 0x1faf, 0x1fb8, 0x1fb9, 0x1fb2, 0x1fbc, + 0x1fb4, 0x1fb5, 0x1fb6, 0x1fb7, 0x1fb8, 0x1fb9, 0x1fba, 0x1fbb, + 0x1fbc, 0x1fbd, 0x1fbe, 0x1fbf, 0x1fc0, 0x1fc1, 0x1fc2, 0x1fc3, + 0x1fc4, 0x1fc5, 0x1fc6, 0x1fc7, 0x1fc8, 0x1fc9, 0x1fca, 0x1fcb, + 0x1fc3, 0x1fcd, 0x1fce, 0x1fcf, 0x1fd8, 0x1fd9, 0x1fd2, 0x1fd3, + 0x1fd4, 0x1fd5, 0x1fd6, 0x1fd7, 0x1fd8, 0x1fd9, 0x1fda, 0x1fdb, + 0x1fdc, 0x1fdd, 0x1fde, 0x1fdf, 0x1fe8, 0x1fe9, 0x1fe2, 0x1fe3, + 0x1fe4, 0x1fec, 0x1fe6, 0x1fe7, 0x1fe8, 0x1fe9, 0x1fea, 0x1feb, + 0x1fec, 0x1fed, 0x1fee, 0x1fef, 0x1ff0, 0x1ff1, 0x1ff2, 0x1ff3, + 0x1ff4, 0x1ff5, 0x1ff6, 0x1ff7, 0x1ff8, 0x1ff9, 0x1ffa, 0x1ffb, + 0x1ff3, 0x1ffd, 0x1ffe, 0x1fff, 0x2000, 0x2001, 0x2002, 0x2003, + 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200a, 0x200b, + 0x200c, 0x200d, 0x200e, 0x200f, 0x2010, 0x2011, 0x2012, 0x2013, + 0x2014, 0x2015, 0x2016, 0x2017, 0x2018, 0x2019, 0x201a, 0x201b, + 0x201c, 0x201d, 0x201e, 0x201f, 0x2020, 0x2021, 0x2022, 0x2023, + 0x2024, 0x2025, 0x2026, 0x2027, 0x2028, 0x2029, 0x202a, 0x202b, + 0x202c, 0x202d, 0x202e, 0x202f, 0x2030, 0x2031, 0x2032, 0x2033, + 0x2034, 0x2035, 0x2036, 0x2037, 0x2038, 0x2039, 0x203a, 0x203b, + 0x203c, 0x203d, 0x203e, 0x203f, 0x2040, 0x2041, 0x2042, 0x2043, + 0x2044, 0x2045, 0x2046, 0x2047, 0x2048, 0x2049, 0x204a, 0x204b, + 0x204c, 0x204d, 0x204e, 0x204f, 0x2050, 0x2051, 0x2052, 0x2053, + 0x2054, 0x2055, 0x2056, 0x2057, 0x2058, 0x2059, 0x205a, 0x205b, + 0x205c, 0x205d, 0x205e, 0x205f, 0x2060, 0x2061, 0x2062, 0x2063, + 0x2064, 0x2065, 0x2066, 0x2067, 0x2068, 0x2069, 0x206a, 0x206b, + 0x206c, 0x206d, 0x206e, 0x206f, 0x2070, 0x2071, 0x2072, 0x2073, + 0x2074, 0x2075, 0x2076, 0x2077, 0x2078, 0x2079, 0x207a, 0x207b, + 0x207c, 0x207d, 0x207e, 0x207f, 0x2080, 0x2081, 0x2082, 0x2083, + 0x2084, 0x2085, 0x2086, 0x2087, 0x2088, 0x2089, 0x208a, 0x208b, + 0x208c, 0x208d, 0x208e, 0x208f, 0x2090, 0x2091, 0x2092, 0x2093, + 0x2094, 0x2095, 0x2096, 0x2097, 0x2098, 0x2099, 0x209a, 0x209b, + 0x209c, 0x209d, 0x209e, 0x209f, 0x20a0, 0x20a1, 0x20a2, 0x20a3, + 0x20a4, 0x20a5, 0x20a6, 0x20a7, 0x20a8, 0x20a9, 0x20aa, 0x20ab, + 0x20ac, 0x20ad, 0x20ae, 0x20af, 0x20b0, 0x20b1, 0x20b2, 0x20b3, + 0x20b4, 0x20b5, 0x20b6, 0x20b7, 0x20b8, 0x20b9, 0x20ba, 0x20bb, + 0x20bc, 0x20bd, 0x20be, 0x20bf, 0x20c0, 0x20c1, 0x20c2, 0x20c3, + 0x20c4, 0x20c5, 0x20c6, 0x20c7, 0x20c8, 0x20c9, 0x20ca, 0x20cb, + 0x20cc, 0x20cd, 0x20ce, 0x20cf, 0x20d0, 0x20d1, 0x20d2, 0x20d3, + 0x20d4, 0x20d5, 0x20d6, 0x20d7, 0x20d8, 0x20d9, 0x20da, 0x20db, + 0x20dc, 0x20dd, 0x20de, 0x20df, 0x20e0, 0x20e1, 0x20e2, 0x20e3, + 0x20e4, 0x20e5, 0x20e6, 0x20e7, 0x20e8, 0x20e9, 0x20ea, 0x20eb, + 0x20ec, 0x20ed, 0x20ee, 0x20ef, 0x20f0, 0x20f1, 0x20f2, 0x20f3, + 0x20f4, 0x20f5, 0x20f6, 0x20f7, 0x20f8, 0x20f9, 0x20fa, 0x20fb, + 0x20fc, 0x20fd, 0x20fe, 0x20ff, 0x2100, 0x2101, 0x2102, 0x2103, + 0x2104, 0x2105, 0x2106, 0x2107, 0x2108, 0x2109, 0x210a, 0x210b, + 0x210c, 0x210d, 0x210e, 0x210f, 0x2110, 0x2111, 0x2112, 0x2113, + 0x2114, 0x2115, 0x2116, 0x2117, 0x2118, 0x2119, 0x211a, 0x211b, + 0x211c, 0x211d, 0x211e, 0x211f, 0x2120, 0x2121, 0x2122, 0x2123, + 0x2124, 0x2125, 0x2126, 0x2127, 0x2128, 0x2129, 0x212a, 0x212b, + 0x212c, 0x212d, 0x212e, 0x212f, 0x2130, 0x2131, 0x2132, 0x2133, + 0x2134, 0x2135, 0x2136, 0x2137, 0x2138, 0x2139, 0x213a, 0x213b, + 0x213c, 0x213d, 0x213e, 0x213f, 0x2140, 0x2141, 0x2142, 0x2143, + 0x2144, 0x2145, 0x2146, 0x2147, 0x2148, 0x2149, 0x214a, 0x214b, + 0x214c, 0x214d, 0x2132, 0x214f, 0x2150, 0x2151, 0x2152, 0x2153, + 0x2154, 0x2155, 0x2156, 0x2157, 0x2158, 0x2159, 0x215a, 0x215b, + 0x215c, 0x215d, 0x215e, 0x215f, 0x2160, 0x2161, 0x2162, 0x2163, + 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0x216a, 0x216b, + 0x216c, 0x216d, 0x216e, 0x216f, 0x2160, 0x2161, 0x2162, 0x2163, + 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0x216a, 0x216b, + 0x216c, 0x216d, 0x216e, 0x216f, 0x2180, 0x2181, 0x2182, 0x2183, + 0x2183, 0xffff, 0x034b, 0x24b6, 0x24b7, 0x24b8, 0x24b9, 0x24ba, + 0x24bb, 0x24bc, 0x24bd, 0x24be, 0x24bf, 0x24c0, 0x24c1, 0x24c2, + 0x24c3, 0x24c4, 0x24c5, 0x24c6, 0x24c7, 0x24c8, 0x24c9, 0x24ca, + 0x24cb, 0x24cc, 0x24cd, 0x24ce, 0x24cf, 0xffff, 0x0746, 0x2c00, + 0x2c01, 0x2c02, 0x2c03, 0x2c04, 0x2c05, 0x2c06, 0x2c07, 0x2c08, + 0x2c09, 0x2c0a, 0x2c0b, 0x2c0c, 0x2c0d, 0x2c0e, 0x2c0f, 0x2c10, + 0x2c11, 0x2c12, 0x2c13, 0x2c14, 0x2c15, 0x2c16, 0x2c17, 0x2c18, + 0x2c19, 0x2c1a, 0x2c1b, 0x2c1c, 0x2c1d, 0x2c1e, 0x2c1f, 0x2c20, + 0x2c21, 0x2c22, 0x2c23, 0x2c24, 0x2c25, 0x2c26, 0x2c27, 0x2c28, + 0x2c29, 0x2c2a, 0x2c2b, 0x2c2c, 0x2c2d, 0x2c2e, 0x2c5f, 0x2c60, + 0x2c60, 0x2c62, 0x2c63, 0x2c64, 0x2c65, 0x2c66, 0x2c67, 0x2c67, + 0x2c69, 0x2c69, 0x2c6b, 0x2c6b, 0x2c6d, 0x2c6e, 0x2c6f, 0x2c70, + 0x2c71, 0x2c72, 0x2c73, 0x2c74, 0x2c75, 0x2c75, 0x2c77, 0x2c78, + 0x2c79, 0x2c7a, 0x2c7b, 0x2c7c, 0x2c7d, 0x2c7e, 0x2c7f, 0x2c80, + 0x2c80, 0x2c82, 0x2c82, 0x2c84, 0x2c84, 0x2c86, 0x2c86, 0x2c88, + 0x2c88, 0x2c8a, 0x2c8a, 0x2c8c, 0x2c8c, 0x2c8e, 0x2c8e, 0x2c90, + 0x2c90, 0x2c92, 0x2c92, 0x2c94, 0x2c94, 0x2c96, 0x2c96, 0x2c98, + 0x2c98, 0x2c9a, 0x2c9a, 0x2c9c, 0x2c9c, 0x2c9e, 0x2c9e, 0x2ca0, + 0x2ca0, 0x2ca2, 0x2ca2, 0x2ca4, 0x2ca4, 0x2ca6, 0x2ca6, 0x2ca8, + 0x2ca8, 0x2caa, 0x2caa, 0x2cac, 0x2cac, 0x2cae, 0x2cae, 0x2cb0, + 0x2cb0, 0x2cb2, 0x2cb2, 0x2cb4, 0x2cb4, 0x2cb6, 0x2cb6, 0x2cb8, + 0x2cb8, 0x2cba, 0x2cba, 0x2cbc, 0x2cbc, 0x2cbe, 0x2cbe, 0x2cc0, + 0x2cc0, 0x2cc2, 0x2cc2, 0x2cc4, 0x2cc4, 0x2cc6, 0x2cc6, 0x2cc8, + 0x2cc8, 0x2cca, 0x2cca, 0x2ccc, 0x2ccc, 0x2cce, 0x2cce, 0x2cd0, + 0x2cd0, 0x2cd2, 0x2cd2, 0x2cd4, 0x2cd4, 0x2cd6, 0x2cd6, 0x2cd8, + 0x2cd8, 0x2cda, 0x2cda, 0x2cdc, 0x2cdc, 0x2cde, 0x2cde, 0x2ce0, + 0x2ce0, 0x2ce2, 0x2ce2, 0x2ce4, 0x2ce5, 0x2ce6, 0x2ce7, 0x2ce8, + 0x2ce9, 0x2cea, 0x2ceb, 0x2cec, 0x2ced, 0x2cee, 0x2cef, 0x2cf0, + 0x2cf1, 0x2cf2, 0x2cf3, 0x2cf4, 0x2cf5, 0x2cf6, 0x2cf7, 0x2cf8, + 0x2cf9, 0x2cfa, 0x2cfb, 0x2cfc, 0x2cfd, 0x2cfe, 0x2cff, 0x10a0, + 0x10a1, 0x10a2, 0x10a3, 0x10a4, 0x10a5, 0x10a6, 0x10a7, 0x10a8, + 0x10a9, 0x10aa, 0x10ab, 0x10ac, 0x10ad, 0x10ae, 0x10af, 0x10b0, + 0x10b1, 0x10b2, 0x10b3, 0x10b4, 0x10b5, 0x10b6, 0x10b7, 0x10b8, + 0x10b9, 0x10ba, 0x10bb, 0x10bc, 0x10bd, 0x10be, 0x10bf, 0x10c0, + 0x10c1, 0x10c2, 0x10c3, 0x10c4, 0x10c5, 0xffff, 0xd21b, 0xff21, + 0xff22, 0xff23, 0xff24, 0xff25, 0xff26, 0xff27, 0xff28, 0xff29, + 0xff2a, 0xff2b, 0xff2c, 0xff2d, 0xff2e, 0xff2f, 0xff30, 0xff31, + 0xff32, 0xff33, 0xff34, 0xff35, 0xff36, 0xff37, 0xff38, 0xff39, + 0xff3a, 0xff5b, 0xff5c, 0xff5d, 0xff5e, 0xff5f, 0xff60, 0xff61, + 0xff62, 0xff63, 0xff64, 0xff65, 0xff66, 0xff67, 0xff68, 0xff69, + 0xff6a, 0xff6b, 0xff6c, 0xff6d, 0xff6e, 0xff6f, 0xff70, 0xff71, + 0xff72, 0xff73, 0xff74, 0xff75, 0xff76, 0xff77, 0xff78, 0xff79, + 0xff7a, 0xff7b, 0xff7c, 0xff7d, 0xff7e, 0xff7f, 0xff80, 0xff81, + 0xff82, 0xff83, 0xff84, 0xff85, 0xff86, 0xff87, 0xff88, 0xff89, + 0xff8a, 0xff8b, 0xff8c, 0xff8d, 0xff8e, 0xff8f, 0xff90, 0xff91, + 0xff92, 0xff93, 0xff94, 0xff95, 0xff96, 0xff97, 0xff98, 0xff99, + 0xff9a, 0xff9b, 0xff9c, 0xff9d, 0xff9e, 0xff9f, 0xffa0, 0xffa1, + 0xffa2, 0xffa3, 0xffa4, 0xffa5, 0xffa6, 0xffa7, 0xffa8, 0xffa9, + 0xffaa, 0xffab, 0xffac, 0xffad, 0xffae, 0xffaf, 0xffb0, 0xffb1, + 0xffb2, 0xffb3, 0xffb4, 0xffb5, 0xffb6, 0xffb7, 0xffb8, 0xffb9, + 0xffba, 0xffbb, 0xffbc, 0xffbd, 0xffbe, 0xffbf, 0xffc0, 0xffc1, + 0xffc2, 0xffc3, 0xffc4, 0xffc5, 0xffc6, 0xffc7, 0xffc8, 0xffc9, + 0xffca, 0xffcb, 0xffcc, 0xffcd, 0xffce, 0xffcf, 0xffd0, 0xffd1, + 0xffd2, 0xffd3, 0xffd4, 0xffd5, 0xffd6, 0xffd7, 0xffd8, 0xffd9, + 0xffda, 0xffdb, 0xffdc, 0xffdd, 0xffde, 0xffdf, 0xffe0, 0xffe1, + 0xffe2, 0xffe3, 0xffe4, 0xffe5, 0xffe6, 0xffe7, 0xffe8, 0xffe9, + 0xffea, 0xffeb, 0xffec, 0xffed, 0xffee, 0xffef, 0xfff0, 0xfff1, + 0xfff2, 0xfff3, 0xfff4, 0xfff5, 0xfff6, 0xfff7, 0xfff8, 0xfff9, + 0xfffa, 0xfffb, 0xfffc, 0xfffd, 0xfffe, 0xffff, +}; + +/* + * Allow full-width illegal characters : + * "MS windows 7" supports full-width-invalid-name-characters. + * So we should check half-width-invalid-name-characters(ASCII) only + * for compatibility. + * + * " * / : < > ? \ | + */ +static unsigned short bad_uni_chars[] = { + 0x0022, 0x002A, 0x002F, 0x003A, + 0x003C, 0x003E, 0x003F, 0x005C, 0x007C, + 0 +}; + +static int exfat_convert_char_to_ucs2(struct nls_table *nls, + const unsigned char *ch, int ch_len, unsigned short *ucs2, + int *lossy) +{ + int len; + + *ucs2 = 0x0; + + if (ch[0] < 0x80) { + *ucs2 = ch[0]; + return 1; + } + + len = nls->char2uni(ch, ch_len, ucs2); + if (len < 0) { + /* conversion failed */ + if (lossy != NULL) + *lossy |= NLS_NAME_LOSSY; + *ucs2 = '_'; + return 1; + } + return len; +} + +static int exfat_convert_ucs2_to_char(struct nls_table *nls, + unsigned short ucs2, unsigned char *ch, int *lossy) +{ + int len; + + ch[0] = 0x0; + + if (ucs2 < 0x0080) { + ch[0] = ucs2; + return 1; + } + + len = nls->uni2char(ucs2, ch, MAX_CHARSET_SIZE); + if (len < 0) { + /* conversion failed */ + if (lossy != NULL) + *lossy |= NLS_NAME_LOSSY; + ch[0] = '_'; + return 1; + } + return len; +} + +unsigned short exfat_toupper(struct super_block *sb, unsigned short a) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + + return sbi->vol_utbl[a] ? sbi->vol_utbl[a] : a; +} + +static unsigned short *exfat_wstrchr(unsigned short *str, unsigned short wchar) +{ + while (*str) { + if (*(str++) == wchar) + return str; + } + return NULL; +} + +int exfat_uniname_ncmp(struct super_block *sb, unsigned short *a, + unsigned short *b, unsigned int len) +{ + int i; + + for (i = 0; i < len; i++, a++, b++) + if (exfat_toupper(sb, *a) != exfat_toupper(sb, *b)) + return 1; + return 0; +} + +static int exfat_utf16_to_utf8(struct super_block *sb, + struct exfat_uni_name *p_uniname, unsigned char *p_cstring, + int buflen) +{ + int len; + const unsigned short *uniname = p_uniname->name; + + /* always len >= 0 */ + len = utf16s_to_utf8s(uniname, MAX_NAME_LENGTH, UTF16_HOST_ENDIAN, + p_cstring, buflen); + p_cstring[len] = '\0'; + return len; +} + +static int exfat_utf8_to_utf16(struct super_block *sb, + const unsigned char *p_cstring, const int len, + struct exfat_uni_name *p_uniname, int *p_lossy) +{ + int i, unilen, lossy = NLS_NAME_NO_LOSSY; + unsigned short upname[MAX_NAME_LENGTH + 1]; + unsigned short *uniname = p_uniname->name; + + WARN_ON(!len); + + unilen = utf8s_to_utf16s(p_cstring, len, UTF16_HOST_ENDIAN, + (wchar_t *)uniname, MAX_NAME_LENGTH + 2); + if (unilen < 0) { + exfat_msg(sb, KERN_ERR, + "failed to %s (err : %d) nls len : %d", + __func__, unilen, len); + return unilen; + } + + if (unilen > MAX_NAME_LENGTH) { + exfat_msg(sb, KERN_ERR, + "failed to %s (estr:ENAMETOOLONG) nls len : %d, unilen : %d > %d", + __func__, len, unilen, MAX_NAME_LENGTH); + return -ENAMETOOLONG; + } + + p_uniname->name_len = unilen & 0xFF; + + for (i = 0; i < unilen; i++) { + if (*uniname < 0x0020 || + exfat_wstrchr(bad_uni_chars, *uniname)) + lossy |= NLS_NAME_LOSSY; + + upname[i] = exfat_toupper(sb, *uniname); + uniname++; + } + + *uniname = '\0'; + p_uniname->name_len = unilen; + p_uniname->name_hash = exfat_calc_chksum_2byte(upname, unilen << 1, 0, + CS_DEFAULT); + + if (p_lossy) + *p_lossy = lossy; + return unilen; +} + +#define PLANE_SIZE 0x00010000 +#define SURROGATE_MASK 0xfffff800 +#define SURROGATE_PAIR 0x0000d800 +#define SURROGATE_LOW 0x00000400 +#define SURROGATE_BITS 0x000003ff + +unsigned short exfat_high_surrogate(unicode_t u) +{ + return ((u - PLANE_SIZE) >> 10) + SURROGATE_PAIR; +} + +unsigned short exfat_low_surrogate(unicode_t u) +{ + return ((u - PLANE_SIZE) & SURROGATE_BITS) | SURROGATE_PAIR | + SURROGATE_LOW; +} + +static int __exfat_utf16_to_nls(struct super_block *sb, + struct exfat_uni_name *p_uniname, unsigned char *p_cstring, + int buflen) +{ + int i, j, len, out_len = 0; + unsigned char buf[MAX_CHARSET_SIZE]; + const unsigned short *uniname = p_uniname->name; + struct nls_table *nls = EXFAT_SB(sb)->nls_io; + + i = 0; + while (i < MAX_NAME_LENGTH && out_len < (buflen - 1)) { + if (*uniname == '\0') + break; + if ((*uniname & SURROGATE_MASK) != SURROGATE_PAIR) { + len = exfat_convert_ucs2_to_char(nls, *uniname, buf, + NULL); + } else { + /* Process UTF-16 surrogate pair as one character */ + if (!(*uniname & SURROGATE_LOW) && + i+1 < MAX_NAME_LENGTH && + (*(uniname+1) & SURROGATE_MASK) == SURROGATE_PAIR && + (*(uniname+1) & SURROGATE_LOW)) { + uniname++; + i++; + } + + /* + * UTF-16 surrogate pair encodes code points above + * U+FFFF. Code points above U+FFFF are not supported + * by kernel NLS framework therefore use replacement + * character + */ + len = 1; + buf[0] = '_'; + } + + if (out_len + len >= buflen) + len = buflen - 1 - out_len; + out_len += len; + + if (len > 1) { + for (j = 0; j < len; j++) + *p_cstring++ = buf[j]; + } else { /* len == 1 */ + *p_cstring++ = *buf; + } + + uniname++; + i++; + } + + *p_cstring = '\0'; + return out_len; +} + +static int exfat_nls_to_ucs2(struct super_block *sb, + const unsigned char *p_cstring, const int len, + struct exfat_uni_name *p_uniname, int *p_lossy) +{ + int i = 0, unilen = 0, lossy = NLS_NAME_NO_LOSSY; + unsigned short upname[MAX_NAME_LENGTH + 1]; + unsigned short *uniname = p_uniname->name; + struct nls_table *nls = EXFAT_SB(sb)->nls_io; + + WARN_ON(!len); + + while (unilen < MAX_NAME_LENGTH && i < len) { + i += exfat_convert_char_to_ucs2(nls, p_cstring + i, len - i, + uniname, &lossy); + + if (*uniname < 0x0020 || + exfat_wstrchr(bad_uni_chars, *uniname)) + lossy |= NLS_NAME_LOSSY; + + upname[unilen] = exfat_toupper(sb, *uniname); + uniname++; + unilen++; + } + + if (p_cstring[i] != '\0') + lossy |= NLS_NAME_OVERLEN; + + *uniname = '\0'; + p_uniname->name_len = unilen; + p_uniname->name_hash = exfat_calc_chksum_2byte(upname, unilen << 1, 0, + CS_DEFAULT); + + if (p_lossy) + *p_lossy = lossy; + return unilen; +} + +int exfat_utf16_to_nls(struct super_block *sb, struct exfat_uni_name *uniname, + unsigned char *p_cstring, int buflen) +{ + if (EXFAT_SB(sb)->options.utf8) + return exfat_utf16_to_utf8(sb, uniname, p_cstring, + buflen); + return __exfat_utf16_to_nls(sb, uniname, p_cstring, buflen); +} + +int exfat_nls_to_utf16(struct super_block *sb, const unsigned char *p_cstring, + const int len, struct exfat_uni_name *uniname, int *p_lossy) +{ + if (EXFAT_SB(sb)->options.utf8) + return exfat_utf8_to_utf16(sb, p_cstring, len, + uniname, p_lossy); + return exfat_nls_to_ucs2(sb, p_cstring, len, uniname, p_lossy); +} + +static int exfat_load_upcase_table(struct super_block *sb, + sector_t sector, unsigned long long num_sectors, + unsigned int utbl_checksum) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + unsigned int sect_size = sb->s_blocksize; + unsigned int i, index = 0, checksum = 0; + int ret; + unsigned char skip = false; + unsigned short *upcase_table; + + upcase_table = kcalloc(UTBL_COUNT, sizeof(unsigned short), GFP_KERNEL); + if (!upcase_table) + return -ENOMEM; + + sbi->vol_utbl = upcase_table; + num_sectors += sector; + + while (sector < num_sectors) { + struct buffer_head *bh; + + bh = sb_bread(sb, sector); + if (!bh) { + exfat_msg(sb, KERN_ERR, + "failed to read sector(0x%llx)\n", + (unsigned long long)sector); + ret = -EIO; + goto free_table; + } + sector++; + for (i = 0; i < sect_size && index <= 0xFFFF; i += 2) { + unsigned short uni = get_unaligned_le16(bh->b_data + i); + + checksum = ((checksum & 1) ? 0x80000000 : 0) + + (checksum >> 1) + + *(((unsigned char *)bh->b_data) + i); + checksum = ((checksum & 1) ? 0x80000000 : 0) + + (checksum >> 1) + + *(((unsigned char *)bh->b_data) + (i + 1)); + + if (skip) { + index += uni; + skip = false; + } else if (uni == index) { + index++; + } else if (uni == 0xFFFF) { + skip = true; + } else { /* uni != index , uni != 0xFFFF */ + upcase_table[index] = uni; + index++; + } + } + brelse(bh); + } + + if (index >= 0xFFFF && utbl_checksum == checksum) + return 0; + + exfat_msg(sb, KERN_ERR, + "failed to load upcase table (idx : 0x%08x, chksum : 0x%08x, utbl_chksum : 0x%08x)\n", + index, checksum, utbl_checksum); + ret = -EINVAL; +free_table: + exfat_free_upcase_table(sbi); + return ret; +} + +static int exfat_load_default_upcase_table(struct super_block *sb) +{ + int i, ret = -EIO; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + unsigned char skip = false; + unsigned short uni = 0, *upcase_table; + unsigned int index = 0; + + upcase_table = kcalloc(UTBL_COUNT, sizeof(unsigned short), GFP_KERNEL); + if (!upcase_table) + return -ENOMEM; + + sbi->vol_utbl = upcase_table; + + for (i = 0; index <= 0xFFFF && i < EXFAT_NUM_UPCASE; i++) { + uni = uni_def_upcase[i]; + if (skip) { + index += uni; + skip = false; + } else if (uni == index) { + index++; + } else if (uni == 0xFFFF) { + skip = true; + } else { + upcase_table[index] = uni; + index++; + } + } + + if (index >= 0xFFFF) + return 0; + + /* FATAL error: default upcase table has error */ + exfat_free_upcase_table(sbi); + return ret; +} + +int exfat_create_upcase_table(struct super_block *sb) +{ + int i, ret; + unsigned int tbl_clu, type; + sector_t sector; + unsigned long long tbl_size, num_sectors; + unsigned char blksize_bits = sb->s_blocksize_bits; + struct exfat_chain clu; + struct exfat_dentry *ep; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct buffer_head *bh; + + clu.dir = sbi->root_dir; + clu.flags = ALLOC_FAT_CHAIN; + + while (clu.dir != EXFAT_EOF_CLUSTER) { + for (i = 0; i < sbi->dentries_per_clu; i++) { + ep = exfat_get_dentry(sb, &clu, i, &bh, NULL); + if (!ep) + return -EIO; + + type = exfat_get_entry_type(ep); + if (type == TYPE_UNUSED) { + brelse(bh); + break; + } + + if (type != TYPE_UPCASE) { + brelse(bh); + continue; + } + + tbl_clu = le32_to_cpu(ep->dentry.upcase.start_clu); + tbl_size = le64_to_cpu(ep->dentry.upcase.size); + + sector = exfat_cluster_to_sector(sbi, tbl_clu); + num_sectors = ((tbl_size - 1) >> blksize_bits) + 1; + ret = exfat_load_upcase_table(sb, sector, num_sectors, + le32_to_cpu(ep->dentry.upcase.checksum)); + + brelse(bh); + if (ret && ret != -EIO) + goto load_default; + + /* load successfully */ + return ret; + } + + if (exfat_get_next_cluster(sb, &(clu.dir))) + return -EIO; + } + +load_default: + /* load default upcase table */ + return exfat_load_default_upcase_table(sb); +} + +void exfat_free_upcase_table(struct exfat_sb_info *sbi) +{ + kfree(sbi->vol_utbl); +} From 78db3c6713c959c7ca037708baf91b9bd38271df Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Mon, 2 Mar 2020 15:21:42 +0900 Subject: [PATCH 044/592] exfat: add Kconfig and Makefile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds the Kconfig and Makefile for exfat. Signed-off-by: Namjae Jeon Signed-off-by: Sungjong Seo Reviewed-by: Pali Rohár Reviewed-by: Christoph Hellwig Signed-off-by: Al Viro Signed-off-by: Park Ju Hyung --- Kconfig | 21 +++++++++++++++++++++ Makefile | 8 ++++++++ 2 files changed, 29 insertions(+) create mode 100644 Kconfig create mode 100644 Makefile diff --git a/Kconfig b/Kconfig new file mode 100644 index 000000000000..2d3636dc5b8c --- /dev/null +++ b/Kconfig @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +config EXFAT_FS + tristate "exFAT filesystem support" + select NLS + help + This allows you to mount devices formatted with the exFAT file system. + exFAT is typically used on SD-Cards or USB sticks. + + To compile this as a module, choose M here: the module will be called + exfat. + +config EXFAT_DEFAULT_IOCHARSET + string "Default iocharset for exFAT" + default "utf8" + depends on EXFAT_FS + help + Set this to the default input/output character set to use for + converting between the encoding is used for user visible filename and + UTF-16 character that exfat filesystem use, and can be overridden with + the "iocharset" mount option for exFAT filesystems. diff --git a/Makefile b/Makefile new file mode 100644 index 000000000000..ed51926a4971 --- /dev/null +++ b/Makefile @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Makefile for the linux exFAT filesystem support. +# +obj-$(CONFIG_EXFAT_FS) += exfat.o + +exfat-y := inode.o namei.o dir.o super.o fatent.o cache.o nls.o misc.o \ + file.o balloc.o From 8f3343314fcfb40ae279bdec6ec8ce833ff9132e Mon Sep 17 00:00:00 2001 From: Valdis Kletnieks Date: Mon, 2 Mar 2020 15:21:45 +0900 Subject: [PATCH 045/592] exfat: update file system parameter handling Al Viro recently reworked the way file system parameters are handled Update super.c to work with it in linux-next 20200203. Signed-off-by: Valdis Kletnieks Reviewed-by: Christoph Hellwig Acked-by: Namjae Jeon Signed-off-by: Al Viro Signed-off-by: Park Ju Hyung --- super.c | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/super.c b/super.c index f06e0b53e393..16ed202ef527 100644 --- a/super.c +++ b/super.c @@ -214,7 +214,14 @@ enum { Opt_time_offset, }; -static const struct fs_parameter_spec exfat_param_specs[] = { +static const struct constant_table exfat_param_enums[] = { + { "continue", EXFAT_ERRORS_CONT }, + { "panic", EXFAT_ERRORS_PANIC }, + { "remount-ro", EXFAT_ERRORS_RO }, + {} +}; + +static const struct fs_parameter_spec exfat_parameters[] = { fsparam_u32("uid", Opt_uid), fsparam_u32("gid", Opt_gid), fsparam_u32oct("umask", Opt_umask), @@ -222,25 +229,12 @@ static const struct fs_parameter_spec exfat_param_specs[] = { fsparam_u32oct("fmask", Opt_fmask), fsparam_u32oct("allow_utime", Opt_allow_utime), fsparam_string("iocharset", Opt_charset), - fsparam_enum("errors", Opt_errors), + fsparam_enum("errors", Opt_errors, exfat_param_enums), fsparam_flag("discard", Opt_discard), fsparam_s32("time_offset", Opt_time_offset), {} }; -static const struct fs_parameter_enum exfat_param_enums[] = { - { Opt_errors, "continue", EXFAT_ERRORS_CONT }, - { Opt_errors, "panic", EXFAT_ERRORS_PANIC }, - { Opt_errors, "remount-ro", EXFAT_ERRORS_RO }, - {} -}; - -static const struct fs_parameter_description exfat_parameters = { - .name = "exfat", - .specs = exfat_param_specs, - .enums = exfat_param_enums, -}; - static int exfat_parse_param(struct fs_context *fc, struct fs_parameter *param) { struct exfat_sb_info *sbi = fc->s_fs_info; @@ -248,7 +242,7 @@ static int exfat_parse_param(struct fs_context *fc, struct fs_parameter *param) struct fs_parse_result result; int opt; - opt = fs_parse(fc, &exfat_parameters, param, &result); + opt = fs_parse(fc, exfat_parameters, param, &result); if (opt < 0) return opt; @@ -665,7 +659,7 @@ static struct file_system_type exfat_fs_type = { .owner = THIS_MODULE, .name = "exfat", .init_fs_context = exfat_init_fs_context, - .parameters = &exfat_parameters, + .parameters = exfat_parameters, .kill_sb = kill_block_super, .fs_flags = FS_REQUIRES_DEV, }; From 8ea1202136d8a320c58af731d489123ba82b4b98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Tue, 17 Mar 2020 22:46:52 +0100 Subject: [PATCH 046/592] exfat: Fix discard support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Discard support was always unconditionally disabled. Now it is disabled only in the case when blk_queue_discard() returns false. Signed-off-by: Pali Rohár Signed-off-by: Namjae Jeon Signed-off-by: Park Ju Hyung --- super.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/super.c b/super.c index 16ed202ef527..30e914ad17b5 100644 --- a/super.c +++ b/super.c @@ -531,10 +531,11 @@ static int exfat_fill_super(struct super_block *sb, struct fs_context *fc) if (opts->discard) { struct request_queue *q = bdev_get_queue(sb->s_bdev); - if (!blk_queue_discard(q)) + if (!blk_queue_discard(q)) { exfat_msg(sb, KERN_WARNING, "mounting with \"discard\" option, but the device does not support discard"); - opts->discard = 0; + opts->discard = 0; + } } sb->s_flags |= SB_NODIRATIME; From ddfc4330d95a7b2dcfb22655045c73a6fdd06e36 Mon Sep 17 00:00:00 2001 From: Thomas Backlund Date: Sat, 4 Apr 2020 23:29:43 +0300 Subject: [PATCH 047/592] exfat: add missing MODULE_ALIAS_FS() This adds the necessary MODULE_ALIAS_FS() to exfat so the module gets automatically loaded when an exfat filesystem is mounted. Signed-off-by: Thomas Backlund Signed-off-by: Namjae Jeon Signed-off-by: Park Ju Hyung --- super.c | 1 + 1 file changed, 1 insertion(+) diff --git a/super.c b/super.c index 30e914ad17b5..86c875606024 100644 --- a/super.c +++ b/super.c @@ -718,6 +718,7 @@ static void __exit exit_exfat_fs(void) module_init(init_exfat_fs); module_exit(exit_exfat_fs); +MODULE_ALIAS_FS("exfat"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("exFAT filesystem support"); MODULE_AUTHOR("Samsung Electronics Co., Ltd."); From a1b58dd8c74cb33dfdfc9914128f09262df96d1e Mon Sep 17 00:00:00 2001 From: Tetsuhiro Kohada Date: Tue, 21 Apr 2020 10:58:58 +0900 Subject: [PATCH 048/592] exfat: Unify access to the boot sector Unify access to boot sector via 'sbi->pbr_bh'. This fixes vol_flags inconsistency at read failed in fs_set_vol_flags(), and buffer_head leak in __exfat_fill_super(). Signed-off-by: Tetsuhiro Kohada Signed-off-by: Namjae Jeon Signed-off-by: Park Ju Hyung --- balloc.c | 3 --- super.c | 43 ++++++++++++++++--------------------------- 2 files changed, 16 insertions(+), 30 deletions(-) diff --git a/balloc.c b/balloc.c index 6a04cc02565a..6774a5a6ded8 100644 --- a/balloc.c +++ b/balloc.c @@ -91,7 +91,6 @@ static int exfat_allocate_bitmap(struct super_block *sb, } } - sbi->pbr_bh = NULL; return 0; } @@ -137,8 +136,6 @@ void exfat_free_bitmap(struct exfat_sb_info *sbi) { int i; - brelse(sbi->pbr_bh); - for (i = 0; i < sbi->map_sectors; i++) __brelse(sbi->vol_amap[i]); diff --git a/super.c b/super.c index 86c875606024..6b63e5092628 100644 --- a/super.c +++ b/super.c @@ -49,6 +49,7 @@ static void exfat_put_super(struct super_block *sb) sync_blockdev(sb->s_bdev); exfat_set_vol_flags(sb, VOL_CLEAN); exfat_free_bitmap(sbi); + brelse(sbi->pbr_bh); mutex_unlock(&sbi->s_lock); call_rcu(&sbi->rcu, exfat_delayed_free); @@ -100,7 +101,7 @@ static int exfat_statfs(struct dentry *dentry, struct kstatfs *buf) int exfat_set_vol_flags(struct super_block *sb, unsigned short new_flag) { struct exfat_sb_info *sbi = EXFAT_SB(sb); - struct pbr64 *bpb; + struct pbr64 *bpb = (struct pbr64 *)sbi->pbr_bh->b_data; bool sync = 0; /* flags are not changed */ @@ -115,15 +116,6 @@ int exfat_set_vol_flags(struct super_block *sb, unsigned short new_flag) if (sb_rdonly(sb)) return 0; - if (!sbi->pbr_bh) { - sbi->pbr_bh = sb_bread(sb, 0); - if (!sbi->pbr_bh) { - exfat_msg(sb, KERN_ERR, "failed to read boot sector"); - return -ENOMEM; - } - } - - bpb = (struct pbr64 *)sbi->pbr_bh->b_data; bpb->bsx.vol_flags = cpu_to_le16(new_flag); if (new_flag == VOL_DIRTY && !buffer_dirty(sbi->pbr_bh)) @@ -355,10 +347,10 @@ static int exfat_read_root(struct inode *inode) return 0; } -static struct pbr *exfat_read_pbr_with_logical_sector(struct super_block *sb, - struct buffer_head **prev_bh) +static struct pbr *exfat_read_pbr_with_logical_sector(struct super_block *sb) { - struct pbr *p_pbr = (struct pbr *) (*prev_bh)->b_data; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct pbr *p_pbr = (struct pbr *) (sbi->pbr_bh)->b_data; unsigned short logical_sect = 0; logical_sect = 1 << p_pbr->bsx.f64.sect_size_bits; @@ -378,26 +370,23 @@ static struct pbr *exfat_read_pbr_with_logical_sector(struct super_block *sb, } if (logical_sect > sb->s_blocksize) { - struct buffer_head *bh = NULL; - - __brelse(*prev_bh); - *prev_bh = NULL; + brelse(sbi->pbr_bh); + sbi->pbr_bh = NULL; if (!sb_set_blocksize(sb, logical_sect)) { exfat_msg(sb, KERN_ERR, "unable to set blocksize %u", logical_sect); return NULL; } - bh = sb_bread(sb, 0); - if (!bh) { + sbi->pbr_bh = sb_bread(sb, 0); + if (!sbi->pbr_bh) { exfat_msg(sb, KERN_ERR, "unable to read boot sector (logical sector size = %lu)", sb->s_blocksize); return NULL; } - *prev_bh = bh; - p_pbr = (struct pbr *) bh->b_data; + p_pbr = (struct pbr *)sbi->pbr_bh->b_data; } return p_pbr; } @@ -408,21 +397,20 @@ static int __exfat_fill_super(struct super_block *sb) int ret; struct pbr *p_pbr; struct pbr64 *p_bpb; - struct buffer_head *bh; struct exfat_sb_info *sbi = EXFAT_SB(sb); /* set block size to read super block */ sb_min_blocksize(sb, 512); /* read boot sector */ - bh = sb_bread(sb, 0); - if (!bh) { + sbi->pbr_bh = sb_bread(sb, 0); + if (!sbi->pbr_bh) { exfat_msg(sb, KERN_ERR, "unable to read boot sector"); return -EIO; } /* PRB is read */ - p_pbr = (struct pbr *)bh->b_data; + p_pbr = (struct pbr *)sbi->pbr_bh->b_data; /* check the validity of PBR */ if (le16_to_cpu((p_pbr->signature)) != PBR_SIGNATURE) { @@ -433,7 +421,7 @@ static int __exfat_fill_super(struct super_block *sb) /* check logical sector size */ - p_pbr = exfat_read_pbr_with_logical_sector(sb, &bh); + p_pbr = exfat_read_pbr_with_logical_sector(sb); if (!p_pbr) { ret = -EIO; goto free_bh; @@ -514,7 +502,7 @@ free_alloc_bitmap: free_upcase_table: exfat_free_upcase_table(sbi); free_bh: - brelse(bh); + brelse(sbi->pbr_bh); return ret; } @@ -606,6 +594,7 @@ put_inode: free_table: exfat_free_upcase_table(sbi); exfat_free_bitmap(sbi); + brelse(sbi->pbr_bh); check_nls_io: unload_nls(sbi->nls_io); From dac30edf26360102cd1c513e13d70deb92038646 Mon Sep 17 00:00:00 2001 From: Tetsuhiro Kohada Date: Tue, 7 Apr 2020 17:34:10 +0900 Subject: [PATCH 049/592] exfat: remove 'bps' mount-option remount fails because exfat_show_options() returns unsupported option 'bps'. > # mount -o ro,remount > exfat: Unknown parameter 'bps' To fix the problem, just remove 'bps' option from exfat_show_options(). Signed-off-by: Tetsuhiro Kohada Signed-off-by: Namjae Jeon Signed-off-by: Park Ju Hyung --- super.c | 1 - 1 file changed, 1 deletion(-) diff --git a/super.c b/super.c index 6b63e5092628..cb5eac38102d 100644 --- a/super.c +++ b/super.c @@ -151,7 +151,6 @@ static int exfat_show_options(struct seq_file *m, struct dentry *root) seq_puts(m, ",iocharset=utf8"); else if (sbi->nls_io) seq_printf(m, ",iocharset=%s", sbi->nls_io->charset); - seq_printf(m, ",bps=%ld", sb->s_blocksize); if (opts->errors == EXFAT_ERRORS_CONT) seq_puts(m, ",errors=continue"); else if (opts->errors == EXFAT_ERRORS_PANIC) From ff39697fa1a9d561666354f3b57c46b16402f417 Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Fri, 17 Apr 2020 14:43:49 +0900 Subject: [PATCH 050/592] exfat: properly set s_time_gran The s_time_gran superblock field indicates the on-disk nanosecond granularity of timestamps, and for exfat that seems to be 10ms, so set s_time_gran to 10000000ns. Without this, in-memory timestamps change when they get re-read from disk. Signed-off-by: Eric Sandeen Signed-off-by: Namjae Jeon Signed-off-by: Park Ju Hyung --- super.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/super.c b/super.c index cb5eac38102d..ee42ecf59059 100644 --- a/super.c +++ b/super.c @@ -529,7 +529,7 @@ static int exfat_fill_super(struct super_block *sb, struct fs_context *fc) sb->s_magic = EXFAT_SUPER_MAGIC; sb->s_op = &exfat_sops; - sb->s_time_gran = 1; + sb->s_time_gran = 10 * NSEC_PER_MSEC; sb->s_time_min = EXFAT_MIN_TIMESTAMP_SECS; sb->s_time_max = EXFAT_MAX_TIMESTAMP_SECS; From 7777b49ea3a91a23a3906bac7cf5f520e349cb2d Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Tue, 21 Apr 2020 11:13:10 +0900 Subject: [PATCH 051/592] exfat: truncate atimes to 2s granularity The timestamp for access_time has double seconds granularity(There is no 10msIncrement field for access_time unlike create/modify_time). exfat's atimes are restricted to only 2s granularity so after we set an atime, round it down to the nearest 2s and set the sub-second component of the timestamp to 0. Signed-off-by: Eric Sandeen Signed-off-by: Namjae Jeon Signed-off-by: Park Ju Hyung --- exfat_fs.h | 1 + file.c | 2 ++ misc.c | 14 +++++++++++++- namei.c | 7 +++++++ super.c | 1 + 5 files changed, 24 insertions(+), 1 deletion(-) diff --git a/exfat_fs.h b/exfat_fs.h index 67d4e46fb810..d67fb8a6f770 100644 --- a/exfat_fs.h +++ b/exfat_fs.h @@ -507,6 +507,7 @@ void exfat_msg(struct super_block *sb, const char *lv, const char *fmt, ...) __printf(3, 4) __cold; void exfat_get_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts, u8 tz, __le16 time, __le16 date, u8 time_ms); +void exfat_truncate_atime(struct timespec64 *ts); void exfat_set_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts, u8 *tz, __le16 *time, __le16 *date, u8 *time_ms); unsigned short exfat_calc_chksum_2byte(void *data, int len, diff --git a/file.c b/file.c index 483f683757aa..4f76764165cf 100644 --- a/file.c +++ b/file.c @@ -273,6 +273,7 @@ int exfat_getattr(const struct path *path, struct kstat *stat, struct exfat_inode_info *ei = EXFAT_I(inode); generic_fillattr(inode, stat); + exfat_truncate_atime(&stat->atime); stat->result_mask |= STATX_BTIME; stat->btime.tv_sec = ei->i_crtime.tv_sec; stat->btime.tv_nsec = ei->i_crtime.tv_nsec; @@ -339,6 +340,7 @@ int exfat_setattr(struct dentry *dentry, struct iattr *attr) } setattr_copy(inode, attr); + exfat_truncate_atime(&inode->i_atime); mark_inode_dirty(inode); out: diff --git a/misc.c b/misc.c index 14a3300848f6..ebd2cbe3cbc1 100644 --- a/misc.c +++ b/misc.c @@ -88,7 +88,8 @@ void exfat_get_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts, if (time_ms) { ts->tv_sec += time_ms / 100; ts->tv_nsec = (time_ms % 100) * 10 * NSEC_PER_MSEC; - } + } else + ts->tv_nsec = 0; if (tz & EXFAT_TZ_VALID) /* Adjust timezone to UTC0. */ @@ -124,6 +125,17 @@ void exfat_set_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts, *tz = EXFAT_TZ_VALID; } +/* + * The timestamp for access_time has double seconds granularity. + * (There is no 10msIncrement field for access_time unlike create/modify_time) + * atime also has only a 2-second resolution. + */ +void exfat_truncate_atime(struct timespec64 *ts) +{ + ts->tv_sec = round_down(ts->tv_sec, 2); + ts->tv_nsec = 0; +} + unsigned short exfat_calc_chksum_2byte(void *data, int len, unsigned short chksum, int type) { diff --git a/namei.c b/namei.c index a8681d91f569..b72d782568b8 100644 --- a/namei.c +++ b/namei.c @@ -595,6 +595,7 @@ static int exfat_create(struct inode *dir, struct dentry *dentry, umode_t mode, inode_inc_iversion(inode); inode->i_mtime = inode->i_atime = inode->i_ctime = EXFAT_I(inode)->i_crtime = current_time(inode); + exfat_truncate_atime(&inode->i_atime); /* timestamp is already written, so mark_inode_dirty() is unneeded. */ d_instantiate(dentry, inode); @@ -854,6 +855,7 @@ static int exfat_unlink(struct inode *dir, struct dentry *dentry) inode_inc_iversion(dir); dir->i_mtime = dir->i_atime = current_time(dir); + exfat_truncate_atime(&dir->i_atime); if (IS_DIRSYNC(dir)) exfat_sync_inode(dir); else @@ -861,6 +863,7 @@ static int exfat_unlink(struct inode *dir, struct dentry *dentry) clear_nlink(inode); inode->i_mtime = inode->i_atime = current_time(inode); + exfat_truncate_atime(&inode->i_atime); exfat_unhash_inode(inode); exfat_d_version_set(dentry, inode_query_iversion(dir)); unlock: @@ -903,6 +906,7 @@ static int exfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) inode_inc_iversion(inode); inode->i_mtime = inode->i_atime = inode->i_ctime = EXFAT_I(inode)->i_crtime = current_time(inode); + exfat_truncate_atime(&inode->i_atime); /* timestamp is already written, so mark_inode_dirty() is unneeded. */ d_instantiate(dentry, inode); @@ -1019,6 +1023,7 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry) inode_inc_iversion(dir); dir->i_mtime = dir->i_atime = current_time(dir); + exfat_truncate_atime(&dir->i_atime); if (IS_DIRSYNC(dir)) exfat_sync_inode(dir); else @@ -1027,6 +1032,7 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry) clear_nlink(inode); inode->i_mtime = inode->i_atime = current_time(inode); + exfat_truncate_atime(&inode->i_atime); exfat_unhash_inode(inode); exfat_d_version_set(dentry, inode_query_iversion(dir)); unlock: @@ -1387,6 +1393,7 @@ static int exfat_rename(struct inode *old_dir, struct dentry *old_dentry, inode_inc_iversion(new_dir); new_dir->i_ctime = new_dir->i_mtime = new_dir->i_atime = EXFAT_I(new_dir)->i_crtime = current_time(new_dir); + exfat_truncate_atime(&new_dir->i_atime); if (IS_DIRSYNC(new_dir)) exfat_sync_inode(new_dir); else diff --git a/super.c b/super.c index ee42ecf59059..0565d5539d57 100644 --- a/super.c +++ b/super.c @@ -342,6 +342,7 @@ static int exfat_read_root(struct inode *inode) exfat_save_attr(inode, ATTR_SUBDIR); inode->i_mtime = inode->i_atime = inode->i_ctime = ei->i_crtime = current_time(inode); + exfat_truncate_atime(&inode->i_atime); exfat_cache_init_inode(inode); return 0; } From 28b6bfcd74f93e4e404b0921c4b5ec18e45ae5a0 Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Fri, 1 May 2020 20:34:25 -0500 Subject: [PATCH 052/592] exfat: use iter_file_splice_write Doing copy_file_range() on exfat with a file opened for direct IO leads to an -EFAULT: # xfs_io -f -d -c "truncate 32768" \ -c "copy_range -d 16384 -l 16384 -f 0" /mnt/test/junk copy_range: Bad address and the reason seems to be that we go through: default_file_splice_write splice_from_pipe __splice_from_pipe write_pipe_buf __kernel_write new_sync_write generic_file_write_iter generic_file_direct_write exfat_direct_IO do_blockdev_direct_IO iov_iter_get_pages and land in iterate_all_kinds(), which does "return -EFAULT" for our kvec iter. Setting exfat's splice_write to iter_file_splice_write fixes this and lets fsx (which originally detected the problem) run to success from the xfstests harness. Signed-off-by: Eric Sandeen Signed-off-by: Namjae Jeon Signed-off-by: Park Ju Hyung --- file.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/file.c b/file.c index 4f76764165cf..c9db8eb0cfc3 100644 --- a/file.c +++ b/file.c @@ -348,12 +348,13 @@ out: } const struct file_operations exfat_file_operations = { - .llseek = generic_file_llseek, - .read_iter = generic_file_read_iter, - .write_iter = generic_file_write_iter, - .mmap = generic_file_mmap, - .fsync = generic_file_fsync, - .splice_read = generic_file_splice_read, + .llseek = generic_file_llseek, + .read_iter = generic_file_read_iter, + .write_iter = generic_file_write_iter, + .mmap = generic_file_mmap, + .fsync = generic_file_fsync, + .splice_read = generic_file_splice_read, + .splice_write = iter_file_splice_write, }; const struct inode_operations exfat_file_inode_operations = { From 872477eda2e652ce1f2005bc876a2c19a7c3a239 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Wed, 6 May 2020 14:25:54 +0000 Subject: [PATCH 053/592] exfat: fix possible memory leak in exfat_find() 'es' is malloced from exfat_get_dentry_set() in exfat_find() and should be freed before leaving from the error handling cases, otherwise it will cause memory leak. Fixes: 5f2aa075070c ("exfat: add inode operations") Signed-off-by: Wei Yongjun Signed-off-by: Namjae Jeon Signed-off-by: Park Ju Hyung --- namei.c | 1 + 1 file changed, 1 insertion(+) diff --git a/namei.c b/namei.c index b72d782568b8..a2659a8a68a1 100644 --- a/namei.c +++ b/namei.c @@ -692,6 +692,7 @@ static int exfat_find(struct inode *dir, struct qstr *qname, exfat_fs_error(sb, "non-zero size file starts with zero cluster (size : %llu, p_dir : %u, entry : 0x%08x)", i_size_read(dir), ei->dir.dir, ei->entry); + kfree(es); return -EIO; } From 773486313345f8912ff5b2be4e67dd9e099bc5fa Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Fri, 22 May 2020 08:10:10 +0900 Subject: [PATCH 054/592] exfat: add the dummy mount options to be backward compatible with staging/exfat As Ubuntu and Fedora release new version used kernel version equal to or higher than v5.4, They started to support kernel exfat filesystem. Linus reported a mount error with new version of exfat on Fedora: exfat: Unknown parameter 'namecase' This is because there is a difference in mount option between old staging/exfat and new exfat. And utf8, debug, and codepage options as well as namecase have been removed from new exfat. This patch add the dummy mount options as deprecated option to be backward compatible with old one. Reported-by: Linus Torvalds Signed-off-by: Namjae Jeon Cc: Matthew Wilcox Cc: Al Viro Cc: Eric Sandeen Signed-off-by: Linus Torvalds Signed-off-by: Park Ju Hyung --- super.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/super.c b/super.c index 0565d5539d57..a846ff555656 100644 --- a/super.c +++ b/super.c @@ -203,6 +203,12 @@ enum { Opt_errors, Opt_discard, Opt_time_offset, + + /* Deprecated options */ + Opt_utf8, + Opt_debug, + Opt_namecase, + Opt_codepage, }; static const struct constant_table exfat_param_enums[] = { @@ -223,6 +229,14 @@ static const struct fs_parameter_spec exfat_parameters[] = { fsparam_enum("errors", Opt_errors, exfat_param_enums), fsparam_flag("discard", Opt_discard), fsparam_s32("time_offset", Opt_time_offset), + __fsparam(NULL, "utf8", Opt_utf8, fs_param_deprecated, + NULL), + __fsparam(NULL, "debug", Opt_debug, fs_param_deprecated, + NULL), + __fsparam(fs_param_is_u32, "namecase", Opt_namecase, + fs_param_deprecated, NULL), + __fsparam(fs_param_is_u32, "codepage", Opt_codepage, + fs_param_deprecated, NULL), {} }; @@ -278,6 +292,11 @@ static int exfat_parse_param(struct fs_context *fc, struct fs_parameter *param) return -EINVAL; opts->time_offset = result.int_32; break; + case Opt_utf8: + case Opt_debug: + case Opt_namecase: + case Opt_codepage: + break; default: return -EINVAL; } From 2e7aab60d7a11f6338858bfea297e2274fc1c28f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Tue, 17 Mar 2020 22:34:33 +0100 Subject: [PATCH 055/592] exfat: Simplify exfat_utf8_d_cmp() for code points above U+FFFF MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If two Unicode code points represented in UTF-16 are different then also their UTF-32 representation must be different. Therefore conversion from UTF-32 to UTF-16 is not needed. Signed-off-by: Pali Rohár Signed-off-by: Namjae Jeon Signed-off-by: Park Ju Hyung --- namei.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/namei.c b/namei.c index a2659a8a68a1..731da41cabbf 100644 --- a/namei.c +++ b/namei.c @@ -185,14 +185,9 @@ static int exfat_utf8_d_cmp(const struct dentry *dentry, unsigned int len, if (u_a <= 0xFFFF && u_b <= 0xFFFF) { if (exfat_toupper(sb, u_a) != exfat_toupper(sb, u_b)) return 1; - } else if (u_a > 0xFFFF && u_b > 0xFFFF) { - if (exfat_low_surrogate(u_a) != - exfat_low_surrogate(u_b) || - exfat_high_surrogate(u_a) != - exfat_high_surrogate(u_b)) - return 1; } else { - return 1; + if (u_a != u_b) + return 1; } } From 0c09b56d034b76113243a5ed0e17358740735ac8 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 24 Apr 2020 13:31:12 +0900 Subject: [PATCH 056/592] exfat: Use a more common logging style Remove the direct use of KERN_ in functions by creating separate exfat_ macros. Miscellanea: o Remove several unnecessary terminating newlines in formats o Realign arguments and fit to 80 columns where appropriate Signed-off-by: Joe Perches Signed-off-by: Namjae Jeon Signed-off-by: Park Ju Hyung --- balloc.c | 8 +++----- dir.c | 9 ++++----- exfat_fs.h | 7 +++++++ fatent.c | 13 +++++-------- misc.c | 4 ++-- namei.c | 26 ++++++++++---------------- nls.c | 20 ++++++++------------ super.c | 47 +++++++++++++++++++++-------------------------- 8 files changed, 60 insertions(+), 74 deletions(-) diff --git a/balloc.c b/balloc.c index 6774a5a6ded8..4055eb00ea9b 100644 --- a/balloc.c +++ b/balloc.c @@ -58,9 +58,8 @@ static int exfat_allocate_bitmap(struct super_block *sb, need_map_size = ((EXFAT_DATA_CLUSTER_COUNT(sbi) - 1) / BITS_PER_BYTE) + 1; if (need_map_size != map_size) { - exfat_msg(sb, KERN_ERR, - "bogus allocation bitmap size(need : %u, cur : %lld)", - need_map_size, map_size); + exfat_err(sb, "bogus allocation bitmap size(need : %u, cur : %lld)", + need_map_size, map_size); /* * Only allowed when bogus allocation * bitmap size is large @@ -192,8 +191,7 @@ void exfat_clear_bitmap(struct inode *inode, unsigned int clu) (1 << sbi->sect_per_clus_bits), GFP_NOFS, 0); if (ret_discard == -EOPNOTSUPP) { - exfat_msg(sb, KERN_ERR, - "discard not supported by device, disabling"); + exfat_err(sb, "discard not supported by device, disabling"); opts->discard = 0; } } diff --git a/dir.c b/dir.c index 4b91afb0f051..53ae965da7ec 100644 --- a/dir.c +++ b/dir.c @@ -720,9 +720,8 @@ static int exfat_dir_readahead(struct super_block *sb, sector_t sec) return 0; if (sec < sbi->data_start_sector) { - exfat_msg(sb, KERN_ERR, - "requested sector is invalid(sect:%llu, root:%llu)", - (unsigned long long)sec, sbi->data_start_sector); + exfat_err(sb, "requested sector is invalid(sect:%llu, root:%llu)", + (unsigned long long)sec, sbi->data_start_sector); return -EIO; } @@ -750,7 +749,7 @@ struct exfat_dentry *exfat_get_dentry(struct super_block *sb, sector_t sec; if (p_dir->dir == DIR_DELETED) { - exfat_msg(sb, KERN_ERR, "abnormal access to deleted dentry\n"); + exfat_err(sb, "abnormal access to deleted dentry"); return NULL; } @@ -853,7 +852,7 @@ struct exfat_entry_set_cache *exfat_get_dentry_set(struct super_block *sb, struct buffer_head *bh; if (p_dir->dir == DIR_DELETED) { - exfat_msg(sb, KERN_ERR, "access to deleted dentry\n"); + exfat_err(sb, "access to deleted dentry"); return NULL; } diff --git a/exfat_fs.h b/exfat_fs.h index d67fb8a6f770..1ebfb9085f1f 100644 --- a/exfat_fs.h +++ b/exfat_fs.h @@ -505,6 +505,13 @@ void __exfat_fs_error(struct super_block *sb, int report, const char *fmt, ...) fmt, ## args) void exfat_msg(struct super_block *sb, const char *lv, const char *fmt, ...) __printf(3, 4) __cold; +#define exfat_err(sb, fmt, ...) \ + exfat_msg(sb, KERN_ERR, fmt, ##__VA_ARGS__) +#define exfat_warn(sb, fmt, ...) \ + exfat_msg(sb, KERN_WARNING, fmt, ##__VA_ARGS__) +#define exfat_info(sb, fmt, ...) \ + exfat_msg(sb, KERN_INFO, fmt, ##__VA_ARGS__) + void exfat_get_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts, u8 tz, __le16 time, __le16 date, u8 time_ms); void exfat_truncate_atime(struct timespec64 *ts); diff --git a/fatent.c b/fatent.c index a855b1769a96..267e5e09eb13 100644 --- a/fatent.c +++ b/fatent.c @@ -170,8 +170,7 @@ int exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain) /* check cluster validation */ if (p_chain->dir < 2 && p_chain->dir >= sbi->num_clusters) { - exfat_msg(sb, KERN_ERR, "invalid start cluster (%u)", - p_chain->dir); + exfat_err(sb, "invalid start cluster (%u)", p_chain->dir); return -EIO; } @@ -305,8 +304,7 @@ int exfat_zeroed_cluster(struct inode *dir, unsigned int clu) return 0; release_bhs: - exfat_msg(sb, KERN_ERR, "failed zeroed sect %llu\n", - (unsigned long long)blknr); + exfat_err(sb, "failed zeroed sect %llu\n", (unsigned long long)blknr); for (i = 0; i < n; i++) bforget(bhs[i]); return err; @@ -337,9 +335,8 @@ int exfat_alloc_cluster(struct inode *inode, unsigned int num_alloc, /* find new cluster */ if (hint_clu == EXFAT_EOF_CLUSTER) { if (sbi->clu_srch_ptr < EXFAT_FIRST_CLUSTER) { - exfat_msg(sb, KERN_ERR, - "sbi->clu_srch_ptr is invalid (%u)\n", - sbi->clu_srch_ptr); + exfat_err(sb, "sbi->clu_srch_ptr is invalid (%u)\n", + sbi->clu_srch_ptr); sbi->clu_srch_ptr = EXFAT_FIRST_CLUSTER; } @@ -350,7 +347,7 @@ int exfat_alloc_cluster(struct inode *inode, unsigned int num_alloc, /* check cluster validation */ if (hint_clu < EXFAT_FIRST_CLUSTER && hint_clu >= sbi->num_clusters) { - exfat_msg(sb, KERN_ERR, "hint_cluster is invalid (%u)\n", + exfat_err(sb, "hint_cluster is invalid (%u)", hint_clu); hint_clu = EXFAT_FIRST_CLUSTER; if (p_chain->flags == ALLOC_NO_FAT_CHAIN) { diff --git a/misc.c b/misc.c index ebd2cbe3cbc1..ce5e8a1b0726 100644 --- a/misc.c +++ b/misc.c @@ -32,7 +32,7 @@ void __exfat_fs_error(struct super_block *sb, int report, const char *fmt, ...) va_start(args, fmt); vaf.fmt = fmt; vaf.va = &args; - exfat_msg(sb, KERN_ERR, "error, %pV\n", &vaf); + exfat_err(sb, "error, %pV", &vaf); va_end(args); } @@ -41,7 +41,7 @@ void __exfat_fs_error(struct super_block *sb, int report, const char *fmt, ...) sb->s_id); } else if (opts->errors == EXFAT_ERRORS_RO && !sb_rdonly(sb)) { sb->s_flags |= SB_RDONLY; - exfat_msg(sb, KERN_ERR, "Filesystem has been set read-only"); + exfat_err(sb, "Filesystem has been set read-only"); } } diff --git a/namei.c b/namei.c index 731da41cabbf..585b47b2db3d 100644 --- a/namei.c +++ b/namei.c @@ -773,8 +773,8 @@ static struct dentry *exfat_lookup(struct inode *dir, struct dentry *dentry, if (d_unhashed(alias)) { WARN_ON(alias->d_name.hash_len != dentry->d_name.hash_len); - exfat_msg(sb, KERN_INFO, - "rehashed a dentry(%p) in read lookup", alias); + exfat_info(sb, "rehashed a dentry(%p) in read lookup", + alias); d_drop(dentry); d_rehash(alias); } else if (!S_ISDIR(i_mode)) { @@ -819,7 +819,7 @@ static int exfat_unlink(struct inode *dir, struct dentry *dentry) exfat_chain_dup(&cdir, &ei->dir); entry = ei->entry; if (ei->dir.dir == DIR_DELETED) { - exfat_msg(sb, KERN_ERR, "abnormal access to deleted dentry"); + exfat_err(sb, "abnormal access to deleted dentry"); err = -ENOENT; goto unlock; } @@ -974,7 +974,7 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry) entry = ei->entry; if (ei->dir.dir == DIR_DELETED) { - exfat_msg(sb, KERN_ERR, "abnormal access to deleted dentry"); + exfat_err(sb, "abnormal access to deleted dentry"); err = -ENOENT; goto unlock; } @@ -986,9 +986,8 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry) err = exfat_check_dir_empty(sb, &clu_to_free); if (err) { if (err == -EIO) - exfat_msg(sb, KERN_ERR, - "failed to exfat_check_dir_empty : err(%d)", - err); + exfat_err(sb, "failed to exfat_check_dir_empty : err(%d)", + err); goto unlock; } @@ -1009,9 +1008,7 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry) err = exfat_remove_entries(dir, &cdir, entry, 0, num_entries); if (err) { - exfat_msg(sb, KERN_ERR, - "failed to exfat_remove_entries : err(%d)", - err); + exfat_err(sb, "failed to exfat_remove_entries : err(%d)", err); goto unlock; } ei->dir.dir = DIR_DELETED; @@ -1240,8 +1237,7 @@ static int __exfat_rename(struct inode *old_parent_inode, return -EINVAL; if (ei->dir.dir == DIR_DELETED) { - exfat_msg(sb, KERN_ERR, - "abnormal access to deleted source dentry"); + exfat_err(sb, "abnormal access to deleted source dentry"); return -ENOENT; } @@ -1263,8 +1259,7 @@ static int __exfat_rename(struct inode *old_parent_inode, new_ei = EXFAT_I(new_inode); if (new_ei->dir.dir == DIR_DELETED) { - exfat_msg(sb, KERN_ERR, - "abnormal access to deleted target dentry"); + exfat_err(sb, "abnormal access to deleted target dentry"); goto out; } @@ -1426,8 +1421,7 @@ static int exfat_rename(struct inode *old_dir, struct dentry *old_dentry, if (S_ISDIR(new_inode->i_mode)) drop_nlink(new_inode); } else { - exfat_msg(sb, KERN_WARNING, - "abnormal access to an inode dropped"); + exfat_warn(sb, "abnormal access to an inode dropped"); WARN_ON(new_inode->i_nlink == 0); } new_inode->i_ctime = EXFAT_I(new_inode)->i_crtime = diff --git a/nls.c b/nls.c index 6d1c3ae130ff..2178786b708b 100644 --- a/nls.c +++ b/nls.c @@ -503,16 +503,14 @@ static int exfat_utf8_to_utf16(struct super_block *sb, unilen = utf8s_to_utf16s(p_cstring, len, UTF16_HOST_ENDIAN, (wchar_t *)uniname, MAX_NAME_LENGTH + 2); if (unilen < 0) { - exfat_msg(sb, KERN_ERR, - "failed to %s (err : %d) nls len : %d", - __func__, unilen, len); + exfat_err(sb, "failed to %s (err : %d) nls len : %d", + __func__, unilen, len); return unilen; } if (unilen > MAX_NAME_LENGTH) { - exfat_msg(sb, KERN_ERR, - "failed to %s (estr:ENAMETOOLONG) nls len : %d, unilen : %d > %d", - __func__, len, unilen, MAX_NAME_LENGTH); + exfat_err(sb, "failed to %s (estr:ENAMETOOLONG) nls len : %d, unilen : %d > %d", + __func__, len, unilen, MAX_NAME_LENGTH); return -ENAMETOOLONG; } @@ -687,9 +685,8 @@ static int exfat_load_upcase_table(struct super_block *sb, bh = sb_bread(sb, sector); if (!bh) { - exfat_msg(sb, KERN_ERR, - "failed to read sector(0x%llx)\n", - (unsigned long long)sector); + exfat_err(sb, "failed to read sector(0x%llx)\n", + (unsigned long long)sector); ret = -EIO; goto free_table; } @@ -722,9 +719,8 @@ static int exfat_load_upcase_table(struct super_block *sb, if (index >= 0xFFFF && utbl_checksum == checksum) return 0; - exfat_msg(sb, KERN_ERR, - "failed to load upcase table (idx : 0x%08x, chksum : 0x%08x, utbl_chksum : 0x%08x)\n", - index, checksum, utbl_checksum); + exfat_err(sb, "failed to load upcase table (idx : 0x%08x, chksum : 0x%08x, utbl_chksum : 0x%08x)", + index, checksum, utbl_checksum); ret = -EINVAL; free_table: exfat_free_upcase_table(sbi); diff --git a/super.c b/super.c index a846ff555656..f9aa1e5dc238 100644 --- a/super.c +++ b/super.c @@ -376,15 +376,13 @@ static struct pbr *exfat_read_pbr_with_logical_sector(struct super_block *sb) if (!is_power_of_2(logical_sect) || logical_sect < 512 || logical_sect > 4096) { - exfat_msg(sb, KERN_ERR, "bogus logical sector size %u", - logical_sect); + exfat_err(sb, "bogus logical sector size %u", logical_sect); return NULL; } if (logical_sect < sb->s_blocksize) { - exfat_msg(sb, KERN_ERR, - "logical sector size too small for device (logical sector size = %u)", - logical_sect); + exfat_err(sb, "logical sector size too small for device (logical sector size = %u)", + logical_sect); return NULL; } @@ -393,15 +391,14 @@ static struct pbr *exfat_read_pbr_with_logical_sector(struct super_block *sb) sbi->pbr_bh = NULL; if (!sb_set_blocksize(sb, logical_sect)) { - exfat_msg(sb, KERN_ERR, - "unable to set blocksize %u", logical_sect); + exfat_err(sb, "unable to set blocksize %u", + logical_sect); return NULL; } sbi->pbr_bh = sb_bread(sb, 0); if (!sbi->pbr_bh) { - exfat_msg(sb, KERN_ERR, - "unable to read boot sector (logical sector size = %lu)", - sb->s_blocksize); + exfat_err(sb, "unable to read boot sector (logical sector size = %lu)", + sb->s_blocksize); return NULL; } @@ -424,7 +421,7 @@ static int __exfat_fill_super(struct super_block *sb) /* read boot sector */ sbi->pbr_bh = sb_bread(sb, 0); if (!sbi->pbr_bh) { - exfat_msg(sb, KERN_ERR, "unable to read boot sector"); + exfat_err(sb, "unable to read boot sector"); return -EIO; } @@ -433,7 +430,7 @@ static int __exfat_fill_super(struct super_block *sb) /* check the validity of PBR */ if (le16_to_cpu((p_pbr->signature)) != PBR_SIGNATURE) { - exfat_msg(sb, KERN_ERR, "invalid boot record signature"); + exfat_err(sb, "invalid boot record signature"); ret = -EINVAL; goto free_bh; } @@ -458,7 +455,7 @@ static int __exfat_fill_super(struct super_block *sb) p_bpb = (struct pbr64 *)p_pbr; if (!p_bpb->bsx.num_fats) { - exfat_msg(sb, KERN_ERR, "bogus number of FAT structure"); + exfat_err(sb, "bogus number of FAT structure"); ret = -EINVAL; goto free_bh; } @@ -488,8 +485,7 @@ static int __exfat_fill_super(struct super_block *sb) if (le16_to_cpu(p_bpb->bsx.vol_flags) & VOL_DIRTY) { sbi->vol_flag |= VOL_DIRTY; - exfat_msg(sb, KERN_WARNING, - "Volume was not properly unmounted. Some data may be corrupt. Please run fsck."); + exfat_warn(sb, "Volume was not properly unmounted. Some data may be corrupt. Please run fsck."); } /* exFAT file size is limited by a disk volume size */ @@ -498,19 +494,19 @@ static int __exfat_fill_super(struct super_block *sb) ret = exfat_create_upcase_table(sb); if (ret) { - exfat_msg(sb, KERN_ERR, "failed to load upcase table"); + exfat_err(sb, "failed to load upcase table"); goto free_bh; } ret = exfat_load_bitmap(sb); if (ret) { - exfat_msg(sb, KERN_ERR, "failed to load alloc-bitmap"); + exfat_err(sb, "failed to load alloc-bitmap"); goto free_upcase_table; } ret = exfat_count_used_clusters(sb, &sbi->used_clusters); if (ret) { - exfat_msg(sb, KERN_ERR, "failed to scan clusters"); + exfat_err(sb, "failed to scan clusters"); goto free_alloc_bitmap; } @@ -539,8 +535,7 @@ static int exfat_fill_super(struct super_block *sb, struct fs_context *fc) struct request_queue *q = bdev_get_queue(sb->s_bdev); if (!blk_queue_discard(q)) { - exfat_msg(sb, KERN_WARNING, - "mounting with \"discard\" option, but the device does not support discard"); + exfat_warn(sb, "mounting with \"discard\" option, but the device does not support discard"); opts->discard = 0; } } @@ -555,7 +550,7 @@ static int exfat_fill_super(struct super_block *sb, struct fs_context *fc) err = __exfat_fill_super(sb); if (err) { - exfat_msg(sb, KERN_ERR, "failed to recognize exfat type"); + exfat_err(sb, "failed to recognize exfat type"); goto check_nls_io; } @@ -567,8 +562,8 @@ static int exfat_fill_super(struct super_block *sb, struct fs_context *fc) else { sbi->nls_io = load_nls(sbi->options.iocharset); if (!sbi->nls_io) { - exfat_msg(sb, KERN_ERR, "IO charset %s not found", - sbi->options.iocharset); + exfat_err(sb, "IO charset %s not found", + sbi->options.iocharset); err = -EINVAL; goto free_table; } @@ -581,7 +576,7 @@ static int exfat_fill_super(struct super_block *sb, struct fs_context *fc) root_inode = new_inode(sb); if (!root_inode) { - exfat_msg(sb, KERN_ERR, "failed to allocate root inode."); + exfat_err(sb, "failed to allocate root inode"); err = -ENOMEM; goto free_table; } @@ -590,7 +585,7 @@ static int exfat_fill_super(struct super_block *sb, struct fs_context *fc) inode_set_iversion(root_inode, 1); err = exfat_read_root(root_inode); if (err) { - exfat_msg(sb, KERN_ERR, "failed to initialize root inode."); + exfat_err(sb, "failed to initialize root inode"); goto put_inode; } @@ -599,7 +594,7 @@ static int exfat_fill_super(struct super_block *sb, struct fs_context *fc) sb->s_root = d_make_root(root_inode); if (!sb->s_root) { - exfat_msg(sb, KERN_ERR, "failed to get the root dentry"); + exfat_err(sb, "failed to get the root dentry"); err = -ENOMEM; goto put_inode; } From 13ba99d86c2509c27ed1de9f4ee56e8450ff9076 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 6 Apr 2020 11:13:43 +0200 Subject: [PATCH 057/592] exfat: Improve wording of EXFAT_DEFAULT_IOCHARSET config option - Use consistent capitalization for "exFAT". - Fix grammar, - Split long sentence. Signed-off-by: Geert Uytterhoeven Signed-off-by: Namjae Jeon Signed-off-by: Park Ju Hyung --- Kconfig | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Kconfig b/Kconfig index 2d3636dc5b8c..5a65071b5ecf 100644 --- a/Kconfig +++ b/Kconfig @@ -16,6 +16,7 @@ config EXFAT_DEFAULT_IOCHARSET depends on EXFAT_FS help Set this to the default input/output character set to use for - converting between the encoding is used for user visible filename and - UTF-16 character that exfat filesystem use, and can be overridden with - the "iocharset" mount option for exFAT filesystems. + converting between the encoding that is used for user visible + filenames and the UTF-16 character encoding that the exFAT + filesystem uses. This can be overridden with the "iocharset" mount + option for the exFAT filesystems. From e5e731520e3fd5be1907db3dbd583f09a2c06ad1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Tue, 17 Mar 2020 23:25:52 +0100 Subject: [PATCH 058/592] exfat: Simplify exfat_utf8_d_hash() for code points above U+FFFF MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Function partial_name_hash() takes long type value into which can be stored one Unicode code point. Therefore conversion from UTF-32 to UTF-16 is not needed. Signed-off-by: Pali Rohár Signed-off-by: Namjae Jeon Signed-off-by: Park Ju Hyung --- namei.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/namei.c b/namei.c index 585b47b2db3d..fa926b9c883a 100644 --- a/namei.c +++ b/namei.c @@ -147,16 +147,10 @@ static int exfat_utf8_d_hash(const struct dentry *dentry, struct qstr *qstr) return charlen; /* - * Convert to UTF-16: code points above U+FFFF are encoded as - * surrogate pairs. * exfat_toupper() works only for code points up to the U+FFFF. */ - if (u > 0xFFFF) { - hash = partial_name_hash(exfat_high_surrogate(u), hash); - hash = partial_name_hash(exfat_low_surrogate(u), hash); - } else { - hash = partial_name_hash(exfat_toupper(sb, u), hash); - } + hash = partial_name_hash(u <= 0xFFFF ? exfat_toupper(sb, u) : u, + hash); } qstr->hash = end_name_hash(hash); From f8e11d1abf36f20863664171ae40e2f571a47d42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Tue, 17 Mar 2020 23:25:54 +0100 Subject: [PATCH 059/592] exfat: Remove unused functions exfat_high_surrogate() and exfat_low_surrogate() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After applying previous two patches, these functions are not used anymore. Signed-off-by: Pali Rohár Signed-off-by: Namjae Jeon Signed-off-by: Park Ju Hyung --- exfat_fs.h | 2 -- nls.c | 13 ------------- 2 files changed, 15 deletions(-) diff --git a/exfat_fs.h b/exfat_fs.h index 1ebfb9085f1f..3862df6af738 100644 --- a/exfat_fs.h +++ b/exfat_fs.h @@ -492,8 +492,6 @@ int exfat_nls_to_utf16(struct super_block *sb, struct exfat_uni_name *uniname, int *p_lossy); int exfat_create_upcase_table(struct super_block *sb); void exfat_free_upcase_table(struct exfat_sb_info *sbi); -unsigned short exfat_high_surrogate(unicode_t u); -unsigned short exfat_low_surrogate(unicode_t u); /* exfat/misc.c */ void __exfat_fs_error(struct super_block *sb, int report, const char *fmt, ...) diff --git a/nls.c b/nls.c index 2178786b708b..1ebda90cbdd7 100644 --- a/nls.c +++ b/nls.c @@ -535,22 +535,9 @@ static int exfat_utf8_to_utf16(struct super_block *sb, return unilen; } -#define PLANE_SIZE 0x00010000 #define SURROGATE_MASK 0xfffff800 #define SURROGATE_PAIR 0x0000d800 #define SURROGATE_LOW 0x00000400 -#define SURROGATE_BITS 0x000003ff - -unsigned short exfat_high_surrogate(unicode_t u) -{ - return ((u - PLANE_SIZE) >> 10) + SURROGATE_PAIR; -} - -unsigned short exfat_low_surrogate(unicode_t u) -{ - return ((u - PLANE_SIZE) & SURROGATE_BITS) | SURROGATE_PAIR | - SURROGATE_LOW; -} static int __exfat_utf16_to_nls(struct super_block *sb, struct exfat_uni_name *p_uniname, unsigned char *p_cstring, From 996399d796b7c75c0b2c09e83e559ba7c2b6b070 Mon Sep 17 00:00:00 2001 From: Jason Yan Date: Thu, 16 Apr 2020 13:34:26 +0900 Subject: [PATCH 060/592] exfat: remove the assignment of 0 to bool variable There is no need to init 'sync' in exfat_set_vol_flags(). This also fixes the following coccicheck warning: super.c:104:6-10: WARNING: Assignment of 0/1 to bool variable Signed-off-by: Jason Yan Signed-off-by: Namjae Jeon Signed-off-by: Park Ju Hyung --- super.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/super.c b/super.c index f9aa1e5dc238..c1f47f4071a8 100644 --- a/super.c +++ b/super.c @@ -102,7 +102,7 @@ int exfat_set_vol_flags(struct super_block *sb, unsigned short new_flag) { struct exfat_sb_info *sbi = EXFAT_SB(sb); struct pbr64 *bpb = (struct pbr64 *)sbi->pbr_bh->b_data; - bool sync = 0; + bool sync; /* flags are not changed */ if (sbi->vol_flag == new_flag) From edc10efb3c7533ea9dcc7e985b08cc59eff3f90b Mon Sep 17 00:00:00 2001 From: Tetsuhiro Kohada Date: Wed, 22 Apr 2020 08:30:56 +0900 Subject: [PATCH 061/592] exfat: replace 'time_ms' with 'time_cs' Replace time_ms with time_cs in the file directory entry structure and related functions. The unit of create_time_ms/modify_time_ms in File Directory Entry are not 'milli-second', but 'centi-second'. The exfat specification uses the term '10ms', but instead use 'cs' as in msdos_fs.h. Signed-off-by: Tetsuhiro Kohada Signed-off-by: Namjae Jeon Signed-off-by: Park Ju Hyung --- dir.c | 8 ++++---- exfat_fs.h | 4 ++-- exfat_raw.h | 4 ++-- file.c | 2 +- inode.c | 4 ++-- misc.c | 18 +++++++++--------- namei.c | 4 ++-- 7 files changed, 22 insertions(+), 22 deletions(-) diff --git a/dir.c b/dir.c index 53ae965da7ec..b5a237c33d50 100644 --- a/dir.c +++ b/dir.c @@ -137,12 +137,12 @@ static int exfat_readdir(struct inode *inode, struct exfat_dir_entry *dir_entry) ep->dentry.file.create_tz, ep->dentry.file.create_time, ep->dentry.file.create_date, - ep->dentry.file.create_time_ms); + ep->dentry.file.create_time_cs); exfat_get_entry_time(sbi, &dir_entry->mtime, ep->dentry.file.modify_tz, ep->dentry.file.modify_time, ep->dentry.file.modify_date, - ep->dentry.file.modify_time_ms); + ep->dentry.file.modify_time_cs); exfat_get_entry_time(sbi, &dir_entry->atime, ep->dentry.file.access_tz, ep->dentry.file.access_time, @@ -461,12 +461,12 @@ int exfat_init_dir_entry(struct inode *inode, struct exfat_chain *p_dir, &ep->dentry.file.create_tz, &ep->dentry.file.create_time, &ep->dentry.file.create_date, - &ep->dentry.file.create_time_ms); + &ep->dentry.file.create_time_cs); exfat_set_entry_time(sbi, &ts, &ep->dentry.file.modify_tz, &ep->dentry.file.modify_time, &ep->dentry.file.modify_date, - &ep->dentry.file.modify_time_ms); + &ep->dentry.file.modify_time_cs); exfat_set_entry_time(sbi, &ts, &ep->dentry.file.access_tz, &ep->dentry.file.access_time, diff --git a/exfat_fs.h b/exfat_fs.h index 3862df6af738..294aa7792bc3 100644 --- a/exfat_fs.h +++ b/exfat_fs.h @@ -511,10 +511,10 @@ void exfat_msg(struct super_block *sb, const char *lv, const char *fmt, ...) exfat_msg(sb, KERN_INFO, fmt, ##__VA_ARGS__) void exfat_get_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts, - u8 tz, __le16 time, __le16 date, u8 time_ms); + u8 tz, __le16 time, __le16 date, u8 time_cs); void exfat_truncate_atime(struct timespec64 *ts); void exfat_set_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts, - u8 *tz, __le16 *time, __le16 *date, u8 *time_ms); + u8 *tz, __le16 *time, __le16 *date, u8 *time_cs); unsigned short exfat_calc_chksum_2byte(void *data, int len, unsigned short chksum, int type); void exfat_update_bh(struct super_block *sb, struct buffer_head *bh, int sync); diff --git a/exfat_raw.h b/exfat_raw.h index 2a841010e649..8d6c64a7546d 100644 --- a/exfat_raw.h +++ b/exfat_raw.h @@ -136,8 +136,8 @@ struct exfat_dentry { __le16 modify_date; __le16 access_time; __le16 access_date; - __u8 create_time_ms; - __u8 modify_time_ms; + __u8 create_time_cs; + __u8 modify_time_cs; __u8 create_tz; __u8 modify_tz; __u8 access_tz; diff --git a/file.c b/file.c index c9db8eb0cfc3..84f3d31a3a55 100644 --- a/file.c +++ b/file.c @@ -165,7 +165,7 @@ int __exfat_truncate(struct inode *inode, loff_t new_size) &ep->dentry.file.modify_tz, &ep->dentry.file.modify_time, &ep->dentry.file.modify_date, - &ep->dentry.file.modify_time_ms); + &ep->dentry.file.modify_time_cs); ep->dentry.file.attr = cpu_to_le16(ei->attr); /* File size should be zero if there is no cluster allocated */ diff --git a/inode.c b/inode.c index 06887492f54b..3f367d081cd6 100644 --- a/inode.c +++ b/inode.c @@ -56,12 +56,12 @@ static int __exfat_write_inode(struct inode *inode, int sync) &ep->dentry.file.create_tz, &ep->dentry.file.create_time, &ep->dentry.file.create_date, - &ep->dentry.file.create_time_ms); + &ep->dentry.file.create_time_cs); exfat_set_entry_time(sbi, &inode->i_mtime, &ep->dentry.file.modify_tz, &ep->dentry.file.modify_time, &ep->dentry.file.modify_date, - &ep->dentry.file.modify_time_ms); + &ep->dentry.file.modify_time_cs); exfat_set_entry_time(sbi, &inode->i_atime, &ep->dentry.file.access_tz, &ep->dentry.file.access_time, diff --git a/misc.c b/misc.c index ce5e8a1b0726..ab7f88b1f6d3 100644 --- a/misc.c +++ b/misc.c @@ -75,7 +75,7 @@ static void exfat_adjust_tz(struct timespec64 *ts, u8 tz_off) /* Convert a EXFAT time/date pair to a UNIX date (seconds since 1 1 70). */ void exfat_get_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts, - u8 tz, __le16 time, __le16 date, u8 time_ms) + u8 tz, __le16 time, __le16 date, u8 time_cs) { u16 t = le16_to_cpu(time); u16 d = le16_to_cpu(date); @@ -84,10 +84,10 @@ void exfat_get_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts, t >> 11, (t >> 5) & 0x003F, (t & 0x001F) << 1); - /* time_ms field represent 0 ~ 199(1990 ms) */ - if (time_ms) { - ts->tv_sec += time_ms / 100; - ts->tv_nsec = (time_ms % 100) * 10 * NSEC_PER_MSEC; + /* time_cs field represent 0 ~ 199cs(1990 ms) */ + if (time_cs) { + ts->tv_sec += time_cs / 100; + ts->tv_nsec = (time_cs % 100) * 10 * NSEC_PER_MSEC; } else ts->tv_nsec = 0; @@ -101,7 +101,7 @@ void exfat_get_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts, /* Convert linear UNIX date to a EXFAT time/date pair. */ void exfat_set_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts, - u8 *tz, __le16 *time, __le16 *date, u8 *time_ms) + u8 *tz, __le16 *time, __le16 *date, u8 *time_cs) { struct tm tm; u16 t, d; @@ -113,9 +113,9 @@ void exfat_set_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts, *time = cpu_to_le16(t); *date = cpu_to_le16(d); - /* time_ms field represent 0 ~ 199(1990 ms) */ - if (time_ms) - *time_ms = (tm.tm_sec & 1) * 100 + + /* time_cs field represent 0 ~ 199cs(1990 ms) */ + if (time_cs) + *time_cs = (tm.tm_sec & 1) * 100 + ts->tv_nsec / (10 * NSEC_PER_MSEC); /* diff --git a/namei.c b/namei.c index fa926b9c883a..48f4df883f3b 100644 --- a/namei.c +++ b/namei.c @@ -689,12 +689,12 @@ static int exfat_find(struct inode *dir, struct qstr *qname, ep->dentry.file.create_tz, ep->dentry.file.create_time, ep->dentry.file.create_date, - ep->dentry.file.create_time_ms); + ep->dentry.file.create_time_cs); exfat_get_entry_time(sbi, &info->mtime, ep->dentry.file.modify_tz, ep->dentry.file.modify_time, ep->dentry.file.modify_date, - ep->dentry.file.modify_time_ms); + ep->dentry.file.modify_time_cs); exfat_get_entry_time(sbi, &info->atime, ep->dentry.file.access_tz, ep->dentry.file.access_time, From b9ccfcdc8cdd24bdb640a80a4791806dd3ce61ca Mon Sep 17 00:00:00 2001 From: Tetsuhiro Kohada Date: Wed, 20 May 2020 16:56:41 +0900 Subject: [PATCH 062/592] exfat: optimize dir-cache Optimize directory access based on exfat_entry_set_cache. - Hold bh instead of copied d-entry. - Modify bh->data directly instead of the copied d-entry. - Write back the retained bh instead of rescanning the d-entry-set. And - Remove unused cache related definitions. Signed-off-by: Tetsuhiro Kohada Reviewed-by: Sungjong Seo Signed-off-by: Namjae Jeon Signed-off-by: Park Ju Hyung --- dir.c | 197 ++++++++++++++++++++--------------------------------- exfat_fs.h | 27 ++++---- file.c | 15 ++-- inode.c | 51 ++++++-------- namei.c | 14 ++-- 5 files changed, 123 insertions(+), 181 deletions(-) diff --git a/dir.c b/dir.c index b5a237c33d50..2902d285bf20 100644 --- a/dir.c +++ b/dir.c @@ -32,35 +32,30 @@ static void exfat_get_uniname_from_ext_entry(struct super_block *sb, struct exfat_chain *p_dir, int entry, unsigned short *uniname) { int i; - struct exfat_dentry *ep; struct exfat_entry_set_cache *es; - es = exfat_get_dentry_set(sb, p_dir, entry, ES_ALL_ENTRIES, &ep); + es = exfat_get_dentry_set(sb, p_dir, entry, ES_ALL_ENTRIES); if (!es) return; - if (es->num_entries < 3) - goto free_es; - - ep += 2; - /* * First entry : file entry * Second entry : stream-extension entry * Third entry : first file-name entry * So, the index of first file-name dentry should start from 2. */ - for (i = 2; i < es->num_entries; i++, ep++) { + for (i = 2; i < es->num_entries; i++) { + struct exfat_dentry *ep = exfat_get_dentry_cached(es, i); + /* end of name entry */ if (exfat_get_entry_type(ep) != TYPE_EXTEND) - goto free_es; + break; exfat_extract_uni_name(ep, uniname); uniname += EXFAT_FILE_NAME_LEN; } -free_es: - kfree(es); + exfat_free_dentry_set(es, false); } /* read a directory entry from the opened directory */ @@ -590,62 +585,33 @@ int exfat_remove_entries(struct inode *inode, struct exfat_chain *p_dir, return 0; } -int exfat_update_dir_chksum_with_entry_set(struct super_block *sb, - struct exfat_entry_set_cache *es, int sync) +void exfat_update_dir_chksum_with_entry_set(struct exfat_entry_set_cache *es) { - struct exfat_sb_info *sbi = EXFAT_SB(sb); - struct buffer_head *bh; - sector_t sec = es->sector; - unsigned int off = es->offset; - int chksum_type = CS_DIR_ENTRY, i, num_entries = es->num_entries; - unsigned int buf_off = (off - es->offset); - unsigned int remaining_byte_in_sector, copy_entries, clu; + int chksum_type = CS_DIR_ENTRY, i; unsigned short chksum = 0; + struct exfat_dentry *ep; - for (i = 0; i < num_entries; i++) { - chksum = exfat_calc_chksum_2byte(&es->entries[i], DENTRY_SIZE, - chksum, chksum_type); + for (i = 0; i < es->num_entries; i++) { + ep = exfat_get_dentry_cached(es, i); + chksum = exfat_calc_chksum_2byte(ep, DENTRY_SIZE, chksum, + chksum_type); chksum_type = CS_DEFAULT; } + ep = exfat_get_dentry_cached(es, 0); + ep->dentry.file.checksum = cpu_to_le16(chksum); + es->modified = true; +} - es->entries[0].dentry.file.checksum = cpu_to_le16(chksum); +void exfat_free_dentry_set(struct exfat_entry_set_cache *es, int sync) +{ + int i; - while (num_entries) { - /* write per sector base */ - remaining_byte_in_sector = (1 << sb->s_blocksize_bits) - off; - copy_entries = min_t(int, - EXFAT_B_TO_DEN(remaining_byte_in_sector), - num_entries); - bh = sb_bread(sb, sec); - if (!bh) - goto err_out; - memcpy(bh->b_data + off, - (unsigned char *)&es->entries[0] + buf_off, - EXFAT_DEN_TO_B(copy_entries)); - exfat_update_bh(sb, bh, sync); - brelse(bh); - num_entries -= copy_entries; - - if (num_entries) { - /* get next sector */ - if (exfat_is_last_sector_in_cluster(sbi, sec)) { - clu = exfat_sector_to_cluster(sbi, sec); - if (es->alloc_flag == ALLOC_NO_FAT_CHAIN) - clu++; - else if (exfat_get_next_cluster(sb, &clu)) - goto err_out; - sec = exfat_cluster_to_sector(sbi, clu); - } else { - sec++; - } - off = 0; - buf_off += EXFAT_DEN_TO_B(copy_entries); - } + for (i = 0; i < es->num_bh; i++) { + if (es->modified) + exfat_update_bh(es->sb, es->bh[i], sync); + brelse(es->bh[i]); } - - return 0; -err_out: - return -EIO; + kfree(es); } static int exfat_walk_fat_chain(struct super_block *sb, @@ -820,34 +786,40 @@ static bool exfat_validate_entry(unsigned int type, } } +struct exfat_dentry *exfat_get_dentry_cached( + struct exfat_entry_set_cache *es, int num) +{ + int off = es->start_off + num * DENTRY_SIZE; + struct buffer_head *bh = es->bh[EXFAT_B_TO_BLK(off, es->sb)]; + char *p = bh->b_data + EXFAT_BLK_OFFSET(off, es->sb); + + return (struct exfat_dentry *)p; +} + /* * Returns a set of dentries for a file or dir. * - * Note that this is a copy (dump) of dentries so that user should - * call write_entry_set() to apply changes made in this entry set - * to the real device. + * Note It provides a direct pointer to bh->data via exfat_get_dentry_cached(). + * User should call exfat_get_dentry_set() after setting 'modified' to apply + * changes made in this entry set to the real device. * * in: * sb+p_dir+entry: indicates a file/dir * type: specifies how many dentries should be included. - * out: - * file_ep: will point the first dentry(= file dentry) on success * return: * pointer of entry set on success, * NULL on failure. */ struct exfat_entry_set_cache *exfat_get_dentry_set(struct super_block *sb, - struct exfat_chain *p_dir, int entry, unsigned int type, - struct exfat_dentry **file_ep) + struct exfat_chain *p_dir, int entry, unsigned int type) { - int ret; + int ret, i, num_bh; unsigned int off, byte_offset, clu = 0; - unsigned int entry_type; sector_t sec; struct exfat_sb_info *sbi = EXFAT_SB(sb); struct exfat_entry_set_cache *es; - struct exfat_dentry *ep, *pos; - unsigned char num_entries; + struct exfat_dentry *ep; + int num_entries; enum exfat_validate_dentry_mode mode = ES_MODE_STARTED; struct buffer_head *bh; @@ -861,11 +833,18 @@ struct exfat_entry_set_cache *exfat_get_dentry_set(struct super_block *sb, if (ret) return NULL; + es = kzalloc(sizeof(*es), GFP_KERNEL); + if (!es) + return NULL; + es->sb = sb; + es->modified = false; + /* byte offset in cluster */ byte_offset = EXFAT_CLU_OFFSET(byte_offset, sbi); /* byte offset in sector */ off = EXFAT_BLK_OFFSET(byte_offset, sb); + es->start_off = off; /* sector offset in cluster */ sec = EXFAT_B_TO_BLK(byte_offset, sb); @@ -873,72 +852,46 @@ struct exfat_entry_set_cache *exfat_get_dentry_set(struct super_block *sb, bh = sb_bread(sb, sec); if (!bh) - return NULL; + goto free_es; + es->bh[es->num_bh++] = bh; - ep = (struct exfat_dentry *)(bh->b_data + off); - entry_type = exfat_get_entry_type(ep); - - if (entry_type != TYPE_FILE && entry_type != TYPE_DIR) - goto release_bh; + ep = exfat_get_dentry_cached(es, 0); + if (!exfat_validate_entry(exfat_get_entry_type(ep), &mode)) + goto free_es; num_entries = type == ES_ALL_ENTRIES ? ep->dentry.file.num_ext + 1 : type; - es = kmalloc(struct_size(es, entries, num_entries), GFP_KERNEL); - if (!es) - goto release_bh; - es->num_entries = num_entries; - es->sector = sec; - es->offset = off; - es->alloc_flag = p_dir->flags; - pos = &es->entries[0]; - - while (num_entries) { - if (!exfat_validate_entry(exfat_get_entry_type(ep), &mode)) - goto free_es; - - /* copy dentry */ - memcpy(pos, ep, sizeof(struct exfat_dentry)); - - if (--num_entries == 0) - break; - - if (((off + DENTRY_SIZE) & (sb->s_blocksize - 1)) < - (off & (sb->s_blocksize - 1))) { - /* get the next sector */ - if (exfat_is_last_sector_in_cluster(sbi, sec)) { - if (es->alloc_flag == ALLOC_NO_FAT_CHAIN) - clu++; - else if (exfat_get_next_cluster(sb, &clu)) - goto free_es; - sec = exfat_cluster_to_sector(sbi, clu); - } else { - sec++; - } - - brelse(bh); - bh = sb_bread(sb, sec); - if (!bh) + num_bh = EXFAT_B_TO_BLK_ROUND_UP(off + num_entries * DENTRY_SIZE, sb); + for (i = 1; i < num_bh; i++) { + /* get the next sector */ + if (exfat_is_last_sector_in_cluster(sbi, sec)) { + if (p_dir->flags == ALLOC_NO_FAT_CHAIN) + clu++; + else if (exfat_get_next_cluster(sb, &clu)) goto free_es; - off = 0; - ep = (struct exfat_dentry *)bh->b_data; + sec = exfat_cluster_to_sector(sbi, clu); } else { - ep++; - off += DENTRY_SIZE; + sec++; } - pos++; + + bh = sb_bread(sb, sec); + if (!bh) + goto free_es; + es->bh[es->num_bh++] = bh; } - if (file_ep) - *file_ep = &es->entries[0]; - brelse(bh); + /* validiate cached dentries */ + for (i = 1; i < num_entries; i++) { + ep = exfat_get_dentry_cached(es, i); + if (!exfat_validate_entry(exfat_get_entry_type(ep), &mode)) + goto free_es; + } return es; free_es: - kfree(es); -release_bh: - brelse(bh); + exfat_free_dentry_set(es, false); return NULL; } diff --git a/exfat_fs.h b/exfat_fs.h index 294aa7792bc3..c84ae9e60508 100644 --- a/exfat_fs.h +++ b/exfat_fs.h @@ -71,10 +71,8 @@ enum { #define MAX_NAME_LENGTH 255 /* max len of file name excluding NULL */ #define MAX_VFSNAME_BUF_SIZE ((MAX_NAME_LENGTH + 1) * MAX_CHARSET_SIZE) -#define FAT_CACHE_SIZE 128 -#define FAT_CACHE_HASH_SIZE 64 -#define BUF_CACHE_SIZE 256 -#define BUF_CACHE_HASH_SIZE 64 +/* Enough size to hold 256 dentry (even 512 Byte sector) */ +#define DIR_CACHE_SIZE (256*sizeof(struct exfat_dentry)/512+1) #define EXFAT_HINT_NONE -1 #define EXFAT_MIN_SUBDIR 2 @@ -170,14 +168,12 @@ struct exfat_hint { }; struct exfat_entry_set_cache { - /* sector number that contains file_entry */ - sector_t sector; - /* byte offset in the sector */ - unsigned int offset; - /* flag in stream entry. 01 for cluster chain, 03 for contig. */ - int alloc_flag; + struct super_block *sb; + bool modified; + unsigned int start_off; + int num_bh; + struct buffer_head *bh[DIR_CACHE_SIZE]; unsigned int num_entries; - struct exfat_dentry entries[]; }; struct exfat_dir_entry { @@ -451,8 +447,7 @@ int exfat_remove_entries(struct inode *inode, struct exfat_chain *p_dir, int entry, int order, int num_entries); int exfat_update_dir_chksum(struct inode *inode, struct exfat_chain *p_dir, int entry); -int exfat_update_dir_chksum_with_entry_set(struct super_block *sb, - struct exfat_entry_set_cache *es, int sync); +void exfat_update_dir_chksum_with_entry_set(struct exfat_entry_set_cache *es); int exfat_calc_num_entries(struct exfat_uni_name *p_uniname); int exfat_find_dir_entry(struct super_block *sb, struct exfat_inode_info *ei, struct exfat_chain *p_dir, struct exfat_uni_name *p_uniname, @@ -463,9 +458,11 @@ int exfat_find_location(struct super_block *sb, struct exfat_chain *p_dir, struct exfat_dentry *exfat_get_dentry(struct super_block *sb, struct exfat_chain *p_dir, int entry, struct buffer_head **bh, sector_t *sector); +struct exfat_dentry *exfat_get_dentry_cached(struct exfat_entry_set_cache *es, + int num); struct exfat_entry_set_cache *exfat_get_dentry_set(struct super_block *sb, - struct exfat_chain *p_dir, int entry, unsigned int type, - struct exfat_dentry **file_ep); + struct exfat_chain *p_dir, int entry, unsigned int type); +void exfat_free_dentry_set(struct exfat_entry_set_cache *es, int sync); int exfat_count_dir_entries(struct super_block *sb, struct exfat_chain *p_dir); /* inode.c */ diff --git a/file.c b/file.c index 84f3d31a3a55..8e3f0eef45d7 100644 --- a/file.c +++ b/file.c @@ -96,11 +96,9 @@ int __exfat_truncate(struct inode *inode, loff_t new_size) unsigned int num_clusters_new, num_clusters_phys; unsigned int last_clu = EXFAT_FREE_CLUSTER; struct exfat_chain clu; - struct exfat_dentry *ep, *ep2; struct super_block *sb = inode->i_sb; struct exfat_sb_info *sbi = EXFAT_SB(sb); struct exfat_inode_info *ei = EXFAT_I(inode); - struct exfat_entry_set_cache *es = NULL; int evict = (ei->dir.dir == DIR_DELETED) ? 1 : 0; /* check if the given file ID is opened */ @@ -153,12 +151,15 @@ int __exfat_truncate(struct inode *inode, loff_t new_size) /* update the directory entry */ if (!evict) { struct timespec64 ts; + struct exfat_dentry *ep, *ep2; + struct exfat_entry_set_cache *es; es = exfat_get_dentry_set(sb, &(ei->dir), ei->entry, - ES_ALL_ENTRIES, &ep); + ES_ALL_ENTRIES); if (!es) return -EIO; - ep2 = ep + 1; + ep = exfat_get_dentry_cached(es, 0); + ep2 = exfat_get_dentry_cached(es, 1); ts = current_time(inode); exfat_set_entry_time(sbi, &ts, @@ -185,10 +186,8 @@ int __exfat_truncate(struct inode *inode, loff_t new_size) ep2->dentry.stream.start_clu = EXFAT_FREE_CLUSTER; } - if (exfat_update_dir_chksum_with_entry_set(sb, es, - inode_needs_sync(inode))) - return -EIO; - kfree(es); + exfat_update_dir_chksum_with_entry_set(es); + exfat_free_dentry_set(es, inode_needs_sync(inode)); } /* cut off from the FAT chain */ diff --git a/inode.c b/inode.c index 3f367d081cd6..ef7cf7a6d187 100644 --- a/inode.c +++ b/inode.c @@ -19,7 +19,6 @@ static int __exfat_write_inode(struct inode *inode, int sync) { - int ret = -EIO; unsigned long long on_disk_size; struct exfat_dentry *ep, *ep2; struct exfat_entry_set_cache *es = NULL; @@ -43,11 +42,11 @@ static int __exfat_write_inode(struct inode *inode, int sync) exfat_set_vol_flags(sb, VOL_DIRTY); /* get the directory entry of given file or directory */ - es = exfat_get_dentry_set(sb, &(ei->dir), ei->entry, ES_ALL_ENTRIES, - &ep); + es = exfat_get_dentry_set(sb, &(ei->dir), ei->entry, ES_ALL_ENTRIES); if (!es) return -EIO; - ep2 = ep + 1; + ep = exfat_get_dentry_cached(es, 0); + ep2 = exfat_get_dentry_cached(es, 1); ep->dentry.file.attr = cpu_to_le16(exfat_make_attr(inode)); @@ -77,9 +76,9 @@ static int __exfat_write_inode(struct inode *inode, int sync) ep2->dentry.stream.valid_size = cpu_to_le64(on_disk_size); ep2->dentry.stream.size = ep2->dentry.stream.valid_size; - ret = exfat_update_dir_chksum_with_entry_set(sb, es, sync); - kfree(es); - return ret; + exfat_update_dir_chksum_with_entry_set(es); + exfat_free_dentry_set(es, sync); + return 0; } int exfat_write_inode(struct inode *inode, struct writeback_control *wbc) @@ -110,8 +109,6 @@ static int exfat_map_cluster(struct inode *inode, unsigned int clu_offset, int ret, modified = false; unsigned int last_clu; struct exfat_chain new_clu; - struct exfat_dentry *ep; - struct exfat_entry_set_cache *es = NULL; struct super_block *sb = inode->i_sb; struct exfat_sb_info *sbi = EXFAT_SB(sb); struct exfat_inode_info *ei = EXFAT_I(inode); @@ -222,34 +219,28 @@ static int exfat_map_cluster(struct inode *inode, unsigned int clu_offset, num_clusters += num_to_be_allocated; *clu = new_clu.dir; - if (ei->dir.dir != DIR_DELETED) { + if (ei->dir.dir != DIR_DELETED && modified) { + struct exfat_dentry *ep; + struct exfat_entry_set_cache *es; + es = exfat_get_dentry_set(sb, &(ei->dir), ei->entry, - ES_ALL_ENTRIES, &ep); + ES_ALL_ENTRIES); if (!es) return -EIO; /* get stream entry */ - ep++; + ep = exfat_get_dentry_cached(es, 1); /* update directory entry */ - if (modified) { - if (ep->dentry.stream.flags != ei->flags) - ep->dentry.stream.flags = ei->flags; + ep->dentry.stream.flags = ei->flags; + ep->dentry.stream.start_clu = + cpu_to_le32(ei->start_clu); + ep->dentry.stream.valid_size = + cpu_to_le64(i_size_read(inode)); + ep->dentry.stream.size = + ep->dentry.stream.valid_size; - if (le32_to_cpu(ep->dentry.stream.start_clu) != - ei->start_clu) - ep->dentry.stream.start_clu = - cpu_to_le32(ei->start_clu); - - ep->dentry.stream.valid_size = - cpu_to_le64(i_size_read(inode)); - ep->dentry.stream.size = - ep->dentry.stream.valid_size; - } - - if (exfat_update_dir_chksum_with_entry_set(sb, es, - inode_needs_sync(inode))) - return -EIO; - kfree(es); + exfat_update_dir_chksum_with_entry_set(es); + exfat_free_dentry_set(es, inode_needs_sync(inode)); } /* end of if != DIR_DELETED */ diff --git a/namei.c b/namei.c index 48f4df883f3b..5b0f35329d63 100644 --- a/namei.c +++ b/namei.c @@ -600,8 +600,6 @@ static int exfat_find(struct inode *dir, struct qstr *qname, int ret, dentry, num_entries, count; struct exfat_chain cdir; struct exfat_uni_name uni_name; - struct exfat_dentry *ep, *ep2; - struct exfat_entry_set_cache *es = NULL; struct super_block *sb = dir->i_sb; struct exfat_sb_info *sbi = EXFAT_SB(sb); struct exfat_inode_info *ei = EXFAT_I(dir); @@ -660,10 +658,14 @@ static int exfat_find(struct inode *dir, struct qstr *qname, info->num_subdirs = count; } else { - es = exfat_get_dentry_set(sb, &cdir, dentry, ES_2_ENTRIES, &ep); + struct exfat_dentry *ep, *ep2; + struct exfat_entry_set_cache *es; + + es = exfat_get_dentry_set(sb, &cdir, dentry, ES_2_ENTRIES); if (!es) return -EIO; - ep2 = ep + 1; + ep = exfat_get_dentry_cached(es, 0); + ep2 = exfat_get_dentry_cached(es, 1); info->type = exfat_get_entry_type(ep); info->attr = le16_to_cpu(ep->dentry.file.attr); @@ -681,7 +683,7 @@ static int exfat_find(struct inode *dir, struct qstr *qname, exfat_fs_error(sb, "non-zero size file starts with zero cluster (size : %llu, p_dir : %u, entry : 0x%08x)", i_size_read(dir), ei->dir.dir, ei->entry); - kfree(es); + exfat_free_dentry_set(es, false); return -EIO; } @@ -700,7 +702,7 @@ static int exfat_find(struct inode *dir, struct qstr *qname, ep->dentry.file.access_time, ep->dentry.file.access_date, 0); - kfree(es); + exfat_free_dentry_set(es, false); if (info->type == TYPE_DIR) { exfat_chain_set(&cdir, info->start_clu, From 151d575510c5d71da530a4db90c5f0264724005d Mon Sep 17 00:00:00 2001 From: Tetsuhiro Kohada Date: Fri, 29 May 2020 19:14:56 +0900 Subject: [PATCH 063/592] exfat: redefine PBR as boot_sector Aggregate PBR related definitions and redefine as "boot_sector" to comply with the exFAT specification. And, rename variable names including 'pbr'. Signed-off-by: Tetsuhiro Kohada Reviewed-by: Sungjong Seo Signed-off-by: Namjae Jeon Signed-off-by: Park Ju Hyung --- exfat_fs.h | 2 +- exfat_raw.h | 79 ++++++++++++++++++------------------------------- super.c | 84 ++++++++++++++++++++++++++--------------------------- 3 files changed, 72 insertions(+), 93 deletions(-) diff --git a/exfat_fs.h b/exfat_fs.h index c84ae9e60508..911f58b93f3d 100644 --- a/exfat_fs.h +++ b/exfat_fs.h @@ -227,7 +227,7 @@ struct exfat_sb_info { unsigned int root_dir; /* root dir cluster */ unsigned int dentries_per_clu; /* num of dentries per cluster */ unsigned int vol_flag; /* volume dirty flag */ - struct buffer_head *pbr_bh; /* buffer_head of PBR sector */ + struct buffer_head *boot_bh; /* buffer_head of BOOT sector */ unsigned int map_clu; /* allocation bitmap start cluster */ unsigned int map_sectors; /* num of allocation bitmap sectors */ diff --git a/exfat_raw.h b/exfat_raw.h index 8d6c64a7546d..07f74190df44 100644 --- a/exfat_raw.h +++ b/exfat_raw.h @@ -8,7 +8,8 @@ #include -#define PBR_SIGNATURE 0xAA55 +#define BOOT_SIGNATURE 0xAA55 +#define EXBOOT_SIGNATURE 0xAA550000 #define EXFAT_MAX_FILE_LEN 255 @@ -55,7 +56,7 @@ /* checksum types */ #define CS_DIR_ENTRY 0 -#define CS_PBR_SECTOR 1 +#define CS_BOOT_SECTOR 1 #define CS_DEFAULT 2 /* file attributes */ @@ -69,57 +70,35 @@ #define ATTR_RWMASK (ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUME | \ ATTR_SUBDIR | ATTR_ARCHIVE) -#define PBR64_JUMP_BOOT_LEN 3 -#define PBR64_OEM_NAME_LEN 8 -#define PBR64_RESERVED_LEN 53 +#define BOOTSEC_JUMP_BOOT_LEN 3 +#define BOOTSEC_FS_NAME_LEN 8 +#define BOOTSEC_OLDBPB_LEN 53 #define EXFAT_FILE_NAME_LEN 15 -/* EXFAT BIOS parameter block (64 bytes) */ -struct bpb64 { - __u8 jmp_boot[PBR64_JUMP_BOOT_LEN]; - __u8 oem_name[PBR64_OEM_NAME_LEN]; - __u8 res_zero[PBR64_RESERVED_LEN]; -} __packed; - -/* EXFAT EXTEND BIOS parameter block (56 bytes) */ -struct bsx64 { - __le64 vol_offset; - __le64 vol_length; - __le32 fat_offset; - __le32 fat_length; - __le32 clu_offset; - __le32 clu_count; - __le32 root_cluster; - __le32 vol_serial; - __u8 fs_version[2]; - __le16 vol_flags; - __u8 sect_size_bits; - __u8 sect_per_clus_bits; - __u8 num_fats; - __u8 phy_drv_no; - __u8 perc_in_use; - __u8 reserved2[7]; -} __packed; - -/* EXFAT PBR[BPB+BSX] (120 bytes) */ -struct pbr64 { - struct bpb64 bpb; - struct bsx64 bsx; -} __packed; - -/* Common PBR[Partition Boot Record] (512 bytes) */ -struct pbr { - union { - __u8 raw[64]; - struct bpb64 f64; - } bpb; - union { - __u8 raw[56]; - struct bsx64 f64; - } bsx; - __u8 boot_code[390]; - __le16 signature; +/* EXFAT: Main and Backup Boot Sector (512 bytes) */ +struct boot_sector { + __u8 jmp_boot[BOOTSEC_JUMP_BOOT_LEN]; + __u8 fs_name[BOOTSEC_FS_NAME_LEN]; + __u8 must_be_zero[BOOTSEC_OLDBPB_LEN]; + __le64 partition_offset; + __le64 vol_length; + __le32 fat_offset; + __le32 fat_length; + __le32 clu_offset; + __le32 clu_count; + __le32 root_cluster; + __le32 vol_serial; + __u8 fs_revision[2]; + __le16 vol_flags; + __u8 sect_size_bits; + __u8 sect_per_clus_bits; + __u8 num_fats; + __u8 drv_sel; + __u8 percent_in_use; + __u8 reserved[7]; + __u8 boot_code[390]; + __le16 signature; } __packed; struct exfat_dentry { diff --git a/super.c b/super.c index c1f47f4071a8..e60d28e73ff0 100644 --- a/super.c +++ b/super.c @@ -49,7 +49,7 @@ static void exfat_put_super(struct super_block *sb) sync_blockdev(sb->s_bdev); exfat_set_vol_flags(sb, VOL_CLEAN); exfat_free_bitmap(sbi); - brelse(sbi->pbr_bh); + brelse(sbi->boot_bh); mutex_unlock(&sbi->s_lock); call_rcu(&sbi->rcu, exfat_delayed_free); @@ -101,7 +101,7 @@ static int exfat_statfs(struct dentry *dentry, struct kstatfs *buf) int exfat_set_vol_flags(struct super_block *sb, unsigned short new_flag) { struct exfat_sb_info *sbi = EXFAT_SB(sb); - struct pbr64 *bpb = (struct pbr64 *)sbi->pbr_bh->b_data; + struct boot_sector *p_boot = (struct boot_sector *)sbi->boot_bh->b_data; bool sync; /* flags are not changed */ @@ -116,18 +116,18 @@ int exfat_set_vol_flags(struct super_block *sb, unsigned short new_flag) if (sb_rdonly(sb)) return 0; - bpb->bsx.vol_flags = cpu_to_le16(new_flag); + p_boot->vol_flags = cpu_to_le16(new_flag); - if (new_flag == VOL_DIRTY && !buffer_dirty(sbi->pbr_bh)) + if (new_flag == VOL_DIRTY && !buffer_dirty(sbi->boot_bh)) sync = true; else sync = false; - set_buffer_uptodate(sbi->pbr_bh); - mark_buffer_dirty(sbi->pbr_bh); + set_buffer_uptodate(sbi->boot_bh); + mark_buffer_dirty(sbi->boot_bh); if (sync) - sync_dirty_buffer(sbi->pbr_bh); + sync_dirty_buffer(sbi->boot_bh); return 0; } @@ -366,13 +366,14 @@ static int exfat_read_root(struct inode *inode) return 0; } -static struct pbr *exfat_read_pbr_with_logical_sector(struct super_block *sb) +static struct boot_sector *exfat_read_boot_with_logical_sector( + struct super_block *sb) { struct exfat_sb_info *sbi = EXFAT_SB(sb); - struct pbr *p_pbr = (struct pbr *) (sbi->pbr_bh)->b_data; + struct boot_sector *p_boot = (struct boot_sector *)sbi->boot_bh->b_data; unsigned short logical_sect = 0; - logical_sect = 1 << p_pbr->bsx.f64.sect_size_bits; + logical_sect = 1 << p_boot->sect_size_bits; if (!is_power_of_2(logical_sect) || logical_sect < 512 || logical_sect > 4096) { @@ -387,49 +388,48 @@ static struct pbr *exfat_read_pbr_with_logical_sector(struct super_block *sb) } if (logical_sect > sb->s_blocksize) { - brelse(sbi->pbr_bh); - sbi->pbr_bh = NULL; + brelse(sbi->boot_bh); + sbi->boot_bh = NULL; if (!sb_set_blocksize(sb, logical_sect)) { exfat_err(sb, "unable to set blocksize %u", logical_sect); return NULL; } - sbi->pbr_bh = sb_bread(sb, 0); - if (!sbi->pbr_bh) { + sbi->boot_bh = sb_bread(sb, 0); + if (!sbi->boot_bh) { exfat_err(sb, "unable to read boot sector (logical sector size = %lu)", sb->s_blocksize); return NULL; } - p_pbr = (struct pbr *)sbi->pbr_bh->b_data; + p_boot = (struct boot_sector *)sbi->boot_bh->b_data; } - return p_pbr; + return p_boot; } /* mount the file system volume */ static int __exfat_fill_super(struct super_block *sb) { int ret; - struct pbr *p_pbr; - struct pbr64 *p_bpb; + struct boot_sector *p_boot; struct exfat_sb_info *sbi = EXFAT_SB(sb); /* set block size to read super block */ sb_min_blocksize(sb, 512); /* read boot sector */ - sbi->pbr_bh = sb_bread(sb, 0); - if (!sbi->pbr_bh) { + sbi->boot_bh = sb_bread(sb, 0); + if (!sbi->boot_bh) { exfat_err(sb, "unable to read boot sector"); return -EIO; } /* PRB is read */ - p_pbr = (struct pbr *)sbi->pbr_bh->b_data; + p_boot = (struct boot_sector *)sbi->boot_bh->b_data; - /* check the validity of PBR */ - if (le16_to_cpu((p_pbr->signature)) != PBR_SIGNATURE) { + /* check the validity of BOOT */ + if (le16_to_cpu((p_boot->signature)) != BOOT_SIGNATURE) { exfat_err(sb, "invalid boot record signature"); ret = -EINVAL; goto free_bh; @@ -437,8 +437,8 @@ static int __exfat_fill_super(struct super_block *sb) /* check logical sector size */ - p_pbr = exfat_read_pbr_with_logical_sector(sb); - if (!p_pbr) { + p_boot = exfat_read_boot_with_logical_sector(sb); + if (!p_boot) { ret = -EIO; goto free_bh; } @@ -447,43 +447,43 @@ static int __exfat_fill_super(struct super_block *sb) * res_zero field must be filled with zero to prevent mounting * from FAT volume. */ - if (memchr_inv(p_pbr->bpb.f64.res_zero, 0, - sizeof(p_pbr->bpb.f64.res_zero))) { + if (memchr_inv(p_boot->must_be_zero, 0, + sizeof(p_boot->must_be_zero))) { ret = -EINVAL; goto free_bh; } - p_bpb = (struct pbr64 *)p_pbr; - if (!p_bpb->bsx.num_fats) { + p_boot = (struct boot_sector *)p_boot; + if (!p_boot->num_fats) { exfat_err(sb, "bogus number of FAT structure"); ret = -EINVAL; goto free_bh; } - sbi->sect_per_clus = 1 << p_bpb->bsx.sect_per_clus_bits; - sbi->sect_per_clus_bits = p_bpb->bsx.sect_per_clus_bits; + sbi->sect_per_clus = 1 << p_boot->sect_per_clus_bits; + sbi->sect_per_clus_bits = p_boot->sect_per_clus_bits; sbi->cluster_size_bits = sbi->sect_per_clus_bits + sb->s_blocksize_bits; sbi->cluster_size = 1 << sbi->cluster_size_bits; - sbi->num_FAT_sectors = le32_to_cpu(p_bpb->bsx.fat_length); - sbi->FAT1_start_sector = le32_to_cpu(p_bpb->bsx.fat_offset); - sbi->FAT2_start_sector = p_bpb->bsx.num_fats == 1 ? + sbi->num_FAT_sectors = le32_to_cpu(p_boot->fat_length); + sbi->FAT1_start_sector = le32_to_cpu(p_boot->fat_offset); + sbi->FAT2_start_sector = p_boot->num_fats == 1 ? sbi->FAT1_start_sector : sbi->FAT1_start_sector + sbi->num_FAT_sectors; - sbi->data_start_sector = le32_to_cpu(p_bpb->bsx.clu_offset); - sbi->num_sectors = le64_to_cpu(p_bpb->bsx.vol_length); + sbi->data_start_sector = le32_to_cpu(p_boot->clu_offset); + sbi->num_sectors = le64_to_cpu(p_boot->vol_length); /* because the cluster index starts with 2 */ - sbi->num_clusters = le32_to_cpu(p_bpb->bsx.clu_count) + + sbi->num_clusters = le32_to_cpu(p_boot->clu_count) + EXFAT_RESERVED_CLUSTERS; - sbi->root_dir = le32_to_cpu(p_bpb->bsx.root_cluster); + sbi->root_dir = le32_to_cpu(p_boot->root_cluster); sbi->dentries_per_clu = 1 << (sbi->cluster_size_bits - DENTRY_SIZE_BITS); - sbi->vol_flag = le16_to_cpu(p_bpb->bsx.vol_flags); + sbi->vol_flag = le16_to_cpu(p_boot->vol_flags); sbi->clu_srch_ptr = EXFAT_FIRST_CLUSTER; sbi->used_clusters = EXFAT_CLUSTERS_UNTRACKED; - if (le16_to_cpu(p_bpb->bsx.vol_flags) & VOL_DIRTY) { + if (le16_to_cpu(p_boot->vol_flags) & VOL_DIRTY) { sbi->vol_flag |= VOL_DIRTY; exfat_warn(sb, "Volume was not properly unmounted. Some data may be corrupt. Please run fsck."); } @@ -517,7 +517,7 @@ free_alloc_bitmap: free_upcase_table: exfat_free_upcase_table(sbi); free_bh: - brelse(sbi->pbr_bh); + brelse(sbi->boot_bh); return ret; } @@ -608,7 +608,7 @@ put_inode: free_table: exfat_free_upcase_table(sbi); exfat_free_bitmap(sbi); - brelse(sbi->pbr_bh); + brelse(sbi->boot_bh); check_nls_io: unload_nls(sbi->nls_io); From bc42695961cea4045f246b36e6786dcb45ca50fd Mon Sep 17 00:00:00 2001 From: Tetsuhiro Kohada Date: Fri, 29 May 2020 19:14:57 +0900 Subject: [PATCH 064/592] exfat: separate the boot sector analysis Separate the boot sector analysis to read_boot_sector(). And add a check for the fs_name field. Furthermore, add a strict consistency check, because overlapping areas can cause serious corruption. Signed-off-by: Tetsuhiro Kohada Reviewed-by: Sungjong Seo Signed-off-by: Namjae Jeon Signed-off-by: Park Ju Hyung --- exfat_raw.h | 2 ++ super.c | 97 +++++++++++++++++++++++++++++------------------------ 2 files changed, 56 insertions(+), 43 deletions(-) diff --git a/exfat_raw.h b/exfat_raw.h index 07f74190df44..350ce59cc324 100644 --- a/exfat_raw.h +++ b/exfat_raw.h @@ -10,11 +10,13 @@ #define BOOT_SIGNATURE 0xAA55 #define EXBOOT_SIGNATURE 0xAA550000 +#define STR_EXFAT "EXFAT " /* size should be 8 */ #define EXFAT_MAX_FILE_LEN 255 #define VOL_CLEAN 0x0000 #define VOL_DIRTY 0x0002 +#define ERR_MEDIUM 0x0004 #define EXFAT_EOF_CLUSTER 0xFFFFFFFFu #define EXFAT_BAD_CLUSTER 0xFFFFFFF7u diff --git a/super.c b/super.c index e60d28e73ff0..6a1330be5a9a 100644 --- a/super.c +++ b/super.c @@ -366,25 +366,20 @@ static int exfat_read_root(struct inode *inode) return 0; } -static struct boot_sector *exfat_read_boot_with_logical_sector( - struct super_block *sb) +static int exfat_calibrate_blocksize(struct super_block *sb, int logical_sect) { struct exfat_sb_info *sbi = EXFAT_SB(sb); - struct boot_sector *p_boot = (struct boot_sector *)sbi->boot_bh->b_data; - unsigned short logical_sect = 0; - - logical_sect = 1 << p_boot->sect_size_bits; if (!is_power_of_2(logical_sect) || logical_sect < 512 || logical_sect > 4096) { exfat_err(sb, "bogus logical sector size %u", logical_sect); - return NULL; + return -EIO; } if (logical_sect < sb->s_blocksize) { exfat_err(sb, "logical sector size too small for device (logical sector size = %u)", logical_sect); - return NULL; + return -EIO; } if (logical_sect > sb->s_blocksize) { @@ -394,24 +389,20 @@ static struct boot_sector *exfat_read_boot_with_logical_sector( if (!sb_set_blocksize(sb, logical_sect)) { exfat_err(sb, "unable to set blocksize %u", logical_sect); - return NULL; + return -EIO; } sbi->boot_bh = sb_bread(sb, 0); if (!sbi->boot_bh) { exfat_err(sb, "unable to read boot sector (logical sector size = %lu)", sb->s_blocksize); - return NULL; + return -EIO; } - - p_boot = (struct boot_sector *)sbi->boot_bh->b_data; } - return p_boot; + return 0; } -/* mount the file system volume */ -static int __exfat_fill_super(struct super_block *sb) +static int exfat_read_boot_sector(struct super_block *sb) { - int ret; struct boot_sector *p_boot; struct exfat_sb_info *sbi = EXFAT_SB(sb); @@ -424,51 +415,41 @@ static int __exfat_fill_super(struct super_block *sb) exfat_err(sb, "unable to read boot sector"); return -EIO; } - - /* PRB is read */ p_boot = (struct boot_sector *)sbi->boot_bh->b_data; /* check the validity of BOOT */ if (le16_to_cpu((p_boot->signature)) != BOOT_SIGNATURE) { exfat_err(sb, "invalid boot record signature"); - ret = -EINVAL; - goto free_bh; + return -EINVAL; } - - /* check logical sector size */ - p_boot = exfat_read_boot_with_logical_sector(sb); - if (!p_boot) { - ret = -EIO; - goto free_bh; + if (memcmp(p_boot->fs_name, STR_EXFAT, BOOTSEC_FS_NAME_LEN)) { + exfat_err(sb, "invalid fs_name"); /* fs_name may unprintable */ + return -EINVAL; } /* - * res_zero field must be filled with zero to prevent mounting + * must_be_zero field must be filled with zero to prevent mounting * from FAT volume. */ - if (memchr_inv(p_boot->must_be_zero, 0, - sizeof(p_boot->must_be_zero))) { - ret = -EINVAL; - goto free_bh; - } + if (memchr_inv(p_boot->must_be_zero, 0, sizeof(p_boot->must_be_zero))) + return -EINVAL; - p_boot = (struct boot_sector *)p_boot; - if (!p_boot->num_fats) { + if (p_boot->num_fats != 1 && p_boot->num_fats != 2) { exfat_err(sb, "bogus number of FAT structure"); - ret = -EINVAL; - goto free_bh; + return -EINVAL; } sbi->sect_per_clus = 1 << p_boot->sect_per_clus_bits; sbi->sect_per_clus_bits = p_boot->sect_per_clus_bits; - sbi->cluster_size_bits = sbi->sect_per_clus_bits + sb->s_blocksize_bits; + sbi->cluster_size_bits = p_boot->sect_per_clus_bits + + p_boot->sect_size_bits; sbi->cluster_size = 1 << sbi->cluster_size_bits; sbi->num_FAT_sectors = le32_to_cpu(p_boot->fat_length); sbi->FAT1_start_sector = le32_to_cpu(p_boot->fat_offset); - sbi->FAT2_start_sector = p_boot->num_fats == 1 ? - sbi->FAT1_start_sector : - sbi->FAT1_start_sector + sbi->num_FAT_sectors; + sbi->FAT2_start_sector = le32_to_cpu(p_boot->fat_offset); + if (p_boot->num_fats == 2) + sbi->FAT2_start_sector += sbi->num_FAT_sectors; sbi->data_start_sector = le32_to_cpu(p_boot->clu_offset); sbi->num_sectors = le64_to_cpu(p_boot->vol_length); /* because the cluster index starts with 2 */ @@ -483,15 +464,45 @@ static int __exfat_fill_super(struct super_block *sb) sbi->clu_srch_ptr = EXFAT_FIRST_CLUSTER; sbi->used_clusters = EXFAT_CLUSTERS_UNTRACKED; - if (le16_to_cpu(p_boot->vol_flags) & VOL_DIRTY) { - sbi->vol_flag |= VOL_DIRTY; - exfat_warn(sb, "Volume was not properly unmounted. Some data may be corrupt. Please run fsck."); + /* check consistencies */ + if (sbi->num_FAT_sectors << p_boot->sect_size_bits < + sbi->num_clusters * 4) { + exfat_err(sb, "bogus fat length"); + return -EINVAL; } + if (sbi->data_start_sector < + sbi->FAT1_start_sector + sbi->num_FAT_sectors * p_boot->num_fats) { + exfat_err(sb, "bogus data start sector"); + return -EINVAL; + } + if (sbi->vol_flag & VOL_DIRTY) + exfat_warn(sb, "Volume was not properly unmounted. Some data may be corrupt. Please run fsck."); + if (sbi->vol_flag & ERR_MEDIUM) + exfat_warn(sb, "Medium has reported failures. Some data may be lost."); /* exFAT file size is limited by a disk volume size */ sb->s_maxbytes = (u64)(sbi->num_clusters - EXFAT_RESERVED_CLUSTERS) << sbi->cluster_size_bits; + /* check logical sector size */ + if (exfat_calibrate_blocksize(sb, 1 << p_boot->sect_size_bits)) + return -EIO; + + return 0; +} + +/* mount the file system volume */ +static int __exfat_fill_super(struct super_block *sb) +{ + int ret; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + + ret = exfat_read_boot_sector(sb); + if (ret) { + exfat_err(sb, "failed to read boot sector"); + goto free_bh; + } + ret = exfat_create_upcase_table(sb); if (ret) { exfat_err(sb, "failed to load upcase table"); From 5bf4c0bfa76c30a93a2ad037ef9794d6fb1baa68 Mon Sep 17 00:00:00 2001 From: Tetsuhiro Kohada Date: Sun, 31 May 2020 18:30:17 +0900 Subject: [PATCH 065/592] exfat: add boot region verification Add Boot-Regions verification specified in exFAT specification. Note that the checksum type is strongly related to the raw structure, so the'u32 'type is used to clarify the number of bits. Signed-off-by: Tetsuhiro Kohada Reviewed-by: Sungjong Seo Signed-off-by: Namjae Jeon Signed-off-by: Park Ju Hyung --- exfat_fs.h | 1 + misc.c | 14 ++++++++++++++ super.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+) diff --git a/exfat_fs.h b/exfat_fs.h index 911f58b93f3d..8c2a70bfaa10 100644 --- a/exfat_fs.h +++ b/exfat_fs.h @@ -514,6 +514,7 @@ void exfat_set_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts, u8 *tz, __le16 *time, __le16 *date, u8 *time_cs); unsigned short exfat_calc_chksum_2byte(void *data, int len, unsigned short chksum, int type); +u32 exfat_calc_chksum32(void *data, int len, u32 chksum, int type); void exfat_update_bh(struct super_block *sb, struct buffer_head *bh, int sync); void exfat_chain_set(struct exfat_chain *ec, unsigned int dir, unsigned int size, unsigned char flags); diff --git a/misc.c b/misc.c index ab7f88b1f6d3..b82d2dd5bd7c 100644 --- a/misc.c +++ b/misc.c @@ -151,6 +151,20 @@ unsigned short exfat_calc_chksum_2byte(void *data, int len, return chksum; } +u32 exfat_calc_chksum32(void *data, int len, u32 chksum, int type) +{ + int i; + u8 *c = (u8 *)data; + + for (i = 0; i < len; i++, c++) { + if (unlikely(type == CS_BOOT_SECTOR && + (i == 106 || i == 107 || i == 112))) + continue; + chksum = ((chksum << 31) | (chksum >> 1)) + *c; + } + return chksum; +} + void exfat_update_bh(struct super_block *sb, struct buffer_head *bh, int sync) { set_bit(EXFAT_SB_DIRTY, &EXFAT_SB(sb)->s_state); diff --git a/super.c b/super.c index 6a1330be5a9a..405717e4e3ea 100644 --- a/super.c +++ b/super.c @@ -491,6 +491,50 @@ static int exfat_read_boot_sector(struct super_block *sb) return 0; } +static int exfat_verify_boot_region(struct super_block *sb) +{ + struct buffer_head *bh = NULL; + u32 chksum = 0; + __le32 *p_sig, *p_chksum; + int sn, i; + + /* read boot sector sub-regions */ + for (sn = 0; sn < 11; sn++) { + bh = sb_bread(sb, sn); + if (!bh) + return -EIO; + + if (sn != 0 && sn <= 8) { + /* extended boot sector sub-regions */ + p_sig = (__le32 *)&bh->b_data[sb->s_blocksize - 4]; + if (le32_to_cpu(*p_sig) != EXBOOT_SIGNATURE) + exfat_warn(sb, "Invalid exboot-signature(sector = %d): 0x%08x", + sn, le32_to_cpu(*p_sig)); + } + + chksum = exfat_calc_chksum32(bh->b_data, sb->s_blocksize, + chksum, sn ? CS_DEFAULT : CS_BOOT_SECTOR); + brelse(bh); + } + + /* boot checksum sub-regions */ + bh = sb_bread(sb, sn); + if (!bh) + return -EIO; + + for (i = 0; i < sb->s_blocksize; i += sizeof(u32)) { + p_chksum = (__le32 *)&bh->b_data[i]; + if (le32_to_cpu(*p_chksum) != chksum) { + exfat_err(sb, "Invalid boot checksum (boot checksum : 0x%08x, checksum : 0x%08x)", + le32_to_cpu(*p_chksum), chksum); + brelse(bh); + return -EINVAL; + } + } + brelse(bh); + return 0; +} + /* mount the file system volume */ static int __exfat_fill_super(struct super_block *sb) { @@ -503,6 +547,12 @@ static int __exfat_fill_super(struct super_block *sb) goto free_bh; } + ret = exfat_verify_boot_region(sb); + if (ret) { + exfat_err(sb, "invalid boot region"); + goto free_bh; + } + ret = exfat_create_upcase_table(sb); if (ret) { exfat_err(sb, "failed to load upcase table"); From b75517cdd70831882b0dc67b4887b5fc14420b32 Mon Sep 17 00:00:00 2001 From: Tetsuhiro Kohada Date: Fri, 29 May 2020 19:14:59 +0900 Subject: [PATCH 066/592] exfat: standardize checksum calculation To clarify that it is a 16-bit checksum, the parts related to the 16-bit checksum are renamed and change type to u16. Furthermore, replace checksum calculation in exfat_load_upcase_table() with exfat_calc_checksum32(). Signed-off-by: Tetsuhiro Kohada Reviewed-by: Sungjong Seo Signed-off-by: Namjae Jeon Signed-off-by: Park Ju Hyung --- dir.c | 12 ++++++------ exfat_fs.h | 5 ++--- misc.c | 10 ++++------ nls.c | 19 +++++++------------ 4 files changed, 19 insertions(+), 27 deletions(-) diff --git a/dir.c b/dir.c index 2902d285bf20..de43534aa299 100644 --- a/dir.c +++ b/dir.c @@ -491,7 +491,7 @@ int exfat_update_dir_chksum(struct inode *inode, struct exfat_chain *p_dir, int ret = 0; int i, num_entries; sector_t sector; - unsigned short chksum; + u16 chksum; struct exfat_dentry *ep, *fep; struct buffer_head *fbh, *bh; @@ -500,7 +500,7 @@ int exfat_update_dir_chksum(struct inode *inode, struct exfat_chain *p_dir, return -EIO; num_entries = fep->dentry.file.num_ext + 1; - chksum = exfat_calc_chksum_2byte(fep, DENTRY_SIZE, 0, CS_DIR_ENTRY); + chksum = exfat_calc_chksum16(fep, DENTRY_SIZE, 0, CS_DIR_ENTRY); for (i = 1; i < num_entries; i++) { ep = exfat_get_dentry(sb, p_dir, entry + i, &bh, NULL); @@ -508,7 +508,7 @@ int exfat_update_dir_chksum(struct inode *inode, struct exfat_chain *p_dir, ret = -EIO; goto release_fbh; } - chksum = exfat_calc_chksum_2byte(ep, DENTRY_SIZE, chksum, + chksum = exfat_calc_chksum16(ep, DENTRY_SIZE, chksum, CS_DEFAULT); brelse(bh); } @@ -593,8 +593,8 @@ void exfat_update_dir_chksum_with_entry_set(struct exfat_entry_set_cache *es) for (i = 0; i < es->num_entries; i++) { ep = exfat_get_dentry_cached(es, i); - chksum = exfat_calc_chksum_2byte(ep, DENTRY_SIZE, chksum, - chksum_type); + chksum = exfat_calc_chksum16(ep, DENTRY_SIZE, chksum, + chksum_type); chksum_type = CS_DEFAULT; } ep = exfat_get_dentry_cached(es, 0); @@ -1000,7 +1000,7 @@ rewind: } if (entry_type == TYPE_STREAM) { - unsigned short name_hash; + u16 name_hash; if (step != DIRENT_STEP_STRM) { step = DIRENT_STEP_FILE; diff --git a/exfat_fs.h b/exfat_fs.h index 8c2a70bfaa10..595f3117f492 100644 --- a/exfat_fs.h +++ b/exfat_fs.h @@ -137,7 +137,7 @@ struct exfat_dentry_namebuf { struct exfat_uni_name { /* +3 for null and for converting */ unsigned short name[MAX_NAME_LENGTH + 3]; - unsigned short name_hash; + u16 name_hash; unsigned char name_len; }; @@ -512,8 +512,7 @@ void exfat_get_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts, void exfat_truncate_atime(struct timespec64 *ts); void exfat_set_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts, u8 *tz, __le16 *time, __le16 *date, u8 *time_cs); -unsigned short exfat_calc_chksum_2byte(void *data, int len, - unsigned short chksum, int type); +u16 exfat_calc_chksum16(void *data, int len, u16 chksum, int type); u32 exfat_calc_chksum32(void *data, int len, u32 chksum, int type); void exfat_update_bh(struct super_block *sb, struct buffer_head *bh, int sync); void exfat_chain_set(struct exfat_chain *ec, unsigned int dir, diff --git a/misc.c b/misc.c index b82d2dd5bd7c..17d41f3d3709 100644 --- a/misc.c +++ b/misc.c @@ -136,17 +136,15 @@ void exfat_truncate_atime(struct timespec64 *ts) ts->tv_nsec = 0; } -unsigned short exfat_calc_chksum_2byte(void *data, int len, - unsigned short chksum, int type) +u16 exfat_calc_chksum16(void *data, int len, u16 chksum, int type) { int i; - unsigned char *c = (unsigned char *)data; + u8 *c = (u8 *)data; for (i = 0; i < len; i++, c++) { - if (((i == 2) || (i == 3)) && (type == CS_DIR_ENTRY)) + if (unlikely(type == CS_DIR_ENTRY && (i == 2 || i == 3))) continue; - chksum = (((chksum & 1) << 15) | ((chksum & 0xFFFE) >> 1)) + - (unsigned short)*c; + chksum = ((chksum << 15) | (chksum >> 1)) + *c; } return chksum; } diff --git a/nls.c b/nls.c index 1ebda90cbdd7..19321773dd07 100644 --- a/nls.c +++ b/nls.c @@ -527,7 +527,7 @@ static int exfat_utf8_to_utf16(struct super_block *sb, *uniname = '\0'; p_uniname->name_len = unilen; - p_uniname->name_hash = exfat_calc_chksum_2byte(upname, unilen << 1, 0, + p_uniname->name_hash = exfat_calc_chksum16(upname, unilen << 1, 0, CS_DEFAULT); if (p_lossy) @@ -623,7 +623,7 @@ static int exfat_nls_to_ucs2(struct super_block *sb, *uniname = '\0'; p_uniname->name_len = unilen; - p_uniname->name_hash = exfat_calc_chksum_2byte(upname, unilen << 1, 0, + p_uniname->name_hash = exfat_calc_chksum16(upname, unilen << 1, 0, CS_DEFAULT); if (p_lossy) @@ -655,7 +655,8 @@ static int exfat_load_upcase_table(struct super_block *sb, { struct exfat_sb_info *sbi = EXFAT_SB(sb); unsigned int sect_size = sb->s_blocksize; - unsigned int i, index = 0, checksum = 0; + unsigned int i, index = 0; + u32 chksum = 0; int ret; unsigned char skip = false; unsigned short *upcase_table; @@ -681,13 +682,6 @@ static int exfat_load_upcase_table(struct super_block *sb, for (i = 0; i < sect_size && index <= 0xFFFF; i += 2) { unsigned short uni = get_unaligned_le16(bh->b_data + i); - checksum = ((checksum & 1) ? 0x80000000 : 0) + - (checksum >> 1) + - *(((unsigned char *)bh->b_data) + i); - checksum = ((checksum & 1) ? 0x80000000 : 0) + - (checksum >> 1) + - *(((unsigned char *)bh->b_data) + (i + 1)); - if (skip) { index += uni; skip = false; @@ -701,13 +695,14 @@ static int exfat_load_upcase_table(struct super_block *sb, } } brelse(bh); + chksum = exfat_calc_chksum32(bh->b_data, i, chksum, CS_DEFAULT); } - if (index >= 0xFFFF && utbl_checksum == checksum) + if (index >= 0xFFFF && utbl_checksum == chksum) return 0; exfat_err(sb, "failed to load upcase table (idx : 0x%08x, chksum : 0x%08x, utbl_chksum : 0x%08x)", - index, checksum, utbl_checksum); + index, chksum, utbl_checksum); ret = -EINVAL; free_table: exfat_free_upcase_table(sbi); From eb9ac9c11772e8b843e35ffcd2f8819ced8abf54 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Mon, 1 Jun 2020 09:43:49 +0900 Subject: [PATCH 067/592] exfat: remove unnecessary reassignment of p_uniname->name_len kbuild test robot reported : nls.c:531:22: warning: Variable 'p_uniname->name_len' is reassigned a value before the old one has been used. The reassignment of p_uniname->name_len is not needed and remove it. Reported-by: kbuild test robot Signed-off-by: Namjae Jeon Signed-off-by: Park Ju Hyung --- nls.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/nls.c b/nls.c index 19321773dd07..c1ec05695497 100644 --- a/nls.c +++ b/nls.c @@ -514,8 +514,6 @@ static int exfat_utf8_to_utf16(struct super_block *sb, return -ENAMETOOLONG; } - p_uniname->name_len = unilen & 0xFF; - for (i = 0; i < unilen; i++) { if (*uniname < 0x0020 || exfat_wstrchr(bad_uni_chars, *uniname)) From b3d835267748b4769e9550f281b144f987468ad2 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 3 Jun 2020 09:48:36 +0900 Subject: [PATCH 068/592] exfat: fix memory leak in exfat_parse_param() butt3rflyh4ck reported memory leak found by syzkaller. A param->string held by exfat_mount_options. BUG: memory leak unreferenced object 0xffff88801972e090 (size 8): comm "syz-executor.2", pid 16298, jiffies 4295172466 (age 14.060s) hex dump (first 8 bytes): 6b 6f 69 38 2d 75 00 00 koi8-u.. backtrace: [<000000005bfe35d6>] kstrdup+0x36/0x70 mm/util.c:60 [<0000000018ed3277>] exfat_parse_param+0x160/0x5e0 super.c:276 [<000000007680462b>] vfs_parse_fs_param+0x2b4/0x610 fs/fs_context.c:147 [<0000000097c027f2>] vfs_parse_fs_string+0xe6/0x150 fs/fs_context.c:191 [<00000000371bf78f>] generic_parse_monolithic+0x16f/0x1f0 fs/fs_context.c:231 [<000000005ce5eb1b>] do_new_mount fs/namespace.c:2812 [inline] [<000000005ce5eb1b>] do_mount+0x12bb/0x1b30 fs/namespace.c:3141 [<00000000b642040c>] __do_sys_mount fs/namespace.c:3350 [inline] [<00000000b642040c>] __se_sys_mount fs/namespace.c:3327 [inline] [<00000000b642040c>] __x64_sys_mount+0x18f/0x230 fs/namespace.c:3327 [<000000003b024e98>] do_syscall_64+0xf6/0x7d0 arch/x86/entry/common.c:295 [<00000000ce2b698c>] entry_SYSCALL_64_after_hwframe+0x49/0xb3 exfat_free() should call exfat_free_iocharset(), to prevent a leak in case we fail after parsing iocharset= but before calling get_tree_bdev(). Additionally, there's no point copying param->string in exfat_parse_param() - just steal it, leaving NULL in param->string. That's independent from the leak or fix thereof - it's simply avoiding an extra copy. Fixes: 719c1e182916 ("exfat: add super block operations") Cc: stable@vger.kernel.org # v5.7 Reported-by: butt3rflyh4ck Signed-off-by: Al Viro Signed-off-by: Namjae Jeon Signed-off-by: Park Ju Hyung --- super.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/super.c b/super.c index 405717e4e3ea..e650e65536f8 100644 --- a/super.c +++ b/super.c @@ -273,9 +273,8 @@ static int exfat_parse_param(struct fs_context *fc, struct fs_parameter *param) break; case Opt_charset: exfat_free_iocharset(sbi); - opts->iocharset = kstrdup(param->string, GFP_KERNEL); - if (!opts->iocharset) - return -ENOMEM; + opts->iocharset = param->string; + param->string = NULL; break; case Opt_errors: opts->errors = result.uint_32; @@ -686,7 +685,12 @@ static int exfat_get_tree(struct fs_context *fc) static void exfat_free(struct fs_context *fc) { - kfree(fc->s_fs_info); + struct exfat_sb_info *sbi = fc->s_fs_info; + + if (sbi) { + exfat_free_iocharset(sbi); + kfree(sbi); + } } static const struct fs_context_operations exfat_context_ops = { From ee70bb7e3ee076e80c0e131d38b3a22d32c4f917 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Thu, 4 Jun 2020 08:05:31 +0900 Subject: [PATCH 069/592] exfat: fix incorrect update of stream entry in __exfat_truncate() At truncate, there is a problem of incorrect updating in the file entry pointer instead of stream entry. This will cause the problem of overwriting the time field of the file entry to new_size. Fix it to update stream entry. Fixes: 98d917047e8b ("exfat: add file operations") Cc: stable@vger.kernel.org # v5.7 Signed-off-by: Namjae Jeon Signed-off-by: Park Ju Hyung --- file.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/file.c b/file.c index 8e3f0eef45d7..fce03f318787 100644 --- a/file.c +++ b/file.c @@ -171,11 +171,11 @@ int __exfat_truncate(struct inode *inode, loff_t new_size) /* File size should be zero if there is no cluster allocated */ if (ei->start_clu == EXFAT_EOF_CLUSTER) { - ep->dentry.stream.valid_size = 0; - ep->dentry.stream.size = 0; + ep2->dentry.stream.valid_size = 0; + ep2->dentry.stream.size = 0; } else { - ep->dentry.stream.valid_size = cpu_to_le64(new_size); - ep->dentry.stream.size = ep->dentry.stream.valid_size; + ep2->dentry.stream.valid_size = cpu_to_le64(new_size); + ep2->dentry.stream.size = ep->dentry.stream.valid_size; } if (new_size == 0) { From 3944ed144aa34a043a8cd153d40622c9f7108ee4 Mon Sep 17 00:00:00 2001 From: "hyeongseok.kim" Date: Thu, 4 Jun 2020 13:54:28 +0900 Subject: [PATCH 070/592] exfat: fix range validation error in alloc and free cluster There is check error in range condition that can never be entered even with invalid input. Replace incorrent checking code with already existing valid checker. Signed-off-by: hyeongseok.kim Acked-by: Sungjong Seo Signed-off-by: Namjae Jeon Signed-off-by: Park Ju Hyung --- fatent.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fatent.c b/fatent.c index 267e5e09eb13..4e5c5c9c0f2d 100644 --- a/fatent.c +++ b/fatent.c @@ -169,7 +169,7 @@ int exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain) return 0; /* check cluster validation */ - if (p_chain->dir < 2 && p_chain->dir >= sbi->num_clusters) { + if (!is_valid_cluster(sbi, p_chain->dir)) { exfat_err(sb, "invalid start cluster (%u)", p_chain->dir); return -EIO; } @@ -346,7 +346,7 @@ int exfat_alloc_cluster(struct inode *inode, unsigned int num_alloc, } /* check cluster validation */ - if (hint_clu < EXFAT_FIRST_CLUSTER && hint_clu >= sbi->num_clusters) { + if (!is_valid_cluster(sbi, hint_clu)) { exfat_err(sb, "hint_cluster is invalid (%u)", hint_clu); hint_clu = EXFAT_FIRST_CLUSTER; From 94f594f5f3fb7c7945122960955a346886ea1b97 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 8 Jun 2020 17:16:29 +0300 Subject: [PATCH 071/592] exfat: Fix potential use after free in exfat_load_upcase_table() This code calls brelse(bh) and then dereferences "bh" on the next line resulting in a possible use after free. The brelse() should just be moved down a line. Fixes: b676fdbcf4c8 ("exfat: standardize checksum calculation") Signed-off-by: Dan Carpenter Signed-off-by: Namjae Jeon Signed-off-by: Park Ju Hyung --- nls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nls.c b/nls.c index c1ec05695497..57b5a7a4d1f7 100644 --- a/nls.c +++ b/nls.c @@ -692,8 +692,8 @@ static int exfat_load_upcase_table(struct super_block *sb, index++; } } - brelse(bh); chksum = exfat_calc_chksum32(bh->b_data, i, chksum, CS_DEFAULT); + brelse(bh); } if (index >= 0xFFFF && utbl_checksum == chksum) From 19bcc82723cbdf50e9e4a5144bcd83da983c24dc Mon Sep 17 00:00:00 2001 From: Park Ju Hyung Date: Tue, 13 Aug 2019 03:40:47 +0900 Subject: [PATCH 072/592] Add GPL 2.0 license Signed-off-by: Park Ju Hyung --- LICENSE | 359 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 359 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000000..ff0812fd89cc --- /dev/null +++ b/LICENSE @@ -0,0 +1,359 @@ +Valid-License-Identifier: GPL-2.0 +Valid-License-Identifier: GPL-2.0-only +Valid-License-Identifier: GPL-2.0+ +Valid-License-Identifier: GPL-2.0-or-later +SPDX-URL: https://spdx.org/licenses/GPL-2.0.html +Usage-Guide: + To use this license in source code, put one of the following SPDX + tag/value pairs into a comment according to the placement + guidelines in the licensing rules documentation. + For 'GNU General Public License (GPL) version 2 only' use: + SPDX-License-Identifier: GPL-2.0 + or + SPDX-License-Identifier: GPL-2.0-only + For 'GNU General Public License (GPL) version 2 or any later version' use: + SPDX-License-Identifier: GPL-2.0+ + or + SPDX-License-Identifier: GPL-2.0-or-later +License-Text: + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. From 249ef5e0785ef99519abcafb8af5755a67f3cbcd Mon Sep 17 00:00:00 2001 From: Park Ju Hyung Date: Fri, 26 Jun 2020 04:10:09 +0900 Subject: [PATCH 073/592] exfat: allow building externally Signed-off-by: Park Ju Hyung --- Makefile | 37 ++++++++++++++++++++++++++++++++++++- config.h | 13 +++++++++++++ exfat_fs.h | 2 ++ 3 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 config.h diff --git a/Makefile b/Makefile index ed51926a4971..1baf3530db92 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,42 @@ # # Makefile for the linux exFAT filesystem support. # + +ifneq ($(KERNELRELEASE),) +# Called from inline kernel build +# DKMS_DEFINE obj-$(CONFIG_EXFAT_FS) += exfat.o -exfat-y := inode.o namei.o dir.o super.o fatent.o cache.o nls.o misc.o \ +exfat-objs := inode.o namei.o dir.o super.o fatent.o cache.o nls.o misc.o \ file.o balloc.o +else +# Called from external kernel module build + +KERNELRELEASE ?= $(shell uname -r) +KDIR ?= /lib/modules/${KERNELRELEASE}/build +MDIR ?= /lib/modules/${KERNELRELEASE} +PWD := $(shell pwd) + +export CONFIG_EXFAT_FS := m + +all: + $(MAKE) -C $(KDIR) M=$(PWD) modules + +clean: + $(MAKE) -C $(KDIR) M=$(PWD) clean + +help: + $(MAKE) -C $(KDIR) M=$(PWD) help + +install: exfat.ko + rm -f ${MDIR}/kernel/fs/exfat/exfat.ko + install -m644 -b -D exfat.ko ${MDIR}/kernel/fs/exfat/exfat.ko + depmod -aq + +uninstall: + rm -rf ${MDIR}/kernel/fs/exfat + depmod -aq + +endif + +.PHONY : all clean install uninstall diff --git a/config.h b/config.h new file mode 100644 index 000000000000..59bf2bea3386 --- /dev/null +++ b/config.h @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + */ + +#ifndef _EXFAT_CONFIG_H +#define _EXFAT_CONFIG_H + +#ifndef CONFIG_EXFAT_DEFAULT_IOCHARSET /* if Kconfig lacked iocharset */ +#define CONFIG_EXFAT_DEFAULT_IOCHARSET "utf8" +#endif + +#endif /* _EXFAT_CONFIG_H */ diff --git a/exfat_fs.h b/exfat_fs.h index 595f3117f492..aa8f0e5893fc 100644 --- a/exfat_fs.h +++ b/exfat_fs.h @@ -10,6 +10,8 @@ #include #include +#include "config.h" + #define EXFAT_SUPER_MAGIC 0x2011BAB0UL #define EXFAT_ROOT_INO 1 From 5d72b8948377396446a33c8c9012d0badcf9a025 Mon Sep 17 00:00:00 2001 From: Park Ju Hyung Date: Tue, 13 Aug 2019 04:28:39 +0900 Subject: [PATCH 074/592] exfat: add gitignore Signed-off-by: Park Ju Hyung --- .gitignore | 147 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000000..2030c7a4d2f8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,147 @@ +# +# NOTE! Don't add files that are generated in specific +# subdirectories here. Add them in the ".gitignore" file +# in that subdirectory instead. +# +# NOTE! Please use 'git ls-files -i --exclude-standard' +# command after changing this file, to see if there are +# any tracked files which get ignored after the change. +# +# Normal rules (sorted alphabetically) +# +.* +*.a +*.asn1.[ch] +*.bin +*.bz2 +*.c.[012]*.* +*.dt.yaml +*.dtb +*.dtb.S +*.dwo +*.elf +*.gcno +*.gz +*.i +*.ko +*.lex.c +*.ll +*.lst +*.lz4 +*.lzma +*.lzo +*.mod +*.mod.c +*.o +*.o.* +*.order +*.patch +*.s +*.so +*.so.dbg +*.su +*.symtypes +*.tab.[ch] +*.tar +*.xz +Module.symvers +modules.builtin + +# +# Top-level generic files +# +/tags +/TAGS +/linux +/vmlinux +/vmlinux.32 +/vmlinux-gdb.py +/vmlinuz +/System.map +/Module.markers +/modules.builtin.modinfo + +# +# RPM spec file (make rpm-pkg) +# +/*.spec + +# +# Debian directory (make deb-pkg) +# +/debian/ + +# +# Snap directory (make snap-pkg) +# +/snap/ + +# +# tar directory (make tar*-pkg) +# +/tar-install/ + +# +# We don't want to ignore the following even if they are dot-files +# +!.clang-format +!.cocciconfig +!.get_maintainer.ignore +!.gitattributes +!.gitignore +!.mailmap + +# +# Generated include files +# +/include/config/ +/include/generated/ +/include/ksym/ +/arch/*/include/generated/ + +# stgit generated dirs +patches-* + +# quilt's files +patches +series + +# cscope files +cscope.* +ncscope.* + +# gnu global files +GPATH +GRTAGS +GSYMS +GTAGS + +# id-utils files +ID + +*.orig +*~ +\#*# + +# +# Leavings from module signing +# +extra_certificates +signing_key.pem +signing_key.priv +signing_key.x509 +x509.genkey + +# Kconfig presets +/all.config +/alldef.config +/allmod.config +/allno.config +/allrandom.config +/allyes.config + +# Kdevelop4 +*.kdev4 + +# Clang's compilation database file +/compile_commands.json From 0b27bc5e152071767137951f3f1d387c925e8b72 Mon Sep 17 00:00:00 2001 From: Park Ju Hyung Date: Sat, 27 Jun 2020 02:49:41 +0900 Subject: [PATCH 075/592] exfat: remove use of fs_parser This is a major headache for backporting to older kernels Signed-off-by: Park Ju Hyung --- super.c | 206 +++++++++++++++++++++++++++++++++----------------------- 1 file changed, 123 insertions(+), 83 deletions(-) diff --git a/super.c b/super.c index e650e65536f8..f8e61117f0de 100644 --- a/super.c +++ b/super.c @@ -3,8 +3,6 @@ * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. */ -#include -#include #include #include #include @@ -17,10 +15,13 @@ #include #include #include +#include #include "exfat_raw.h" #include "exfat_fs.h" +static int exfat_init_sb_info(struct super_block *sb); + static char exfat_default_iocharset[] = CONFIG_EXFAT_DEFAULT_IOCHARSET; static struct kmem_cache *exfat_inode_cachep; @@ -200,7 +201,9 @@ enum { Opt_fmask, Opt_allow_utime, Opt_charset, - Opt_errors, + Opt_err_cont, + Opt_err_panic, + Opt_err_ro, Opt_discard, Opt_time_offset, @@ -211,90 +214,96 @@ enum { Opt_codepage, }; -static const struct constant_table exfat_param_enums[] = { - { "continue", EXFAT_ERRORS_CONT }, - { "panic", EXFAT_ERRORS_PANIC }, - { "remount-ro", EXFAT_ERRORS_RO }, - {} +static const match_table_t exfat_tokens = { + {Opt_uid, "uid=%u"}, + {Opt_gid, "gid=%u"}, + {Opt_umask, "umask=%o"}, + {Opt_dmask, "dmask=%o"}, + {Opt_fmask, "fmask=%o"}, + {Opt_allow_utime, "allow_utime=%o"}, + {Opt_charset, "iocharset=%s"}, + {Opt_err_cont, "errors=continue"}, + {Opt_err_panic, "errors=panic"}, + {Opt_err_ro, "errors=remount-ro"}, + {Opt_discard, "discard"}, + {Opt_time_offset, "time_offset=%d"}, + + /* Deprecated options */ + {Opt_utf8, "utf8"}, + {Opt_debug, "debug"}, + {Opt_namecase, "namecase=%u"}, + {Opt_codepage, "codepage=%u"}, }; -static const struct fs_parameter_spec exfat_parameters[] = { - fsparam_u32("uid", Opt_uid), - fsparam_u32("gid", Opt_gid), - fsparam_u32oct("umask", Opt_umask), - fsparam_u32oct("dmask", Opt_dmask), - fsparam_u32oct("fmask", Opt_fmask), - fsparam_u32oct("allow_utime", Opt_allow_utime), - fsparam_string("iocharset", Opt_charset), - fsparam_enum("errors", Opt_errors, exfat_param_enums), - fsparam_flag("discard", Opt_discard), - fsparam_s32("time_offset", Opt_time_offset), - __fsparam(NULL, "utf8", Opt_utf8, fs_param_deprecated, - NULL), - __fsparam(NULL, "debug", Opt_debug, fs_param_deprecated, - NULL), - __fsparam(fs_param_is_u32, "namecase", Opt_namecase, - fs_param_deprecated, NULL), - __fsparam(fs_param_is_u32, "codepage", Opt_codepage, - fs_param_deprecated, NULL), - {} -}; - -static int exfat_parse_param(struct fs_context *fc, struct fs_parameter *param) +static int __exfat_parse_option(struct super_block *sb, char *p, substring_t *args, int token, int silent) { - struct exfat_sb_info *sbi = fc->s_fs_info; + struct exfat_sb_info *sbi = sb->s_fs_info; struct exfat_mount_options *opts = &sbi->options; - struct fs_parse_result result; - int opt; + int option; + char *tmpstr; - opt = fs_parse(fc, exfat_parameters, param, &result); - if (opt < 0) - return opt; - - switch (opt) { + switch (token) { case Opt_uid: - opts->fs_uid = make_kuid(current_user_ns(), result.uint_32); + if (match_int(&args[0], &option)) + return -EINVAL; + opts->fs_uid = make_kuid(current_user_ns(), option); break; case Opt_gid: - opts->fs_gid = make_kgid(current_user_ns(), result.uint_32); + if (match_int(&args[0], &option)) + return -EINVAL; + opts->fs_gid = make_kgid(current_user_ns(), option); break; case Opt_umask: - opts->fs_fmask = result.uint_32; - opts->fs_dmask = result.uint_32; - break; case Opt_dmask: - opts->fs_dmask = result.uint_32; - break; case Opt_fmask: - opts->fs_fmask = result.uint_32; + if (match_octal(&args[0], &option)) + return -EINVAL; + if (token != Opt_dmask) + opts->fs_fmask = option; + if (token != Opt_fmask) + opts->fs_dmask = option; break; case Opt_allow_utime: - opts->allow_utime = result.uint_32 & 0022; + if (match_octal(&args[0], &option)) + return -EINVAL; + opts->allow_utime = option & (S_IWGRP | S_IWOTH); break; case Opt_charset: exfat_free_iocharset(sbi); - opts->iocharset = param->string; - param->string = NULL; + tmpstr = match_strdup(&args[0]); + if (!tmpstr) + return -ENOMEM; + opts->iocharset = tmpstr; break; - case Opt_errors: - opts->errors = result.uint_32; + case Opt_err_cont: + opts->errors = EXFAT_ERRORS_CONT; + break; + case Opt_err_panic: + opts->errors = EXFAT_ERRORS_PANIC; + break; + case Opt_err_ro: + opts->errors = EXFAT_ERRORS_RO; break; case Opt_discard: opts->discard = 1; break; case Opt_time_offset: + if (match_int(&args[0], &option)) + return -EINVAL; /* * Make the limit 24 just in case someone invents something * unusual. */ - if (result.int_32 < -24 * 60 || result.int_32 > 24 * 60) + if (option < -24 * 60 || option > 24 * 60) return -EINVAL; - opts->time_offset = result.int_32; + opts->time_offset = option; break; case Opt_utf8: case Opt_debug: case Opt_namecase: case Opt_codepage: + if (!silent) + exfat_warn(sb, "deprecated mount option \"%s\" ", p); break; default: return -EINVAL; @@ -303,6 +312,37 @@ static int exfat_parse_param(struct fs_context *fc, struct fs_parameter *param) return 0; } +static int exfat_parse_options(struct super_block *sb, char *options, int silent, + struct exfat_mount_options *opts) +{ + char *p; + substring_t args[MAX_OPT_ARGS]; + int ret; + + if (!options) + goto out; + + while ((p = strsep(&options, ",")) != NULL) { + int token; + + if (!*p) + continue; + token = match_token(p, exfat_tokens, args); + ret = __exfat_parse_option(sb, p, args, token, silent); + if (ret < 0) { + if (ret == -EINVAL && !silent) { + exfat_msg(sb, KERN_ERR, + "unrecognized mount option \"%s\" " + "or missing value", p); + } + return ret; + } + } + +out: + return 0; +} + static void exfat_hash_init(struct super_block *sb) { struct exfat_sb_info *sbi = EXFAT_SB(sb); @@ -581,13 +621,22 @@ free_bh: return ret; } -static int exfat_fill_super(struct super_block *sb, struct fs_context *fc) +static int exfat_fill_super(struct super_block *sb, void *data, int silent) { - struct exfat_sb_info *sbi = sb->s_fs_info; - struct exfat_mount_options *opts = &sbi->options; + struct exfat_sb_info *sbi; + struct exfat_mount_options *opts; struct inode *root_inode; int err; + err = exfat_init_sb_info(sb); + if (err) { + exfat_err(sb, "failed to initialize superblock info"); + goto failed; + } + + sbi = sb->s_fs_info; + opts = &sbi->options; + if (opts->allow_utime == (unsigned short)-1) opts->allow_utime = ~opts->fs_dmask & 0022; @@ -608,6 +657,12 @@ static int exfat_fill_super(struct super_block *sb, struct fs_context *fc) sb->s_time_min = EXFAT_MIN_TIMESTAMP_SECS; sb->s_time_max = EXFAT_MAX_TIMESTAMP_SECS; + err = exfat_parse_options(sb, data, silent, &sbi->options); + if (err) { + exfat_err(sb, "failed to parse options"); + goto check_nls_io; + } + err = __exfat_fill_super(sb); if (err) { exfat_err(sb, "failed to recognize exfat type"); @@ -675,31 +730,12 @@ check_nls_io: exfat_free_iocharset(sbi); sb->s_fs_info = NULL; kfree(sbi); + +failed: return err; } -static int exfat_get_tree(struct fs_context *fc) -{ - return get_tree_bdev(fc, exfat_fill_super); -} - -static void exfat_free(struct fs_context *fc) -{ - struct exfat_sb_info *sbi = fc->s_fs_info; - - if (sbi) { - exfat_free_iocharset(sbi); - kfree(sbi); - } -} - -static const struct fs_context_operations exfat_context_ops = { - .parse_param = exfat_parse_param, - .get_tree = exfat_get_tree, - .free = exfat_free, -}; - -static int exfat_init_fs_context(struct fs_context *fc) +static int exfat_init_sb_info(struct super_block *sb) { struct exfat_sb_info *sbi; @@ -719,16 +755,20 @@ static int exfat_init_fs_context(struct fs_context *fc) sbi->options.iocharset = exfat_default_iocharset; sbi->options.errors = EXFAT_ERRORS_RO; - fc->s_fs_info = sbi; - fc->ops = &exfat_context_ops; + sb->s_fs_info = sbi; return 0; } +static struct dentry *exfat_fs_mount(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data) +{ + return mount_bdev(fs_type, flags, dev_name, data, exfat_fill_super); +} + static struct file_system_type exfat_fs_type = { .owner = THIS_MODULE, .name = "exfat", - .init_fs_context = exfat_init_fs_context, - .parameters = exfat_parameters, + .mount = exfat_fs_mount, .kill_sb = kill_block_super, .fs_flags = FS_REQUIRES_DEV, }; From ef64ed8ecf82f48a4bce24061df21237ac2fca8a Mon Sep 17 00:00:00 2001 From: Park Ju Hyung Date: Sat, 27 Jun 2020 06:04:14 +0900 Subject: [PATCH 076/592] exfat: add an empty compat.h Signed-off-by: Park Ju Hyung --- compat.h | 11 +++++++++++ exfat_fs.h | 1 + 2 files changed, 12 insertions(+) create mode 100644 compat.h diff --git a/compat.h b/compat.h new file mode 100644 index 000000000000..89e58e658be2 --- /dev/null +++ b/compat.h @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + */ + +#ifndef _EXFAT_COMPAT_H +#define _EXFAT_COMPAT_H + +#include + +#endif /* _EXFAT_COMPAT_H */ diff --git a/exfat_fs.h b/exfat_fs.h index aa8f0e5893fc..2700fbb2b068 100644 --- a/exfat_fs.h +++ b/exfat_fs.h @@ -11,6 +11,7 @@ #include #include "config.h" +#include "compat.h" #define EXFAT_SUPER_MAGIC 0x2011BAB0UL #define EXFAT_ROOT_INO 1 From a3e3e294f77b99c20bcfabe9b1364799dbb4f370 Mon Sep 17 00:00:00 2001 From: Park Ju Hyung Date: Sat, 27 Jun 2020 06:07:22 +0900 Subject: [PATCH 077/592] exfat: guard timestamp range support This is supported from v5.4+ Signed-off-by: Park Ju Hyung --- super.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/super.c b/super.c index f8e61117f0de..564de06269bc 100644 --- a/super.c +++ b/super.c @@ -654,8 +654,10 @@ static int exfat_fill_super(struct super_block *sb, void *data, int silent) sb->s_op = &exfat_sops; sb->s_time_gran = 10 * NSEC_PER_MSEC; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) sb->s_time_min = EXFAT_MIN_TIMESTAMP_SECS; sb->s_time_max = EXFAT_MAX_TIMESTAMP_SECS; +#endif err = exfat_parse_options(sb, data, silent, &sbi->options); if (err) { From d30b3d0777bf2a5b8c64dc706137683a9ae308e7 Mon Sep 17 00:00:00 2001 From: Park Ju Hyung Date: Sat, 27 Jun 2020 06:08:36 +0900 Subject: [PATCH 078/592] exfat: use sops->free_inode only on v5.2+ Signed-off-by: Park Ju Hyung --- super.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/super.c b/super.c index 564de06269bc..90e23615256f 100644 --- a/super.c +++ b/super.c @@ -184,7 +184,11 @@ static void exfat_free_inode(struct inode *inode) static const struct super_operations exfat_sops = { .alloc_inode = exfat_alloc_inode, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0) .free_inode = exfat_free_inode, +#else + .destroy_inode = exfat_free_inode, +#endif .write_inode = exfat_write_inode, .evict_inode = exfat_evict_inode, .put_super = exfat_put_super, From 0d9a33c3a6171e65585b7593bb50aa0cf8fd6796 Mon Sep 17 00:00:00 2001 From: Park Ju Hyung Date: Sat, 27 Jun 2020 06:10:46 +0900 Subject: [PATCH 079/592] exfat: handle kernel versions without exported iversion.h Signed-off-by: Park Ju Hyung --- compat.h | 10 ++++++++++ inode.c | 1 - namei.c | 1 - super.c | 1 - 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/compat.h b/compat.h index 89e58e658be2..3d531730912a 100644 --- a/compat.h +++ b/compat.h @@ -8,4 +8,14 @@ #include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0) +#include +#else +#define inode_inc_iversion(inode) (inode->i_version++) +#define inode_query_iversion(inode) (inode->i_version) +#define inode_eq_iversion(inode, version) (inode->i_version == version) +#define inode_peek_iversion_raw(inode) (inode->i_version) +#define inode_set_iversion(inode, val) (inode->i_version = val) +#endif + #endif /* _EXFAT_COMPAT_H */ diff --git a/inode.c b/inode.c index ef7cf7a6d187..5f3d260a17c1 100644 --- a/inode.c +++ b/inode.c @@ -12,7 +12,6 @@ #include #include #include -#include #include "exfat_raw.h" #include "exfat_fs.h" diff --git a/namei.c b/namei.c index 5b0f35329d63..f79453fb4b90 100644 --- a/namei.c +++ b/namei.c @@ -3,7 +3,6 @@ * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. */ -#include #include #include #include diff --git a/super.c b/super.c index 90e23615256f..8e62e7fdba3d 100644 --- a/super.c +++ b/super.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include From 172ebff1a51db9f1ab676861fdab549f4e9fe81b Mon Sep 17 00:00:00 2001 From: Park Ju Hyung Date: Sat, 27 Jun 2020 06:13:26 +0900 Subject: [PATCH 080/592] exfat: handle older kernels without SB_* renamed flags Signed-off-by: Park Ju Hyung --- compat.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/compat.h b/compat.h index 3d531730912a..f959465230b8 100644 --- a/compat.h +++ b/compat.h @@ -18,4 +18,21 @@ #define inode_set_iversion(inode, val) (inode->i_version = val) #endif +/* MS flags were renamed to SB on v4.15 */ +#ifndef SB_NODIRATIME +#define SB_NODIRATIME MS_NODIRATIME +#endif + +#ifndef SB_RDONLY +#define SB_RDONLY MS_RDONLY +#endif + +#ifndef SB_SYNCHRONOUS +#define SB_SYNCHRONOUS MS_SYNCHRONOUS +#endif + +#ifndef sb_rdonly +#define sb_rdonly(sb) ((sb)->s_flags & SB_RDONLY) +#endif + #endif /* _EXFAT_COMPAT_H */ From 78e26150118e3b7fbc2ebe172bcd27ff474d1dd8 Mon Sep 17 00:00:00 2001 From: Park Ju Hyung Date: Sat, 27 Jun 2020 06:13:55 +0900 Subject: [PATCH 081/592] exfat: handle older kernels with different getattr() vfs interface Signed-off-by: Park Ju Hyung --- exfat_fs.h | 4 ++++ file.c | 13 +++++++++++++ 2 files changed, 17 insertions(+) diff --git a/exfat_fs.h b/exfat_fs.h index 2700fbb2b068..749c5303bb15 100644 --- a/exfat_fs.h +++ b/exfat_fs.h @@ -421,8 +421,12 @@ extern const struct file_operations exfat_file_operations; int __exfat_truncate(struct inode *inode, loff_t new_size); void exfat_truncate(struct inode *inode, loff_t size); int exfat_setattr(struct dentry *dentry, struct iattr *attr); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) int exfat_getattr(const struct path *path, struct kstat *stat, unsigned int request_mask, unsigned int query_flags); +#else +int exfat_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat); +#endif /* namei.c */ extern const struct dentry_operations exfat_dentry_ops; diff --git a/file.c b/file.c index fce03f318787..a99baac97c13 100644 --- a/file.c +++ b/file.c @@ -265,6 +265,7 @@ write_size: mutex_unlock(&sbi->s_lock); } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) int exfat_getattr(const struct path *path, struct kstat *stat, unsigned int request_mask, unsigned int query_flags) { @@ -279,6 +280,18 @@ int exfat_getattr(const struct path *path, struct kstat *stat, stat->blksize = EXFAT_SB(inode->i_sb)->cluster_size; return 0; } +#else +int exfat_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) +{ + struct inode *inode = dentry->d_inode; + + generic_fillattr(inode, stat); + exfat_truncate_atime(&stat->atime); + stat->blksize = EXFAT_SB(inode->i_sb)->cluster_size; + + return 0; +} +#endif int exfat_setattr(struct dentry *dentry, struct iattr *attr) { From 53500c78d0e9475cdbab529b1aedcdae3afe8a4e Mon Sep 17 00:00:00 2001 From: Park Ju Hyung Date: Sat, 27 Jun 2020 06:37:31 +0900 Subject: [PATCH 082/592] exfat: include exfat_raw.h to exfat_fs.h exfat_fs.h is unusable without exfat_raw.h. Include it directly. Signed-off-by: Park Ju Hyung --- balloc.c | 1 - cache.c | 1 - dir.c | 1 - exfat_fs.h | 1 + fatent.c | 1 - file.c | 1 - inode.c | 1 - misc.c | 1 - namei.c | 1 - nls.c | 1 - super.c | 1 - 11 files changed, 1 insertion(+), 10 deletions(-) diff --git a/balloc.c b/balloc.c index 4055eb00ea9b..d8c398b005b5 100644 --- a/balloc.c +++ b/balloc.c @@ -7,7 +7,6 @@ #include #include -#include "exfat_raw.h" #include "exfat_fs.h" static const unsigned char free_bit[] = { diff --git a/cache.c b/cache.c index 03d0824fc368..47882395a884 100644 --- a/cache.c +++ b/cache.c @@ -14,7 +14,6 @@ #include #include -#include "exfat_raw.h" #include "exfat_fs.h" #define EXFAT_CACHE_VALID 0 diff --git a/dir.c b/dir.c index de43534aa299..71de965cc6a1 100644 --- a/dir.c +++ b/dir.c @@ -7,7 +7,6 @@ #include #include -#include "exfat_raw.h" #include "exfat_fs.h" static int exfat_extract_uni_name(struct exfat_dentry *ep, diff --git a/exfat_fs.h b/exfat_fs.h index 749c5303bb15..b004a2b45b5a 100644 --- a/exfat_fs.h +++ b/exfat_fs.h @@ -12,6 +12,7 @@ #include "config.h" #include "compat.h" +#include "exfat_raw.h" #define EXFAT_SUPER_MAGIC 0x2011BAB0UL #define EXFAT_ROOT_INO 1 diff --git a/fatent.c b/fatent.c index 4e5c5c9c0f2d..317c966e380b 100644 --- a/fatent.c +++ b/fatent.c @@ -7,7 +7,6 @@ #include #include -#include "exfat_raw.h" #include "exfat_fs.h" static int exfat_mirror_bh(struct super_block *sb, sector_t sec, diff --git a/file.c b/file.c index a99baac97c13..db2cdf37a015 100644 --- a/file.c +++ b/file.c @@ -7,7 +7,6 @@ #include #include -#include "exfat_raw.h" #include "exfat_fs.h" static int exfat_cont_expand(struct inode *inode, loff_t size) diff --git a/inode.c b/inode.c index 5f3d260a17c1..20dddebfd706 100644 --- a/inode.c +++ b/inode.c @@ -13,7 +13,6 @@ #include #include -#include "exfat_raw.h" #include "exfat_fs.h" static int __exfat_write_inode(struct inode *inode, int sync) diff --git a/misc.c b/misc.c index 17d41f3d3709..93e05ace37bc 100644 --- a/misc.c +++ b/misc.c @@ -11,7 +11,6 @@ #include #include -#include "exfat_raw.h" #include "exfat_fs.h" /* diff --git a/namei.c b/namei.c index f79453fb4b90..c15d1283f120 100644 --- a/namei.c +++ b/namei.c @@ -8,7 +8,6 @@ #include #include -#include "exfat_raw.h" #include "exfat_fs.h" static inline unsigned long exfat_d_version(struct dentry *dentry) diff --git a/nls.c b/nls.c index 57b5a7a4d1f7..d48060a29702 100644 --- a/nls.c +++ b/nls.c @@ -8,7 +8,6 @@ #include #include -#include "exfat_raw.h" #include "exfat_fs.h" /* Upcase tabel macro */ diff --git a/super.c b/super.c index 8e62e7fdba3d..eb362fece5dd 100644 --- a/super.c +++ b/super.c @@ -16,7 +16,6 @@ #include #include -#include "exfat_raw.h" #include "exfat_fs.h" static int exfat_init_sb_info(struct super_block *sb); From 0db4ba798535a6a05ae41c160a21137459c6fe31 Mon Sep 17 00:00:00 2001 From: Park Ju Hyung Date: Tue, 29 Oct 2019 16:23:17 +0900 Subject: [PATCH 083/592] exfat: implement "quiet" option for setattr Signed-off-by: Park Ju Hyung --- exfat_fs.h | 2 ++ file.c | 13 +++++++++++-- super.c | 7 +++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/exfat_fs.h b/exfat_fs.h index b004a2b45b5a..7a3be6fcb552 100644 --- a/exfat_fs.h +++ b/exfat_fs.h @@ -207,6 +207,8 @@ struct exfat_mount_options { unsigned short allow_utime; /* charset for filename input/display */ char *iocharset; + /* fake return success on setattr(e.g. chmods/chowns) */ + unsigned char quiet; /* on error: continue, panic, remount-ro */ enum exfat_error_mode errors; unsigned utf8:1, /* Use of UTF-8 character set */ diff --git a/file.c b/file.c index db2cdf37a015..316a9fb29b86 100644 --- a/file.c +++ b/file.c @@ -303,7 +303,7 @@ int exfat_setattr(struct dentry *dentry, struct iattr *attr) attr->ia_size > i_size_read(inode)) { error = exfat_cont_expand(inode, attr->ia_size); if (error || attr->ia_valid == ATTR_SIZE) - return error; + goto out; attr->ia_valid &= ~ATTR_SIZE; } @@ -317,8 +317,11 @@ int exfat_setattr(struct dentry *dentry, struct iattr *attr) error = setattr_prepare(dentry, attr); attr->ia_valid = ia_valid; - if (error) + if (error) { + if (sbi->options.quiet) + error = 0; goto out; + } if (((attr->ia_valid & ATTR_UID) && !uid_eq(attr->ia_uid, sbi->options.fs_uid)) || @@ -330,6 +333,12 @@ int exfat_setattr(struct dentry *dentry, struct iattr *attr) goto out; } + if (error) { + if (sbi->options.quiet) + error = 0; + goto out; + } + /* * We don't return -EPERM here. Yes, strange, but this is too * old behavior. diff --git a/super.c b/super.c index eb362fece5dd..17e4e050110c 100644 --- a/super.c +++ b/super.c @@ -146,6 +146,8 @@ static int exfat_show_options(struct seq_file *m, struct dentry *root) seq_printf(m, ",fmask=%04o,dmask=%04o", opts->fs_fmask, opts->fs_dmask); if (opts->allow_utime) seq_printf(m, ",allow_utime=%04o", opts->allow_utime); + if (opts->quiet) + seq_puts(m, ",quiet"); if (opts->utf8) seq_puts(m, ",iocharset=utf8"); else if (sbi->nls_io) @@ -203,6 +205,7 @@ enum { Opt_fmask, Opt_allow_utime, Opt_charset, + Opt_quiet, Opt_err_cont, Opt_err_panic, Opt_err_ro, @@ -224,6 +227,7 @@ static const match_table_t exfat_tokens = { {Opt_fmask, "fmask=%o"}, {Opt_allow_utime, "allow_utime=%o"}, {Opt_charset, "iocharset=%s"}, + {Opt_quiet, "quiet"}, {Opt_err_cont, "errors=continue"}, {Opt_err_panic, "errors=panic"}, {Opt_err_ro, "errors=remount-ro"}, @@ -277,6 +281,9 @@ static int __exfat_parse_option(struct super_block *sb, char *p, substring_t *ar return -ENOMEM; opts->iocharset = tmpstr; break; + case Opt_quiet: + opts->quiet = 1; + break; case Opt_err_cont: opts->errors = EXFAT_ERRORS_CONT; break; From a20e50910ebe20a80a3c00b2acdccc1176e906be Mon Sep 17 00:00:00 2001 From: Park Ju Hyung Date: Sat, 27 Jun 2020 06:39:22 +0900 Subject: [PATCH 084/592] exfat: add virtual xattr support for Android Signed-off-by: Park Ju Hyung --- Kconfig | 20 +++++++++++++- Makefile | 2 +- exfat_fs.h | 11 ++++++++ file.c | 3 ++ namei.c | 3 ++ super.c | 1 + xattr.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 118 insertions(+), 2 deletions(-) create mode 100644 xattr.c diff --git a/Kconfig b/Kconfig index 5a65071b5ecf..e9841704f743 100644 --- a/Kconfig +++ b/Kconfig @@ -10,13 +10,31 @@ config EXFAT_FS To compile this as a module, choose M here: the module will be called exfat. +if EXFAT_FS + config EXFAT_DEFAULT_IOCHARSET string "Default iocharset for exFAT" default "utf8" - depends on EXFAT_FS help Set this to the default input/output character set to use for converting between the encoding that is used for user visible filenames and the UTF-16 character encoding that the exFAT filesystem uses. This can be overridden with the "iocharset" mount option for the exFAT filesystems. + +config EXFAT_VIRTUAL_XATTR + bool "Virtual xattr support for exFAT" + default y + help + To support virtual xattr. + +config EXFAT_VIRTUAL_XATTR_SELINUX_LABEL + string "Default string for SELinux label" + default "u:object_r:exfat:s0" + depends on EXFAT_VIRTUAL_XATTR + help + Set this to the default string for SELinux label. + Support for "u:object_r:exfat:s0" was added in Android Pie, + if you're running Oreo or lower, use "u:object_r:vfat:s0" instead. + +endif # if EXFAT_FS diff --git a/Makefile b/Makefile index 1baf3530db92..a9b6a5ff98bc 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ ifneq ($(KERNELRELEASE),) obj-$(CONFIG_EXFAT_FS) += exfat.o exfat-objs := inode.o namei.o dir.o super.o fatent.o cache.o nls.o misc.o \ - file.o balloc.o + file.o balloc.o xattr.o else # Called from external kernel module build diff --git a/exfat_fs.h b/exfat_fs.h index 7a3be6fcb552..1cc15cfd4d55 100644 --- a/exfat_fs.h +++ b/exfat_fs.h @@ -487,6 +487,17 @@ int exfat_write_inode(struct inode *inode, struct writeback_control *wbc); void exfat_evict_inode(struct inode *inode); int exfat_block_truncate_page(struct inode *inode, loff_t from); +/* xattr.c */ +#ifdef CONFIG_EXFAT_VIRTUAL_XATTR +extern int exfat_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags); +extern ssize_t exfat_getxattr(struct dentry *dentry, const char *name, void *value, size_t size); +extern ssize_t exfat_listxattr(struct dentry *dentry, char *list, size_t size); +extern int exfat_removexattr(struct dentry *dentry, const char *name); +extern const struct xattr_handler *exfat_xattr_handlers[]; +#else +#define exfat_xattr_handlers NULL +#endif + /* exfat/nls.c */ unsigned short exfat_toupper(struct super_block *sb, unsigned short a); int exfat_uniname_ncmp(struct super_block *sb, unsigned short *a, diff --git a/file.c b/file.c index 316a9fb29b86..834d1808cbe5 100644 --- a/file.c +++ b/file.c @@ -380,4 +380,7 @@ const struct file_operations exfat_file_operations = { const struct inode_operations exfat_file_inode_operations = { .setattr = exfat_setattr, .getattr = exfat_getattr, +#ifdef CONFIG_EXFAT_VIRTUAL_XATTR + .listxattr = exfat_listxattr, +#endif }; diff --git a/namei.c b/namei.c index c15d1283f120..de8b324171b3 100644 --- a/namei.c +++ b/namei.c @@ -1436,4 +1436,7 @@ const struct inode_operations exfat_dir_inode_operations = { .rename = exfat_rename, .setattr = exfat_setattr, .getattr = exfat_getattr, +#ifdef CONFIG_EXFAT_VIRTUAL_XATTR + .listxattr = exfat_listxattr, +#endif }; diff --git a/super.c b/super.c index 17e4e050110c..34be61093418 100644 --- a/super.c +++ b/super.c @@ -661,6 +661,7 @@ static int exfat_fill_super(struct super_block *sb, void *data, int silent) sb->s_flags |= SB_NODIRATIME; sb->s_magic = EXFAT_SUPER_MAGIC; sb->s_op = &exfat_sops; + sb->s_xattr = exfat_xattr_handlers; sb->s_time_gran = 10 * NSEC_PER_MSEC; #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) diff --git a/xattr.c b/xattr.c new file mode 100644 index 000000000000..833bdbd6cea4 --- /dev/null +++ b/xattr.c @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * xattr.c: exFAT code for supporting xattr(Extended File Attributes) + */ + +#include "exfat_fs.h" + +#ifdef CONFIG_EXFAT_VIRTUAL_XATTR + +#include +#include +#include +#include + +#ifndef CONFIG_EXFAT_VIRTUAL_XATTR_SELINUX_LABEL +#define CONFIG_EXFAT_VIRTUAL_XATTR_SELINUX_LABEL ("undefined") +#endif + +static const char default_xattr[] = CONFIG_EXFAT_VIRTUAL_XATTR_SELINUX_LABEL; + +static int can_support(const char *name) +{ + if (!name || strcmp(name, "security.selinux")) + return -1; + return 0; +} + +ssize_t exfat_listxattr(struct dentry *dentry, char *list, size_t size) +{ + return 0; +} + +static int __exfat_xattr_check_support(const char *name) +{ + if (can_support(name)) + return -EOPNOTSUPP; + + return 0; +} + +ssize_t __exfat_getxattr(const char *name, void *value, size_t size) +{ + if (can_support(name)) + return -EOPNOTSUPP; + + if ((size > strlen(default_xattr)+1) && value) + strcpy(value, default_xattr); + + return strlen(default_xattr); +} + +static int exfat_xattr_get(const struct xattr_handler *handler, + struct dentry *dentry, struct inode *inode, + const char *name, void *buffer, size_t size) +{ + return __exfat_getxattr(name, buffer, size); +} + +static int exfat_xattr_set(const struct xattr_handler *handler, + struct dentry *dentry, struct inode *inode, + const char *name, const void *value, size_t size, + int flags) +{ + return __exfat_xattr_check_support(name); +} + +static const struct xattr_handler exfat_xattr_handler = { + .prefix = "", /* match anything */ + .get = exfat_xattr_get, + .set = exfat_xattr_set, +}; + +const struct xattr_handler *exfat_xattr_handlers[] = { + &exfat_xattr_handler, + NULL +}; + +#endif /* CONFIG_EXFAT_VIRTUAL_XATTR */ From 87d7e54bb6f855d1c3d75b502f0d132252af353f Mon Sep 17 00:00:00 2001 From: Park Ju Hyung Date: Sat, 27 Jun 2020 06:48:23 +0900 Subject: [PATCH 085/592] exfat: set custom version Signed-off-by: Park Ju Hyung --- exfat_fs.h | 1 + super.c | 2 ++ version.h | 6 ++++++ 3 files changed, 9 insertions(+) create mode 100644 version.h diff --git a/exfat_fs.h b/exfat_fs.h index 1cc15cfd4d55..cebc491ce9e8 100644 --- a/exfat_fs.h +++ b/exfat_fs.h @@ -12,6 +12,7 @@ #include "config.h" #include "compat.h" +#include "version.h" #include "exfat_raw.h" #define EXFAT_SUPER_MAGIC 0x2011BAB0UL diff --git a/super.c b/super.c index 34be61093418..3becb0431504 100644 --- a/super.c +++ b/super.c @@ -797,6 +797,8 @@ static int __init init_exfat_fs(void) { int err; + pr_info("exFAT: file-system version %s\n", EXFAT_VERSION); + err = exfat_cache_init(); if (err) return err; diff --git a/version.h b/version.h new file mode 100644 index 000000000000..fd3e8d568027 --- /dev/null +++ b/version.h @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#define EXFAT_BASE_VERSION "5.8" +#define EXFAT_EXTRAVERSION "0" +#define EXFAT_VARIANT "arter97" +#define EXFAT_VERSION EXFAT_BASE_VERSION "-" EXFAT_EXTRAVERSION EXFAT_VARIANT From ec45335d689ab940fa6d618266eb28b833407789 Mon Sep 17 00:00:00 2001 From: Park Ju Hyung Date: Tue, 13 Aug 2019 09:57:17 +0900 Subject: [PATCH 086/592] exfat: add Ubuntu DKMS configuration Signed-off-by: Park Ju Hyung --- .gitignore | 5 ----- debian/changelog | 19 +++++++++++++++++++ debian/compat | 1 + debian/control | 11 +++++++++++ debian/copyright | 6 ++++++ debian/exfat-dkms.dkms | 5 +++++ debian/rules | 25 +++++++++++++++++++++++++ 7 files changed, 67 insertions(+), 5 deletions(-) create mode 100644 debian/changelog create mode 100644 debian/compat create mode 100644 debian/control create mode 100644 debian/copyright create mode 100644 debian/exfat-dkms.dkms create mode 100755 debian/rules diff --git a/.gitignore b/.gitignore index 2030c7a4d2f8..810b0062282a 100644 --- a/.gitignore +++ b/.gitignore @@ -66,11 +66,6 @@ modules.builtin # /*.spec -# -# Debian directory (make deb-pkg) -# -/debian/ - # # Snap directory (make snap-pkg) # diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 000000000000..1da1548e291d --- /dev/null +++ b/debian/changelog @@ -0,0 +1,19 @@ +exfat-dkms (2.2.0-3arter97) UNRELEASED; urgency=medium + + * Added "quiet" mount option. + + -- Park Ju Hyung Tue, 29 Oct 2019 17:34:32 +0900 + +exfat-dkms (2.2.0-2arter97) UNRELEASED; urgency=medium + + * Fix xattr support. + * Merged upstream exFAT changes. + * More code clean-ups. + + -- Park Ju Hyung Wed, 9 Oct 2019 23:16:22 +0900 + +exfat-dkms (2.2.0-1arter97) UNRELEASED; urgency=medium + + * Initial release. + + -- Park Ju Hyung Tue, 13 Aug 2019 08:53:31 +0900 diff --git a/debian/compat b/debian/compat new file mode 100644 index 000000000000..f599e28b8ab0 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +10 diff --git a/debian/control b/debian/control new file mode 100644 index 000000000000..d6ccaabb25b1 --- /dev/null +++ b/debian/control @@ -0,0 +1,11 @@ +Source: exfat-dkms +Section: misc +Priority: optional +Maintainer: Park Ju Hyung +Build-Depends: debhelper (>= 9), dkms + +Package: exfat-dkms +Architecture: all +Depends: ${misc:Depends}, dkms +Conflicts: exfat-fuse +Description: exFAT filesystem driver for Linux kernel diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 000000000000..ac85309b07f4 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,6 @@ +Author: Park Ju Hyung + +License: + +GNU General Public License version 2, see /usr/share/common-licenses/GPL-2 +for more information. diff --git a/debian/exfat-dkms.dkms b/debian/exfat-dkms.dkms new file mode 100644 index 000000000000..bdb443c8d685 --- /dev/null +++ b/debian/exfat-dkms.dkms @@ -0,0 +1,5 @@ +PACKAGE_NAME="exfat" +PACKAGE_VERSION="#MODULE_VERSION#" +BUILT_MODULE_NAME[0]="$PACKAGE_NAME" +DEST_MODULE_LOCATION[0]="/extra/dkms" +AUTOINSTALL="YES" diff --git a/debian/rules b/debian/rules new file mode 100755 index 000000000000..3ebc260ab85d --- /dev/null +++ b/debian/rules @@ -0,0 +1,25 @@ +#!/usr/bin/make -f + +include /usr/share/dpkg/pkg-info.mk + +version := $(shell dpkg-parsechangelog | grep '^Version:' | cut -d' ' -f2) +TMPDIR := tmp.$(shell uuidgen) + +%: + dh $@ --with dkms + +override_dh_install: + mkdir $(TMPDIR) + cp Makefile $(TMPDIR) + sed -i -e /DKMS_DEFINE/c\CONFIG_EXFAT_FS=m $(TMPDIR)/Makefile + dh_install *.c *.h Kconfig LICENSE $(TMPDIR)/Makefile usr/src/exfat-$(version)/ + rm -r $(TMPDIR) + +override_dh_dkms: + dh_dkms -V $(version) + +override_dh_auto_configure: +override_dh_auto_build: +override_dh_auto_test: +override_dh_auto_install: +override_dh_auto_clean: From f5b27f1156d71e136659595a91bfa6eedf5877be Mon Sep 17 00:00:00 2001 From: Norbert Lange Date: Sun, 15 Sep 2019 22:55:19 +0200 Subject: [PATCH 087/592] exfat: debian: install a Kbuild file, improve installation No more tempdir that might linger around becaue dh_clean does not know about it. Removes the dependency on uuid aswell, can build package on a sbuild slave now. Signed-off-by: Norbert Lange Signed-off-by: Park Ju Hyung --- debian/exfat-dkms.install | 1 + debian/local/print_rule.mk | 2 ++ debian/rules | 14 ++++++-------- 3 files changed, 9 insertions(+), 8 deletions(-) create mode 100644 debian/exfat-dkms.install create mode 100644 debian/local/print_rule.mk diff --git a/debian/exfat-dkms.install b/debian/exfat-dkms.install new file mode 100644 index 000000000000..b601f22c481a --- /dev/null +++ b/debian/exfat-dkms.install @@ -0,0 +1 @@ +usr/src diff --git a/debian/local/print_rule.mk b/debian/local/print_rule.mk new file mode 100644 index 000000000000..43f1c668629a --- /dev/null +++ b/debian/local/print_rule.mk @@ -0,0 +1,2 @@ +writeKbuild: + @printf 'obj-m += exfat.o\nexfat-objs := %s\n' "$(strip $(exfat-objs))" > $(KBUILD_PATH) diff --git a/debian/rules b/debian/rules index 3ebc260ab85d..5c9a58b14e9f 100755 --- a/debian/rules +++ b/debian/rules @@ -3,17 +3,16 @@ include /usr/share/dpkg/pkg-info.mk version := $(shell dpkg-parsechangelog | grep '^Version:' | cut -d' ' -f2) -TMPDIR := tmp.$(shell uuidgen) +targetdir := debian/tmp/usr/src/exfat-$(version) %: dh $@ --with dkms -override_dh_install: - mkdir $(TMPDIR) - cp Makefile $(TMPDIR) - sed -i -e /DKMS_DEFINE/c\CONFIG_EXFAT_FS=m $(TMPDIR)/Makefile - dh_install *.c *.h Kconfig LICENSE $(TMPDIR)/Makefile usr/src/exfat-$(version)/ - rm -r $(TMPDIR) +override_dh_auto_install: + mkdir -p $(targetdir) + install -m644 *.c *.h Kconfig LICENSE Makefile $(targetdir) + # create a Kbuild file instead of patching the Makefile + $(MAKE) KERNELRELEASE=1 KBUILD_PATH=$(targetdir)/Kbuild -s -f Makefile -f debian/local/print_rule.mk writeKbuild override_dh_dkms: dh_dkms -V $(version) @@ -21,5 +20,4 @@ override_dh_dkms: override_dh_auto_configure: override_dh_auto_build: override_dh_auto_test: -override_dh_auto_install: override_dh_auto_clean: From dcf59d03fa8c4088d219728b160eba66ca26f709 Mon Sep 17 00:00:00 2001 From: Park Ju Hyung Date: Sat, 27 Jun 2020 06:53:28 +0900 Subject: [PATCH 088/592] exfat: import README.md from master Signed-off-by: Park Ju Hyung --- README.md | 202 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 000000000000..ee6929e36ebd --- /dev/null +++ b/README.md @@ -0,0 +1,202 @@ +# exfat-linux + +This __exFAT filesystem module for Linux kernel__ is based on `sdFAT` drivers by Samsung, which is used with their smartphone lineups. + +The main objective of **exfat-linux** is to provide the best generic kernel drivers for exFAT. That means Samsung-specific modifications such as fat12/16/32 handlings, defrag and etc has been removed to make the code portable. + +This project can be used for everyday Linux users by simply doing `make && make install`. Ubuntu users can simply add a PPA and start using it, without even downloading the code. This can also be directly dropped-in to an existing Linux kernel source for building the filesystem drivers inline, which should be useful for Android kernel developers. + +--------------------------------------- + +[exfat-nofuse]'s development has been stale for more than a year with no clear maintainership. It's also been lacking critical upstream(*which is Samsung*) changes. + +[exfat-nofuse]: https://github.com/dorimanx/exfat-nofuse + +**exfat-linux** is: + + * Based on a totally different and newer base provided by Samsung + * Intended to keep upstream changes constantly merged + * Intended to fix breakage from newer kernels as-soon-as-possible + +**exfat-linux** has been tested with all major LTS kernels ranging from 3.4 to 4.19 and the ones Canonical uses for Ubuntu: `3.4`, `3.10`, `3.18`, `4.1`, `4.4`, `4.9`, `4.14`, `4.19` and `4.15`, `5.0`, `5.2`, and `5.3-rc`. + +It's also been tested with `x86(i386)`, `x86_64(amd64)`, `arm32(AArch32)` and `arm64(AArch64)`. + +## Disclaimer + +#### ● Original authorship and copyright: Samsung + +#### ● Maintainer of exfat-linux: Park Ju Hyung([arter97](https://twitter.com/arter97)) + +## Using exfat-linux + +### ● Ubuntu PPA + +If you're an Ubuntu user, you can simply add a [PPA repository](https://launchpad.net/~arter97/+archive/ubuntu/exfat-linux) and start using the exFAT module. + +Ubuntu will handle upgrades automatically as well. + +1. Add the exfat-linux repository + + ``` + sudo add-apt-repository ppa:arter97/exfat-linux + sudo apt update + ``` + +2. Install the module + + `sudo apt install exfat-dkms` + +This will use DKMS(Dynamic Kernel Module Support) and automatically build exFAT module for your current Ubuntu installation. + +### ● Manually installing the module + +1. Download the code + + ``` + git clone https://github.com/arter97/exfat-linux + cd exfat-linux + ``` + +2. Build + + `make` + +3. Install + + `sudo make install` + +This will install the module to your __currently running kernel__. + +4. And finally load + + `sudo modprobe exfat` + +If you upgrade the kernel, you'll have to repeat this process. + +If you want to update **exfat-linux** to the latest version, you'll have to repeat this process. + +### ● Merging the drivers to existing Linux kernel source + +If you're using `git`, using `git subtree` or `git submodule` is highly recommended. + +1. Add this repository to `fs/exfat` + +2. Modify `fs/Kconfig` + +``` + menu "DOS/FAT/NT Filesystems" + + source "fs/fat/Kconfig" ++source "fs/exfat/Kconfig" + source "fs/ntfs/Kconfig" + endmenu +``` + +3. Modify `fs/Makefile` + +``` + obj-$(CONFIG_FAT_FS) += fat/ ++obj-$(CONFIG_EXFAT_FS) += exfat/ + obj-$(CONFIG_BFS_FS) += bfs/ +``` + +And you're good to go! + +## Benchmarks + +For reference, existing exFAT implementations were tested and compared on a server running Ubuntu 16.04 with Linux kernel 4.14 under a contained virtual machine. + +Linux 4.14 was used as higher LTS kernels don't work with [exfat-nofuse] at the time of testing. + +### ● Ramdisk + +#### fio sequential I/O + +| Implementation | Base | Read | Write | +| --------------- | ------ | ------------ | ------------ | +| **exfat-linux** | 2.2.0 | 7042 MB/s | 2173 MB/s | +| [exfat-nofuse] | 1.2.9 | 6849 MB/s | 1961 MB/s | +| [exfat-fuse] | N/A | 3097 MB/s | 1710 MB/s | +| ext4 | N/A | 7352 MB/s | 3333 MB/s | + +#### fio random I/O + +| Implementation | Base | Read | Write | +| --------------- | ------ | ------------ | ------------ | +| **exfat-linux** | 2.2.0 | 760 MB/s | 2222 MB/s | +| [exfat-nofuse] | 1.2.9 | 760 MB/s | 2160 MB/s | +| [exfat-fuse] | N/A | 1.7 MB/s | 1.6 MB/s | +| ext4 | N/A | 747 MB/s | 2816 MB/s | + +### ● NVMe device + +#### fio sequential I/O + +| Implementation | Base | Read | Write | +| --------------- | ------ | ------------ | ------------ | +| **exfat-linux** | 2.2.0 | 1283 MB/s | 1832 MB/s | +| [exfat-nofuse] | 1.2.9 | 1285 MB/s | 1678 MB/s | +| [exfat-fuse] | N/A | 751 MB/s | 1464 MB/s | +| ext4 | N/A | 1283 MB/s | 3356 MB/s | + +#### fio random I/O + +| Implementation | Base | Read | Write | +| --------------- | ------ | ------------ | ------------ | +| **exfat-linux** | 2.2.0 | 26 MB/s | 1885 MB/s | +| [exfat-nofuse] | 1.2.9 | 24 MB/s | 1827 MB/s | +| [exfat-fuse] | N/A | 1.6 MB/s | 1.6 MB/s | +| ext4 | N/A | 29 MB/s | 2821 MB/s | + +[exfat-fuse]: https://github.com/relan/exfat + +## Mount options + +* uid +* gid +* umask +* dmask +* fmask +* allow_utime +* codepage +* iocharset +* quiet +* utf8 +* tz + + * Please refer to the [vfat](https://github.com/torvalds/linux/blob/master/Documentation/filesystems/vfat.txt)'s documentation. + +* namecase + + * Passing `namecase=1` as a mount option will make exFAT operate in a case-sensitive mode. + + * Default is insensitive mode. + +* symlink + + * Allow a symlink to be created under exFAT. + +* errors=continue + + * Keep going on a filesystem error. + +* errors=panic + + * Panic and halt the machine if an error occurs. + +* errors=remount-ro + + * Remount the filesystem read-only on an error. + +* discard + + * Enable the use of discard/TRIM commands to ensure flash storage doesn't run out of free blocks. This option may introduce latency penalty on file removal operations. + +* delayed_meta + + * Delay flushing metadata, hence improving performance. + + * This is enabled by default, please pass `nodelayed_meta` to disable it. + +## Enjoy! From 53ae24aa702563c3bc5100d34ce39b310a427f98 Mon Sep 17 00:00:00 2001 From: Park Ju Hyung Date: Sat, 27 Jun 2020 08:14:16 +0900 Subject: [PATCH 089/592] exfat: update README for new base Signed-off-by: Park Ju Hyung --- README.md | 52 +++++++++++++++++----------------------------------- 1 file changed, 17 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index ee6929e36ebd..d1f44c532306 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,23 @@ # exfat-linux -This __exFAT filesystem module for Linux kernel__ is based on `sdFAT` drivers by Samsung, which is used with their smartphone lineups. - -The main objective of **exfat-linux** is to provide the best generic kernel drivers for exFAT. That means Samsung-specific modifications such as fat12/16/32 handlings, defrag and etc has been removed to make the code portable. +This __exFAT filesystem module for Linux kernel__ is a backport of the latest Linux mainline's exFAT drivers by Samsung. This project can be used for everyday Linux users by simply doing `make && make install`. Ubuntu users can simply add a PPA and start using it, without even downloading the code. This can also be directly dropped-in to an existing Linux kernel source for building the filesystem drivers inline, which should be useful for Android kernel developers. ---------------------------------------- - -[exfat-nofuse]'s development has been stale for more than a year with no clear maintainership. It's also been lacking critical upstream(*which is Samsung*) changes. - -[exfat-nofuse]: https://github.com/dorimanx/exfat-nofuse - -**exfat-linux** is: - - * Based on a totally different and newer base provided by Samsung - * Intended to keep upstream changes constantly merged - * Intended to fix breakage from newer kernels as-soon-as-possible - -**exfat-linux** has been tested with all major LTS kernels ranging from 3.4 to 4.19 and the ones Canonical uses for Ubuntu: `3.4`, `3.10`, `3.18`, `4.1`, `4.4`, `4.9`, `4.14`, `4.19` and `4.15`, `5.0`, `5.2`, and `5.3-rc`. +**exfat-linux** has been tested with all major LTS kernels ranging from v4.9 to v5.4 and the ones Canonical uses for Ubuntu: `v4.9`, `v4.14`, `v4.19`, `v5.4` and `v4.15`, `v5.3`, and `v5.6`. It's also been tested with `x86(i386)`, `x86_64(amd64)`, `arm32(AArch32)` and `arm64(AArch64)`. +Linux kernels since `v5.4` includes an exFAT driver, but it is an extremely outdated version from 2016. This was later revised by Samsung directly with `v5.7`. + +People on `v5.7` kernel or higher can just use the bundled exFAT drivers. + +People on `v5.4+` are highly recommended to use this drivers. + +Support for kernel versions lower than `v4.9` were dropped for easier maintenance. For people interested in exFAT support for said kernels, please use the [old branch](https://github.com/arter97/exfat-linux/tree/old). It still works nicely and it's actively being shipped to production smartphones. + +exfat-linux is planned to be maintained until Android devices with `v5.7+` LTS kernel become more common. + ## Disclaimer #### ● Original authorship and copyright: Samsung @@ -68,6 +64,8 @@ This will use DKMS(Dynamic Kernel Module Support) and automatically build exFAT This will install the module to your __currently running kernel__. +__If you're running a `v5.4+` kernel, it is highly recommended to reboot at this point to prevent the existing staging exFAT drivers to load.__ + 4. And finally load `sudo modprobe exfat` @@ -109,6 +107,8 @@ For reference, existing exFAT implementations were tested and compared on a serv Linux 4.14 was used as higher LTS kernels don't work with [exfat-nofuse] at the time of testing. +__The new base backported from mainline is not benchmarked yet.__ + ### ● Ramdisk #### fio sequential I/O @@ -159,24 +159,12 @@ Linux 4.14 was used as higher LTS kernels don't work with [exfat-nofuse] at the * dmask * fmask * allow_utime -* codepage * iocharset * quiet -* utf8 -* tz +* time_offset * Please refer to the [vfat](https://github.com/torvalds/linux/blob/master/Documentation/filesystems/vfat.txt)'s documentation. -* namecase - - * Passing `namecase=1` as a mount option will make exFAT operate in a case-sensitive mode. - - * Default is insensitive mode. - -* symlink - - * Allow a symlink to be created under exFAT. - * errors=continue * Keep going on a filesystem error. @@ -193,10 +181,4 @@ Linux 4.14 was used as higher LTS kernels don't work with [exfat-nofuse] at the * Enable the use of discard/TRIM commands to ensure flash storage doesn't run out of free blocks. This option may introduce latency penalty on file removal operations. -* delayed_meta - - * Delay flushing metadata, hence improving performance. - - * This is enabled by default, please pass `nodelayed_meta` to disable it. - ## Enjoy! From 20b0d3e885d71c4da759ade0b9e52912b4654f39 Mon Sep 17 00:00:00 2001 From: Park Ju Hyung Date: Sat, 27 Jun 2020 08:33:48 +0900 Subject: [PATCH 090/592] exfat: version 5.8-1arter97 Signed-off-by: Park Ju Hyung --- debian/changelog | 7 +++++++ version.h | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index 1da1548e291d..d2ceafeb8284 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +exfat-dkms (5.8-1arter97) UNRELEASED; urgency=medium + + * Rebased to Linux mainline's drivers + * Supports for kernels lower than v4.9 dropped + + -- Park Ju Hyung Sat, 27 Jun 2020 08:32:23 +0900 + exfat-dkms (2.2.0-3arter97) UNRELEASED; urgency=medium * Added "quiet" mount option. diff --git a/version.h b/version.h index fd3e8d568027..d9494febec83 100644 --- a/version.h +++ b/version.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later #define EXFAT_BASE_VERSION "5.8" -#define EXFAT_EXTRAVERSION "0" +#define EXFAT_EXTRAVERSION "1" #define EXFAT_VARIANT "arter97" #define EXFAT_VERSION EXFAT_BASE_VERSION "-" EXFAT_EXTRAVERSION EXFAT_VARIANT From 3b888b448f09fef4aa8d275019c9a58796182432 Mon Sep 17 00:00:00 2001 From: Veera Sundaram Sankaran Date: Fri, 12 Jun 2020 18:32:24 +0800 Subject: [PATCH 091/592] disp: msm: sde: reset ctl during wr_ptr_irq timeout wr_ptr_irq timeout signifies that the MDP is stuck on either the current or previous frame. Handle ctl reset and fence signalling as part of this timeout handling. This logic would help to recover the HW faster in case of posted-start. Change-Id: I09b3d21772df431f9fc4a58b2fd9b4fcac4a7de7 Signed-off-by: Veera Sundaram Sankaran Signed-off-by: Ray Zhang Signed-off-by: Bruce Hoo --- drivers/gpu/drm/msm/sde/sde_encoder.c | 23 +++------------ drivers/gpu/drm/msm/sde/sde_encoder_phys.h | 6 ++++ .../gpu/drm/msm/sde/sde_encoder_phys_cmd.c | 29 +++++++++++++------ 3 files changed, 30 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c index 13aadfd4975a..fe05a401a2fa 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder.c @@ -4626,21 +4626,11 @@ static void _helper_flush_dsc(struct sde_encoder_virt *sde_enc) } } -static void _sde_encoder_needs_hw_reset(struct drm_encoder *drm_enc, - int ln_cnt1) +void sde_encoder_helper_needs_hw_reset(struct drm_encoder *drm_enc) { struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc); struct sde_encoder_phys *phys; - int ln_cnt2, i; - - /* query line count before cur_master is updated */ - if (sde_enc->cur_master && sde_enc->cur_master->ops.get_wr_line_count) - ln_cnt2 = sde_enc->cur_master->ops.get_wr_line_count( - sde_enc->cur_master); - else - ln_cnt2 = -EINVAL; - - SDE_EVT32(DRMID(drm_enc), ln_cnt1, ln_cnt2); + int i; for (i = 0; i < sde_enc->num_phys_encs; i++) { phys = sde_enc->phys_encs[i]; @@ -4658,7 +4648,7 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, struct sde_crtc *sde_crtc; struct msm_drm_private *priv = NULL; bool needs_hw_reset = false; - int ln_cnt1 = -EINVAL, i, rc, ret = 0; + int i, rc, ret = 0; struct msm_display_info *disp_info; if (!drm_enc || !params || !drm_enc->dev || @@ -4675,11 +4665,6 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, SDE_DEBUG_ENC(sde_enc, "\n"); SDE_EVT32(DRMID(drm_enc)); - /* save this for later, in case of errors */ - if (sde_enc->cur_master && sde_enc->cur_master->ops.get_wr_line_count) - ln_cnt1 = sde_enc->cur_master->ops.get_wr_line_count( - sde_enc->cur_master); - if (sde_enc->cur_master && sde_enc->cur_master->connector && disp_info->capabilities & MSM_DISPLAY_CAP_CMD_MODE) sde_enc->frame_trigger_mode = sde_connector_get_property( @@ -4722,7 +4707,7 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, /* if any phys needs reset, reset all phys, in-order */ if (needs_hw_reset) - _sde_encoder_needs_hw_reset(drm_enc, ln_cnt1); + sde_encoder_helper_needs_hw_reset(drm_enc); _sde_encoder_update_master(drm_enc, params); diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h index e5f7ea0192d9..53d6cf5fcf3d 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h @@ -516,6 +516,12 @@ void sde_encoder_phys_setup_cdm(struct sde_encoder_phys *phys_enc, struct drm_framebuffer *fb, const struct sde_format *format, struct sde_rect *wb_roi); +/** + * sde_encoder_helper_needs_hw_reset - hw reset helper function + * @drm_enc: Pointer to drm encoder structure + */ +void sde_encoder_helper_needs_hw_reset(struct drm_encoder *drm_enc); + /** * sde_encoder_helper_trigger_flush - control flush helper function * This helper function may be optionally specified by physical diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c index ffa1d04597e3..197b34a297c8 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c @@ -1436,8 +1436,11 @@ static int sde_encoder_phys_cmd_wait_for_commit_done( cmd_enc = to_sde_encoder_phys_cmd(phys_enc); /* only required for master controller */ - if (sde_encoder_phys_cmd_is_master(phys_enc)) + if (sde_encoder_phys_cmd_is_master(phys_enc)) { rc = _sde_encoder_phys_cmd_wait_for_wr_ptr(phys_enc); + if (rc == -ETIMEDOUT) + goto wait_for_idle; + } if (!rc && sde_encoder_phys_cmd_is_master(phys_enc) && cmd_enc->autorefresh.cfg.enable) @@ -1446,14 +1449,22 @@ static int sde_encoder_phys_cmd_wait_for_commit_done( /* wait for posted start or serialize trigger */ if ((atomic_read(&phys_enc->pending_kickoff_cnt) > 1) || (!rc && phys_enc->frame_trigger_mode == - FRAME_DONE_WAIT_SERIALIZE)) { - rc = _sde_encoder_phys_cmd_wait_for_idle(phys_enc); - if (rc) { - atomic_set(&phys_enc->pending_kickoff_cnt, 0); - SDE_EVT32(DRMID(phys_enc->parent), - phys_enc->hw_pp->idx - PINGPONG_0); - SDE_ERROR("failed wait_for_idle: %d\n", rc); - } + FRAME_DONE_WAIT_SERIALIZE)) + goto wait_for_idle; + +wait_for_idle: + rc = _sde_encoder_phys_cmd_wait_for_idle(phys_enc); + if (rc) { + SDE_EVT32(DRMID(phys_enc->parent), + phys_enc->hw_pp->idx - PINGPONG_0, + phys_enc->frame_trigger_mode, + atomic_read(&phys_enc->pending_kickoff_cnt), + phys_enc->enable_state, rc); + atomic_set(&phys_enc->pending_kickoff_cnt, 0); + SDE_ERROR("pp:%d failed wait_for_idle: %d\n", + phys_enc->hw_pp->idx - PINGPONG_0, rc); + if (phys_enc->enable_state == SDE_ENC_ERR_NEEDS_HW_RESET) + sde_encoder_helper_needs_hw_reset(phys_enc->parent); } return rc; From fb0adea1cd59f8dfec5c50cd21181d2752cb2e4b Mon Sep 17 00:00:00 2001 From: Veera Sundaram Sankaran Date: Fri, 12 Jun 2020 18:45:24 +0800 Subject: [PATCH 092/592] disp: msm: sde: fix release fence signaling in error cases Handle release fence/frame-done error signalling for error case like esd failure, pp_done timeout, interrupt disable on cpu, etc. It fixes the race condition for pending_frame count update and also triggers correct wait function for wr_ptr wait failure. Change-Id: Iad08f20592c97221a1626bb40e607c398a9812b6 Signed-off-by: Veera Sundaram Sankaran Signed-off-by: Dhaval Patel Signed-off-by: Bruce Hoo Signed-off-by: Ray Zhang --- drivers/gpu/drm/msm/sde/sde_encoder.c | 4 +- drivers/gpu/drm/msm/sde/sde_encoder_phys.h | 3 +- .../gpu/drm/msm/sde/sde_encoder_phys_cmd.c | 59 ++++++++++--------- 3 files changed, 35 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c index fe05a401a2fa..b869a2d01262 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder.c @@ -3455,6 +3455,7 @@ static void sde_encoder_virt_disable(struct drm_encoder *drm_enc) sde_enc->phys_encs[i]->cont_splash_single_flush = 0; sde_enc->phys_encs[i]->connector = NULL; } + atomic_set(&sde_enc->frame_done_cnt[i], 0); } sde_enc->cur_master = NULL; @@ -3680,8 +3681,7 @@ static void sde_encoder_frame_done_callback( /* One of the physical encoders has become idle */ for (i = 0; i < sde_enc->num_phys_encs; i++) { - if ((sde_enc->phys_encs[i] == ready_phys) || - (event & SDE_ENCODER_FRAME_EVENT_ERROR)) { + if (sde_enc->phys_encs[i] == ready_phys) { SDE_EVT32_VERBOSE(DRMID(drm_enc), i, atomic_read( &sde_enc->frame_done_cnt[i])); diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h index 53d6cf5fcf3d..8ffb00f43320 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h @@ -379,12 +379,12 @@ struct sde_encoder_phys_cmd_autorefresh { * struct sde_encoder_phys_cmd - sub-class of sde_encoder_phys to handle command * mode specific operations * @base: Baseclass physical encoder structure - * @intf_idx: Intf Block index used by this phys encoder * @stream_sel: Stream selection for multi-stream interfaces * @pp_timeout_report_cnt: number of pingpong done irq timeout errors * @autorefresh: autorefresh feature state * @pending_vblank_cnt: Atomic counter tracking pending wait for VBLANK * @pending_vblank_wq: Wait queue for blocking until VBLANK received + * @wr_ptr_wait_success: log wr_ptr_wait success for release fence trigger */ struct sde_encoder_phys_cmd { struct sde_encoder_phys base; @@ -393,6 +393,7 @@ struct sde_encoder_phys_cmd { struct sde_encoder_phys_cmd_autorefresh autorefresh; atomic_t pending_vblank_cnt; wait_queue_head_t pending_vblank_wq; + bool wr_ptr_wait_success; }; /** diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c index 197b34a297c8..6d127bd06264 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c @@ -481,20 +481,18 @@ static int _sde_encoder_phys_cmd_handle_ppdone_timeout( conn = phys_enc->connector; sde_conn = to_sde_connector(conn); - if (atomic_read(&phys_enc->pending_kickoff_cnt) == 0) + /* decrement the kickoff_cnt before checking for ESD status */ + if (!atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0)) return 0; cmd_enc->pp_timeout_report_cnt++; - pending_kickoff_cnt = atomic_read(&phys_enc->pending_kickoff_cnt); + pending_kickoff_cnt = atomic_read(&phys_enc->pending_kickoff_cnt) + 1; SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0, cmd_enc->pp_timeout_report_cnt, pending_kickoff_cnt, frame_event); - /* decrement the kickoff_cnt before checking for ESD status */ - atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0); - /* check if panel is still sending TE signal or not */ if (sde_connector_esd_status(phys_enc->connector) || sde_conn->panel_dead) @@ -672,13 +670,28 @@ static int _sde_encoder_phys_cmd_wait_for_idle( to_sde_encoder_phys_cmd(phys_enc); struct sde_encoder_wait_info wait_info; bool recovery_events; - int ret, i, pending_cnt; + int ret; + struct sde_hw_ctl *ctl; if (!phys_enc) { SDE_ERROR("invalid encoder\n"); return -EINVAL; } + ctl = phys_enc->hw_ctl; + if (cmd_enc->wr_ptr_wait_success && + (phys_enc->frame_trigger_mode == FRAME_DONE_WAIT_POSTED_START) && + ctl->ops.get_scheduler_status && + (ctl->ops.get_scheduler_status(ctl) & BIT(0)) && + atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0) && + phys_enc->parent_ops.handle_frame_done) { + phys_enc->parent_ops.handle_frame_done( + phys_enc->parent, phys_enc, + SDE_ENCODER_FRAME_EVENT_DONE | + SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE); + return 0; + } + wait_info.wq = &phys_enc->pending_kickoff_wq; wait_info.atomic_cnt = &phys_enc->pending_kickoff_cnt; wait_info.timeout_ms = KICKOFF_TIMEOUT_MS; @@ -692,9 +705,7 @@ static int _sde_encoder_phys_cmd_wait_for_idle( ret = sde_encoder_helper_wait_for_irq(phys_enc, INTR_IDX_PINGPONG, &wait_info); if (ret == -ETIMEDOUT) { - pending_cnt = atomic_read(&phys_enc->pending_kickoff_cnt); - for (i = 0; i < pending_cnt; i++) - _sde_encoder_phys_cmd_handle_ppdone_timeout(phys_enc, + _sde_encoder_phys_cmd_handle_ppdone_timeout(phys_enc, recovery_events); } else if (!ret) { if (cmd_enc->pp_timeout_report_cnt && recovery_events) { @@ -1386,20 +1397,10 @@ static int _sde_encoder_phys_cmd_wait_for_wr_ptr( phys_enc->parent_ops.handle_frame_done( phys_enc->parent, phys_enc, SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE); - } else if ((ret == 0) && - (phys_enc->frame_trigger_mode == FRAME_DONE_WAIT_POSTED_START) && - atomic_read(&phys_enc->pending_kickoff_cnt) && - ctl->ops.get_scheduler_status && - (ctl->ops.get_scheduler_status(ctl) & BIT(0)) && - phys_enc->parent_ops.handle_frame_done) { - atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0); - - phys_enc->parent_ops.handle_frame_done( - phys_enc->parent, phys_enc, - SDE_ENCODER_FRAME_EVENT_DONE | - SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE); } + cmd_enc->wr_ptr_wait_success = (ret == 0) ? true : false; + return ret; } @@ -1427,7 +1428,7 @@ static int sde_encoder_phys_cmd_wait_for_tx_complete( static int sde_encoder_phys_cmd_wait_for_commit_done( struct sde_encoder_phys *phys_enc) { - int rc = 0; + int rc = 0, i, pending_cnt; struct sde_encoder_phys_cmd *cmd_enc; if (!phys_enc) @@ -1440,11 +1441,11 @@ static int sde_encoder_phys_cmd_wait_for_commit_done( rc = _sde_encoder_phys_cmd_wait_for_wr_ptr(phys_enc); if (rc == -ETIMEDOUT) goto wait_for_idle; - } - if (!rc && sde_encoder_phys_cmd_is_master(phys_enc) && - cmd_enc->autorefresh.cfg.enable) - rc = _sde_encoder_phys_cmd_wait_for_autorefresh_done(phys_enc); + if (cmd_enc->autorefresh.cfg.enable) + rc = _sde_encoder_phys_cmd_wait_for_autorefresh_done( + phys_enc); + } /* wait for posted start or serialize trigger */ if ((atomic_read(&phys_enc->pending_kickoff_cnt) > 1) || @@ -1453,14 +1454,16 @@ static int sde_encoder_phys_cmd_wait_for_commit_done( goto wait_for_idle; wait_for_idle: - rc = _sde_encoder_phys_cmd_wait_for_idle(phys_enc); + pending_cnt = atomic_read(&phys_enc->pending_kickoff_cnt); + for (i = 0; i < pending_cnt; i++) + rc |= sde_encoder_wait_for_event(phys_enc->parent, + MSM_ENC_TX_COMPLETE); if (rc) { SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0, phys_enc->frame_trigger_mode, atomic_read(&phys_enc->pending_kickoff_cnt), phys_enc->enable_state, rc); - atomic_set(&phys_enc->pending_kickoff_cnt, 0); SDE_ERROR("pp:%d failed wait_for_idle: %d\n", phys_enc->hw_pp->idx - PINGPONG_0, rc); if (phys_enc->enable_state == SDE_ENC_ERR_NEEDS_HW_RESET) From 1cb8e403b4552d974e0a902c935de274de63a154 Mon Sep 17 00:00:00 2001 From: Dhaval Patel Date: Fri, 12 Jun 2020 19:05:14 +0800 Subject: [PATCH 093/592] disp: msm: sde: wait for specific pp_done instead of zero 2 Frames transfer pending is possible with posted start. One ongoing frame and another triggered frame. Current SW waits for pp_done interrupt if pending frame count is greater than 1. It is possible that interrupt may be missed for ongoing frame. In that case, SW should run pp_done wait for one by one frame instead of two frames together. It allows encoder to check the ctl scheduler status and trigger the frame done event on time. Change-Id: I4817842292d96747890ee70da8a5bdf9b56816ed Signed-off-by: Dhaval Patel Signed-off-by: Ray Zhang Signed-off-by: Bruce Hoo --- drivers/gpu/drm/msm/sde/sde_encoder.c | 9 ++++++--- drivers/gpu/drm/msm/sde/sde_encoder_phys.h | 2 ++ drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c | 16 ++++++++++++---- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c index b869a2d01262..fee86ae93330 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder.c @@ -444,13 +444,16 @@ static int _sde_encoder_wait_timeout(int32_t drm_id, int32_t hw_id, do { rc = wait_event_timeout(*(info->wq), - atomic_read(info->atomic_cnt) == 0, wait_time_jiffies); + atomic_read(info->atomic_cnt) == info->count_check, + wait_time_jiffies); cur_ktime = ktime_get(); SDE_EVT32(drm_id, hw_id, rc, ktime_to_ms(cur_ktime), - timeout_ms, atomic_read(info->atomic_cnt)); + timeout_ms, atomic_read(info->atomic_cnt), + info->count_check); /* If we timed out, counter is valid and time is less, wait again */ - } while (atomic_read(info->atomic_cnt) && (rc == 0) && + } while ((atomic_read(info->atomic_cnt) != info->count_check) && + (rc == 0) && (ktime_compare_safe(exp_ktime, cur_ktime) > 0)); return rc; diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h index 8ffb00f43320..accab600df16 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h @@ -472,11 +472,13 @@ struct sde_enc_phys_init_params { * sde_encoder_wait_info - container for passing arguments to irq wait functions * @wq: wait queue structure * @atomic_cnt: wait until atomic_cnt equals zero + * @count_check: wait for specific atomic_cnt instead of zero. * @timeout_ms: timeout value in milliseconds */ struct sde_encoder_wait_info { wait_queue_head_t *wq; atomic_t *atomic_cnt; + u32 count_check; s64 timeout_ms; }; diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c index 6d127bd06264..1ac7b23bd233 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c @@ -672,6 +672,7 @@ static int _sde_encoder_phys_cmd_wait_for_idle( bool recovery_events; int ret; struct sde_hw_ctl *ctl; + bool wr_ptr_wait_success = true; if (!phys_enc) { SDE_ERROR("invalid encoder\n"); @@ -679,7 +680,11 @@ static int _sde_encoder_phys_cmd_wait_for_idle( } ctl = phys_enc->hw_ctl; - if (cmd_enc->wr_ptr_wait_success && + + if (sde_encoder_phys_cmd_is_master(phys_enc)) + wr_ptr_wait_success = cmd_enc->wr_ptr_wait_success; + + if (wr_ptr_wait_success && (phys_enc->frame_trigger_mode == FRAME_DONE_WAIT_POSTED_START) && ctl->ops.get_scheduler_status && (ctl->ops.get_scheduler_status(ctl) & BIT(0)) && @@ -692,6 +697,9 @@ static int _sde_encoder_phys_cmd_wait_for_idle( return 0; } + if (atomic_read(&phys_enc->pending_kickoff_cnt) > 1) + wait_info.count_check = 1; + wait_info.wq = &phys_enc->pending_kickoff_wq; wait_info.atomic_cnt = &phys_enc->pending_kickoff_cnt; wait_info.timeout_ms = KICKOFF_TIMEOUT_MS; @@ -727,7 +735,7 @@ static int _sde_encoder_phys_cmd_wait_for_autorefresh_done( { struct sde_encoder_phys_cmd *cmd_enc = to_sde_encoder_phys_cmd(phys_enc); - struct sde_encoder_wait_info wait_info; + struct sde_encoder_wait_info wait_info = {NULL}; int ret = 0; if (!phys_enc) { @@ -1351,7 +1359,7 @@ static int _sde_encoder_phys_cmd_wait_for_wr_ptr( { struct sde_encoder_phys_cmd *cmd_enc = to_sde_encoder_phys_cmd(phys_enc); - struct sde_encoder_wait_info wait_info; + struct sde_encoder_wait_info wait_info = {NULL}; int ret; bool frame_pending = true; struct sde_hw_ctl *ctl; @@ -1478,7 +1486,7 @@ static int sde_encoder_phys_cmd_wait_for_vblank( { int rc = 0; struct sde_encoder_phys_cmd *cmd_enc; - struct sde_encoder_wait_info wait_info; + struct sde_encoder_wait_info wait_info = {NULL}; if (!phys_enc) return -EINVAL; From ff76cdcca5deb223d71be208e8d2a02315401a15 Mon Sep 17 00:00:00 2001 From: Veera Sundaram Sankaran Date: Fri, 12 Jun 2020 19:13:48 +0800 Subject: [PATCH 094/592] disp: msm: sde: fix handling the missing pp-done interrupt cases With posted-start, ctl scheduler status and pending-kickoff count are checked to address the missing pp-done interrupt cases, which can occur if the IRQs are disabled for a long time by some entity. Currently this check is done after the wr-ptr-irq. At this point the scheduler status may or may not be idle, based on the frame-transfer. Move this handling after the timeout, so the scheduler is guaranteed to be in idle state for working use-case. Change-Id: I3fa9ecce8139ff667c1882e286571169c543c797 Signed-off-by: Veera Sundaram Sankaran Signed-off-by: Ray Zhang Signed-off-by: Bruce Hoo --- .../gpu/drm/msm/sde/sde_encoder_phys_cmd.c | 56 ++++++++++++++----- 1 file changed, 42 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c index 1ac7b23bd233..fd7897d587b8 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c @@ -663,38 +663,60 @@ static bool _sde_encoder_phys_cmd_is_ongoing_pptx( return false; } -static int _sde_encoder_phys_cmd_wait_for_idle( +static bool _sde_encoder_phys_cmd_is_scheduler_idle( struct sde_encoder_phys *phys_enc) { + bool wr_ptr_wait_success = true; + unsigned long lock_flags; + bool ret = false; struct sde_encoder_phys_cmd *cmd_enc = to_sde_encoder_phys_cmd(phys_enc); - struct sde_encoder_wait_info wait_info; - bool recovery_events; - int ret; - struct sde_hw_ctl *ctl; - bool wr_ptr_wait_success = true; - - if (!phys_enc) { - SDE_ERROR("invalid encoder\n"); - return -EINVAL; - } - - ctl = phys_enc->hw_ctl; + struct sde_hw_ctl *ctl = phys_enc->hw_ctl; if (sde_encoder_phys_cmd_is_master(phys_enc)) wr_ptr_wait_success = cmd_enc->wr_ptr_wait_success; + /* + * Handle cases where a pp-done interrupt is missed + * due to irq latency with POSTED start + */ if (wr_ptr_wait_success && (phys_enc->frame_trigger_mode == FRAME_DONE_WAIT_POSTED_START) && ctl->ops.get_scheduler_status && (ctl->ops.get_scheduler_status(ctl) & BIT(0)) && atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0) && phys_enc->parent_ops.handle_frame_done) { + + spin_lock_irqsave(phys_enc->enc_spinlock, lock_flags); phys_enc->parent_ops.handle_frame_done( phys_enc->parent, phys_enc, SDE_ENCODER_FRAME_EVENT_DONE | SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE); - return 0; + spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags); + + SDE_EVT32(DRMID(phys_enc->parent), + phys_enc->hw_pp->idx - PINGPONG_0, + phys_enc->hw_intf->idx - INTF_0, + atomic_read(&phys_enc->pending_kickoff_cnt)); + + ret = true; + } + + return ret; +} + +static int _sde_encoder_phys_cmd_wait_for_idle( + struct sde_encoder_phys *phys_enc) +{ + struct sde_encoder_phys_cmd *cmd_enc = + to_sde_encoder_phys_cmd(phys_enc); + struct sde_encoder_wait_info wait_info = {NULL}; + bool recovery_events; + int ret; + + if (!phys_enc) { + SDE_ERROR("invalid encoder\n"); + return -EINVAL; } if (atomic_read(&phys_enc->pending_kickoff_cnt) > 1) @@ -710,9 +732,15 @@ static int _sde_encoder_phys_cmd_wait_for_idle( if (_sde_encoder_phys_is_ppsplit_slave(phys_enc)) return 0; + if (_sde_encoder_phys_cmd_is_scheduler_idle(phys_enc)) + return 0; + ret = sde_encoder_helper_wait_for_irq(phys_enc, INTR_IDX_PINGPONG, &wait_info); if (ret == -ETIMEDOUT) { + if (_sde_encoder_phys_cmd_is_scheduler_idle(phys_enc)) + return 0; + _sde_encoder_phys_cmd_handle_ppdone_timeout(phys_enc, recovery_events); } else if (!ret) { From 6c6d649c3ea0d59250ab22b3dec383f7f57ad976 Mon Sep 17 00:00:00 2001 From: Veera Sundaram Sankaran Date: Fri, 12 Jun 2020 19:21:42 +0800 Subject: [PATCH 095/592] disp: msm: sde: avoid encoder power-collapse with pending frames The encoder idle work is scheduled during the frame-done event to be executed after a timeout. During the execution, the check for any on-going/pending frames is invalid as it checks for > 1. Fix it to check for any non-zero frame-pending and avoid power-collapse. Change-Id: If7715ee56cc9bfa63787811458f4fc91de540013 Signed-off-by: Veera Sundaram Sankaran Signed-off-by: Ray Zhang Signed-off-by: Bruce Hoo --- drivers/gpu/drm/msm/sde/sde_encoder.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c index fee86ae93330..1cfa67a88d31 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder.c @@ -2696,7 +2696,7 @@ static int sde_encoder_resource_control(struct drm_encoder *drm_enc, SDE_EVTLOG_ERROR); mutex_unlock(&sde_enc->rc_lock); return 0; - } else if (sde_crtc_frame_pending(sde_enc->crtc) > 1) { + } else if (sde_crtc_frame_pending(sde_enc->crtc)) { SDE_DEBUG_ENC(sde_enc, "skip idle entry"); SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state, sde_crtc_frame_pending(sde_enc->crtc), From b57ddc535025c74b45b35c5ce32e4dfdb37d2a6a Mon Sep 17 00:00:00 2001 From: Veera Sundaram Sankaran Date: Fri, 12 Jun 2020 19:36:49 +0800 Subject: [PATCH 096/592] disp: msm: sde: handle another case for lost pp-done interrupt Due to interrupt delays, sometimes the pp-done interrupt for an in-between frame is lost, as with posted-start frames are queued to the hardware before the completion of the previous frame. Handle the lost pp-done interrupt in the case where frame-n pp-done interrupt is missed and frame-n+1 pp-done interrupt is processed before frame-n+1 wr-ptr interrupt. Change-Id: I36ec7ac494b2720fc005dab75047d2f4a5a2a699 Signed-off-by: Veera Sundaram Sankaran Signed-off-by: Ray Zhang Signed-off-by: Bruce Hoo --- .../gpu/drm/msm/sde/sde_encoder_phys_cmd.c | 22 ++++++++++++++----- drivers/gpu/drm/msm/sde/sde_hw_ctl.h | 2 ++ 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c index fd7897d587b8..15123d6ee7b1 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c @@ -1341,10 +1341,11 @@ static int sde_encoder_phys_cmd_prepare_for_kickoff( } SDE_DEBUG_CMDENC(cmd_enc, "pp %d\n", phys_enc->hw_pp->idx - PINGPONG_0); + phys_enc->frame_trigger_mode = params->frame_trigger_mode; SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0, atomic_read(&phys_enc->pending_kickoff_cnt), - atomic_read(&cmd_enc->autorefresh.kickoff_cnt)); - phys_enc->frame_trigger_mode = params->frame_trigger_mode; + atomic_read(&cmd_enc->autorefresh.kickoff_cnt), + phys_enc->frame_trigger_mode); if (phys_enc->frame_trigger_mode == FRAME_DONE_WAIT_DEFAULT) { /* @@ -1466,6 +1467,8 @@ static int sde_encoder_phys_cmd_wait_for_commit_done( { int rc = 0, i, pending_cnt; struct sde_encoder_phys_cmd *cmd_enc; + u32 scheduler_status = INVALID_CTL_STATUS; + struct sde_hw_ctl *ctl; if (!phys_enc) return -EINVAL; @@ -1481,14 +1484,22 @@ static int sde_encoder_phys_cmd_wait_for_commit_done( if (cmd_enc->autorefresh.cfg.enable) rc = _sde_encoder_phys_cmd_wait_for_autorefresh_done( phys_enc); + + ctl = phys_enc->hw_ctl; + if (ctl && ctl->ops.get_scheduler_status) + scheduler_status = ctl->ops.get_scheduler_status(ctl); } /* wait for posted start or serialize trigger */ - if ((atomic_read(&phys_enc->pending_kickoff_cnt) > 1) || + pending_cnt = atomic_read(&phys_enc->pending_kickoff_cnt); + if ((pending_cnt > 1) || + (pending_cnt && (scheduler_status & BIT(0))) || (!rc && phys_enc->frame_trigger_mode == - FRAME_DONE_WAIT_SERIALIZE)) + FRAME_DONE_WAIT_SERIALIZE)) goto wait_for_idle; + return rc; + wait_for_idle: pending_cnt = atomic_read(&phys_enc->pending_kickoff_cnt); for (i = 0; i < pending_cnt; i++) @@ -1499,7 +1510,8 @@ wait_for_idle: phys_enc->hw_pp->idx - PINGPONG_0, phys_enc->frame_trigger_mode, atomic_read(&phys_enc->pending_kickoff_cnt), - phys_enc->enable_state, rc); + phys_enc->enable_state, + cmd_enc->wr_ptr_wait_success, scheduler_status, rc); SDE_ERROR("pp:%d failed wait_for_idle: %d\n", phys_enc->hw_pp->idx - PINGPONG_0, rc); if (phys_enc->enable_state == SDE_ENC_ERR_NEEDS_HW_RESET) diff --git a/drivers/gpu/drm/msm/sde/sde_hw_ctl.h b/drivers/gpu/drm/msm/sde/sde_hw_ctl.h index 1cef1f2ef58f..dc1a65c7b058 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_ctl.h +++ b/drivers/gpu/drm/msm/sde/sde_hw_ctl.h @@ -19,6 +19,8 @@ #include "sde_hw_sspp.h" #include "sde_hw_blk.h" +#define INVALID_CTL_STATUS 0xfffff88e + /** * sde_ctl_mode_sel: Interface mode selection * SDE_CTL_MODE_SEL_VID: Video mode interface From 5eb64992b711c5edb2fdd6bee31f38e9dc3ae2b4 Mon Sep 17 00:00:00 2001 From: Raviteja Tamatam Date: Fri, 12 Jun 2020 19:48:47 +0800 Subject: [PATCH 097/592] disp: msm: sde: signal retire fence in wr_ptr timeout There can be few cases of ESD where CTL_START is cleared but wr_ptr interrupt does not come. Signaling retire fence in these cases to avoid freeze and dangling pending_retire_fence_cnt. Change-Id: I167f69dce5cbe43b4771e5056d8a73bd7587e76e Signed-off-by: Raviteja Tamatam Signed-off-by: Ray Zhang --- .../gpu/drm/msm/sde/sde_encoder_phys_cmd.c | 34 +++++++++++++------ 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c index 15123d6ee7b1..2e31261902b8 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c @@ -1392,6 +1392,7 @@ static int _sde_encoder_phys_cmd_wait_for_wr_ptr( int ret; bool frame_pending = true; struct sde_hw_ctl *ctl; + unsigned long lock_flags; if (!phys_enc || !phys_enc->hw_ctl) { SDE_ERROR("invalid argument(s)\n"); @@ -1422,18 +1423,29 @@ static int _sde_encoder_phys_cmd_wait_for_wr_ptr( ret = 0; /* - * Signaling the retire fence at wr_ptr timeout - * to allow the next commit and avoid device freeze. - * As wr_ptr timeout can occurs due to no read ptr, - * updating pending_rd_ptr_cnt here may not cover all - * cases. Hence signaling the retire fence. + * There can be few cases of ESD where CTL_START is cleared but + * wr_ptr irq doesn't come. Signaling retire fence in these + * cases to avoid freeze and dangling pending_retire_fence_cnt */ - if (sde_encoder_phys_cmd_is_master(phys_enc) && - atomic_add_unless(&phys_enc->pending_retire_fence_cnt, - -1, 0)) - phys_enc->parent_ops.handle_frame_done( - phys_enc->parent, phys_enc, - SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE); + if (!ret) { + u32 signal_retire_event = + SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE; + + SDE_EVT32(DRMID(phys_enc->parent), + SDE_EVTLOG_FUNC_CASE1); + + if (sde_encoder_phys_cmd_is_master(phys_enc) && + atomic_add_unless( + &phys_enc->pending_retire_fence_cnt, -1, 0)) { + spin_lock_irqsave(phys_enc->enc_spinlock, + lock_flags); + phys_enc->parent_ops.handle_frame_done( + phys_enc->parent, phys_enc, + signal_retire_event); + spin_unlock_irqrestore(phys_enc->enc_spinlock, + lock_flags); + } + } } cmd_enc->wr_ptr_wait_success = (ret == 0) ? true : false; From 12f7276790ead798971ac9a3b1a8c989a70a397d Mon Sep 17 00:00:00 2001 From: Ray Zhang Date: Wed, 24 Jun 2020 13:21:37 +0800 Subject: [PATCH 098/592] disp: msm: sde: avoid multiple frame-done encoder events Currently there is a race condition in checking the pending_kickoff_cnt in wr_ptr_irq wait from display-thread and pp_done_irq from interrupt context. In both places, pending_kickoff_cnt is read first and modified later. In partial update cases where the frame-transfer is short, such a race condition might happen and would lead to both triggering the frame-done/release fence for the same frame. Fix it by combining read/modify to one statement in both places. Change-Id: I9162e7dc3f12af3590514f1ebfd68023aa920181 Signed-off-by: Veera Sundaram Sankaran Signed-off-by: Ray Zhang --- drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c index 2e31261902b8..ef0f55041a9f 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c @@ -183,10 +183,7 @@ static void _sde_encoder_phys_cmd_update_intf_cfg( static void sde_encoder_phys_cmd_pp_tx_done_irq(void *arg, int irq_idx) { struct sde_encoder_phys *phys_enc = arg; - unsigned long lock_flags; - int new_cnt; - u32 event = SDE_ENCODER_FRAME_EVENT_DONE | - SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE; + u32 event = 0; if (!phys_enc || !phys_enc->hw_pp) return; @@ -195,16 +192,17 @@ static void sde_encoder_phys_cmd_pp_tx_done_irq(void *arg, int irq_idx) /* notify all synchronous clients first, then asynchronous clients */ if (phys_enc->parent_ops.handle_frame_done && - atomic_read(&phys_enc->pending_kickoff_cnt)) + atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0)) { + event = SDE_ENCODER_FRAME_EVENT_DONE | + SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE; + spin_lock(phys_enc->enc_spinlock); phys_enc->parent_ops.handle_frame_done(phys_enc->parent, phys_enc, event); - - spin_lock_irqsave(phys_enc->enc_spinlock, lock_flags); - new_cnt = atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0); - spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags); + spin_unlock(phys_enc->enc_spinlock); + } SDE_EVT32_IRQ(DRMID(phys_enc->parent), - phys_enc->hw_pp->idx - PINGPONG_0, new_cnt, event); + phys_enc->hw_pp->idx - PINGPONG_0, event); /* Signal any waiting atomic commit thread */ wake_up_all(&phys_enc->pending_kickoff_wq); From bf6b1c0600b224caf9dc9bc0b7c0128cd6b9b706 Mon Sep 17 00:00:00 2001 From: Mohammed Nayeem Ur Rahman Date: Mon, 15 Jun 2020 20:32:25 +0530 Subject: [PATCH 099/592] msm: adsprpc: Race conditions when handling the ADSP SSR Removed marking the static process is closed in ADSP SSR call back. Any way, this is handled during the PDR callback. Change-Id: I4406ad7559ef5222e8d78b545dfde0168c513eae Acked-by: Tadakamalla Krishnaiah Signed-off-by: Mohammed Nayeem Ur Rahman --- drivers/char/adsprpc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index c3823ec9bf85..cd246dd7ba40 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -3733,8 +3733,6 @@ static int fastrpc_restart_notifier_cb(struct notifier_block *nb, ctx->ssrcount++; ctx->issubsystemup = 0; mutex_unlock(&me->channel[cid].smd_mutex); - if (cid == 0) - me->staticpd_flags = 0; } else if (code == SUBSYS_RAMDUMP_NOTIFICATION) { if (me->channel[0].remoteheap_ramdump_dev && notifdata->enable_ramdump) { From 5665122cb1187c59eff4b68552ade9765a8f3670 Mon Sep 17 00:00:00 2001 From: Norbert Lange Date: Sun, 15 Sep 2019 22:03:02 +0200 Subject: [PATCH 100/592] exfat: debian: comply to debian policy for upstream_version From 5.6.12: "If there is no debian_revision then hyphens are not allowed." Also use the debhelper variables for getting upstream_version. Signed-off-by: Norbert Lange Signed-off-by: Park Ju Hyung --- debian/changelog | 2 +- debian/rules | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index d2ceafeb8284..b38e682885ec 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -exfat-dkms (5.8-1arter97) UNRELEASED; urgency=medium +exfat-dkms (5.8~1arter97) UNRELEASED; urgency=medium * Rebased to Linux mainline's drivers * Supports for kernels lower than v4.9 dropped diff --git a/debian/rules b/debian/rules index 5c9a58b14e9f..1ea3e72c982b 100755 --- a/debian/rules +++ b/debian/rules @@ -2,7 +2,7 @@ include /usr/share/dpkg/pkg-info.mk -version := $(shell dpkg-parsechangelog | grep '^Version:' | cut -d' ' -f2) +version := $(shell echo $(DEB_VERSION_UPSTREAM) | sed -e 's/~[^~]*$$//') targetdir := debian/tmp/usr/src/exfat-$(version) %: From b7832cada19054685ff5283f89536d7509c959a4 Mon Sep 17 00:00:00 2001 From: "Hyeongseok.Kim" Date: Tue, 9 Jun 2020 14:30:44 +0900 Subject: [PATCH 101/592] exfat: Set the unused characters of FileName field to the value 0000h Some fsck tool complain that padding part of the FileName field is not set to the value 0000h. So let's maintain filesystem cleaner, as exfat's spec. recommendation. Signed-off-by: Hyeongseok.Kim Reviewed-by: Sungjong Seo Signed-off-by: Namjae Jeon Signed-off-by: Park Ju Hyung --- dir.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/dir.c b/dir.c index 71de965cc6a1..5377c3506f7e 100644 --- a/dir.c +++ b/dir.c @@ -424,10 +424,12 @@ static void exfat_init_name_entry(struct exfat_dentry *ep, ep->dentry.name.flags = 0x0; for (i = 0; i < EXFAT_FILE_NAME_LEN; i++) { - ep->dentry.name.unicode_0_14[i] = cpu_to_le16(*uniname); - if (*uniname == 0x0) - break; - uniname++; + if (*uniname != 0x0) { + ep->dentry.name.unicode_0_14[i] = cpu_to_le16(*uniname); + uniname++; + } else { + ep->dentry.name.unicode_0_14[i] = 0x0; + } } } From 5d1ce78d0c9fd2b5f380635c529a46483f39a3a9 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 10 Jun 2020 20:22:13 +0300 Subject: [PATCH 102/592] exfat: add missing brelse() calls on error paths If the second exfat_get_dentry() call fails then we need to release "old_bh" before returning. There is a similar bug in exfat_move_file(). Fixes: 5f2aa075070c ("exfat: add inode operations") Reported-by: Markus Elfring Signed-off-by: Dan Carpenter Signed-off-by: Namjae Jeon Signed-off-by: Park Ju Hyung --- namei.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/namei.c b/namei.c index de8b324171b3..821a73c9df8c 100644 --- a/namei.c +++ b/namei.c @@ -1075,10 +1075,14 @@ static int exfat_rename_file(struct inode *inode, struct exfat_chain *p_dir, epold = exfat_get_dentry(sb, p_dir, oldentry + 1, &old_bh, §or_old); + if (!epold) + return -EIO; epnew = exfat_get_dentry(sb, p_dir, newentry + 1, &new_bh, §or_new); - if (!epold || !epnew) + if (!epnew) { + brelse(old_bh); return -EIO; + } memcpy(epnew, epold, DENTRY_SIZE); exfat_update_bh(sb, new_bh, sync); @@ -1159,10 +1163,14 @@ static int exfat_move_file(struct inode *inode, struct exfat_chain *p_olddir, epmov = exfat_get_dentry(sb, p_olddir, oldentry + 1, &mov_bh, §or_mov); + if (!epmov) + return -EIO; epnew = exfat_get_dentry(sb, p_newdir, newentry + 1, &new_bh, §or_new); - if (!epmov || !epnew) + if (!epnew) { + brelse(mov_bh); return -EIO; + } memcpy(epnew, epmov, DENTRY_SIZE); exfat_update_bh(sb, new_bh, IS_DIRSYNC(inode)); From 1ae21e894673b0697cd81918b05a20df38ebe607 Mon Sep 17 00:00:00 2001 From: Hyunchul Lee Date: Tue, 16 Jun 2020 14:34:45 +0900 Subject: [PATCH 103/592] exfat: call sync_filesystem for read-only remount We need to commit dirty metadata and pages to disk before remounting exfat as read-only. This fixes a failure in xfstests generic/452 generic/452 does the following: cp something / mount -o remount,ro the /something is corrupted. because while exfat is remounted as read-only, exfat doesn't have a chance to commit metadata and vfs invalidates page caches in a block device. Signed-off-by: Hyunchul Lee Acked-by: Sungjong Seo Signed-off-by: Namjae Jeon Signed-off-by: Park Ju Hyung --- super.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/super.c b/super.c index 3becb0431504..e4edeb68a192 100644 --- a/super.c +++ b/super.c @@ -19,6 +19,8 @@ #include "exfat_fs.h" static int exfat_init_sb_info(struct super_block *sb); +static int exfat_parse_options(struct super_block *sb, char *options, int silent, + struct exfat_mount_options *opts); static char exfat_default_iocharset[] = CONFIG_EXFAT_DEFAULT_IOCHARSET; static struct kmem_cache *exfat_inode_cachep; @@ -182,6 +184,22 @@ static void exfat_free_inode(struct inode *inode) kmem_cache_free(exfat_inode_cachep, EXFAT_I(inode)); } +static int exfat_remount(struct super_block *sb, int *flags, char *opt) +{ + int ret = 0; + + *flags |= SB_NODIRATIME; + + /* volume flag will be updated in exfat_sync_fs */ + sync_filesystem(sb); + + ret = exfat_parse_options(sb, opt, 0, &EXFAT_SB(sb)->options); + if (ret) + exfat_err(sb, "failed to parse options"); + + return ret; +} + static const struct super_operations exfat_sops = { .alloc_inode = exfat_alloc_inode, #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0) @@ -195,6 +213,7 @@ static const struct super_operations exfat_sops = { .sync_fs = exfat_sync_fs, .statfs = exfat_statfs, .show_options = exfat_show_options, + .remount_fs = exfat_remount, }; enum { From d22017b6ba91f0fe35c4afc983f0a38465b200d0 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Wed, 17 Jun 2020 12:17:18 +0900 Subject: [PATCH 104/592] exfat: move setting VOL_DIRTY over exfat_remove_entries() Move setting VOL_DIRTY over exfat_remove_entries() to avoid unneeded leaving VOL_DIRTY on -ENOTEMPTY. Fixes: 5f2aa075070c ("exfat: add inode operations") Cc: stable@vger.kernel.org # v5.7 Reported-by: Tetsuhiro Kohada Reviewed-by: Sungjong Seo Signed-off-by: Namjae Jeon Signed-off-by: Park Ju Hyung --- namei.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/namei.c b/namei.c index 821a73c9df8c..f0a625e9c9a9 100644 --- a/namei.c +++ b/namei.c @@ -973,7 +973,6 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry) goto unlock; } - exfat_set_vol_flags(sb, VOL_DIRTY); exfat_chain_set(&clu_to_free, ei->start_clu, EXFAT_B_TO_CLU_ROUND_UP(i_size_read(inode), sbi), ei->flags); @@ -1000,6 +999,7 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry) num_entries++; brelse(bh); + exfat_set_vol_flags(sb, VOL_DIRTY); err = exfat_remove_entries(dir, &cdir, entry, 0, num_entries); if (err) { exfat_err(sb, "failed to exfat_remove_entries : err(%d)", err); From de5cb232ee7baa06f45ef132d4b342e4151fe166 Mon Sep 17 00:00:00 2001 From: Sungjong Seo Date: Thu, 18 Jun 2020 20:43:26 +0900 Subject: [PATCH 105/592] exfat: flush dirty metadata in fsync generic_file_fsync() exfat used could not guarantee the consistency of a file because it has flushed not dirty metadata but only dirty data pages for a file. Instead of that, use exfat_file_fsync() for files and directories so that it guarantees to commit both the metadata and data pages for a file. Signed-off-by: Sungjong Seo Signed-off-by: Namjae Jeon Signed-off-by: Park Ju Hyung --- dir.c | 2 +- exfat_fs.h | 1 + file.c | 19 ++++++++++++++++++- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/dir.c b/dir.c index 5377c3506f7e..a54ac925955e 100644 --- a/dir.c +++ b/dir.c @@ -308,7 +308,7 @@ const struct file_operations exfat_dir_operations = { .llseek = generic_file_llseek, .read = generic_read_dir, .iterate = exfat_iterate, - .fsync = generic_file_fsync, + .fsync = exfat_file_fsync, }; int exfat_alloc_new_dir(struct inode *inode, struct exfat_chain *clu) diff --git a/exfat_fs.h b/exfat_fs.h index cebc491ce9e8..99796391ff26 100644 --- a/exfat_fs.h +++ b/exfat_fs.h @@ -431,6 +431,7 @@ int exfat_getattr(const struct path *path, struct kstat *stat, #else int exfat_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat); #endif +int exfat_file_fsync(struct file *file, loff_t start, loff_t end, int datasync); /* namei.c */ extern const struct dentry_operations exfat_dentry_ops; diff --git a/file.c b/file.c index 834d1808cbe5..50565d3a4433 100644 --- a/file.c +++ b/file.c @@ -6,6 +6,7 @@ #include #include #include +#include #include "exfat_fs.h" @@ -367,12 +368,28 @@ out: return error; } +int exfat_file_fsync(struct file *filp, loff_t start, loff_t end, int datasync) +{ + struct inode *inode = filp->f_mapping->host; + int err; + + err = __generic_file_fsync(filp, start, end, datasync); + if (err) + return err; + + err = sync_blockdev(inode->i_sb->s_bdev); + if (err) + return err; + + return blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL); +} + const struct file_operations exfat_file_operations = { .llseek = generic_file_llseek, .read_iter = generic_file_read_iter, .write_iter = generic_file_write_iter, .mmap = generic_file_mmap, - .fsync = generic_file_fsync, + .fsync = exfat_file_fsync, .splice_read = generic_file_splice_read, .splice_write = iter_file_splice_write, }; From 417a031eab05b4306ccaa535125b2c4dba147b87 Mon Sep 17 00:00:00 2001 From: Park Ju Hyung Date: Wed, 1 Jul 2020 02:51:47 +0900 Subject: [PATCH 106/592] exfat: fix sanity-checks on allow_utime and discard mount options These checks should be done after opts is properly populated. Fixes: 0b27bc5e1520 ("exfat: remove use of fs_parser") Signed-off-by: Park Ju Hyung --- super.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/super.c b/super.c index e4edeb68a192..804bc4e9a3ac 100644 --- a/super.c +++ b/super.c @@ -367,6 +367,17 @@ static int exfat_parse_options(struct super_block *sb, char *options, int silent } } + if (opts->allow_utime == (unsigned short)-1) + opts->allow_utime = ~opts->fs_dmask & 0022; + + if (opts->discard) { + struct request_queue *q = bdev_get_queue(sb->s_bdev); + + if (!blk_queue_discard(q)) { + exfat_warn(sb, "mounting with \"discard\" option, but the device does not support discard"); + opts->discard = 0; + } + } out: return 0; } @@ -665,18 +676,6 @@ static int exfat_fill_super(struct super_block *sb, void *data, int silent) sbi = sb->s_fs_info; opts = &sbi->options; - if (opts->allow_utime == (unsigned short)-1) - opts->allow_utime = ~opts->fs_dmask & 0022; - - if (opts->discard) { - struct request_queue *q = bdev_get_queue(sb->s_bdev); - - if (!blk_queue_discard(q)) { - exfat_warn(sb, "mounting with \"discard\" option, but the device does not support discard"); - opts->discard = 0; - } - } - sb->s_flags |= SB_NODIRATIME; sb->s_magic = EXFAT_SUPER_MAGIC; sb->s_op = &exfat_sops; From 0cffd95894a4b97d03a3494f6cdcf8770334b1ff Mon Sep 17 00:00:00 2001 From: Park Ju Hyung Date: Wed, 1 Jul 2020 02:55:46 +0900 Subject: [PATCH 107/592] exfat: limit supported kernel versions via macro Signed-off-by: Park Ju Hyung --- compat.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/compat.h b/compat.h index f959465230b8..ca207327bb26 100644 --- a/compat.h +++ b/compat.h @@ -8,6 +8,16 @@ #include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0) +#error "This driver doesn't support v5.8+, " \ + "please use the included driver from your kernel" +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0) +#error "This driver doesn't support kernel versions lower than v4.9, " \ + "please use the driver from https://github.com/arter97/exfat-linux/tree/old" +#endif + #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0) #include #else From 034f47d607c441e7fb5be3eb71d7a289ef76bc0c Mon Sep 17 00:00:00 2001 From: Park Ju Hyung Date: Wed, 1 Jul 2020 02:55:50 +0900 Subject: [PATCH 108/592] exfat: version 5.8-2arter97 Signed-off-by: Park Ju Hyung --- debian/changelog | 8 ++++++++ version.h | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index b38e682885ec..dbb799fc01f2 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,11 @@ +exfat-dkms (5.8~2arter97) UNRELEASED; urgency=medium + + * Applied fixes from Linux v5.8-rc4 + * Fixed sanity-checks on allow_utime and discard mount options + * Added build-time error messages for unsupported kernel versions + + -- Park Ju Hyung Wed, 01 Jul 2020 02:47:26 +0900 + exfat-dkms (5.8~1arter97) UNRELEASED; urgency=medium * Rebased to Linux mainline's drivers diff --git a/version.h b/version.h index d9494febec83..fb259ecd2099 100644 --- a/version.h +++ b/version.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later #define EXFAT_BASE_VERSION "5.8" -#define EXFAT_EXTRAVERSION "1" +#define EXFAT_EXTRAVERSION "2" #define EXFAT_VARIANT "arter97" #define EXFAT_VERSION EXFAT_BASE_VERSION "-" EXFAT_EXTRAVERSION EXFAT_VARIANT From fa50032c8ae16fd4c51c8df4437003d13b88aac6 Mon Sep 17 00:00:00 2001 From: Vara Reddy Date: Fri, 12 Jun 2020 19:58:53 +0800 Subject: [PATCH 109/592] drm/msm/dsi-staging: update dsi clock calculations Change updates dsi clock calculations for command mode as per recommendation. Now dsi clocks are tied to frame transer time. Propagate correct frame transfer time to hal to update mdp clocks and bandwidth needed accordingly. Change-Id: I46f9038622ddd47cc53c5f3d54229f69a7008c8a Signed-off-by: Vara Reddy Signed-off-by: Ray Zhang --- drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c | 45 ++++++------- drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h | 4 +- drivers/gpu/drm/msm/dsi-staging/dsi_defs.h | 12 ++++ drivers/gpu/drm/msm/dsi-staging/dsi_display.c | 28 +++++++- drivers/gpu/drm/msm/dsi-staging/dsi_panel.c | 65 +++++++++++++++++++ drivers/gpu/drm/msm/dsi-staging/dsi_panel.h | 3 + 6 files changed, 132 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c index 91ea89bd7ac3..798ee09ae7bf 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c @@ -840,21 +840,24 @@ int dsi_ctrl_pixel_format_to_bpp(enum dsi_pixel_format dst_format) } static int dsi_ctrl_update_link_freqs(struct dsi_ctrl *dsi_ctrl, - struct dsi_host_config *config, void *clk_handle) + struct dsi_host_config *config, void *clk_handle, + struct dsi_display_mode *mode) { int rc = 0; u32 num_of_lanes = 0; - u32 bpp; - u64 refresh_rate = TICKS_IN_MICRO_SECOND; + u32 bpp, frame_time_us; u64 h_period, v_period, bit_rate, pclk_rate, bit_rate_per_lane, byte_clk_rate, byte_intf_clk_rate; struct dsi_host_common_cfg *host_cfg = &config->common_config; struct dsi_split_link_config *split_link = &host_cfg->split_link; struct dsi_mode_info *timing = &config->video_timing; u32 bits_per_symbol = 16, num_of_symbols = 7; /* For Cphy */ + u64 dsi_transfer_time_us = mode->priv_info->dsi_transfer_time_us; + u64 min_dsi_clk_hz = mode->priv_info->min_dsi_clk_hz; - /* Get bits per pxl in desitnation format */ + /* Get bits per pxl in desitination format */ bpp = dsi_ctrl_pixel_format_to_bpp(host_cfg->dst_format); + frame_time_us = mult_frac(1000, 1000, (timing->refresh_rate)); if (host_cfg->data_lanes & DSI_DATA_LANE_0) num_of_lanes++; @@ -868,25 +871,20 @@ static int dsi_ctrl_update_link_freqs(struct dsi_ctrl *dsi_ctrl, if (split_link->split_link_enabled) num_of_lanes = split_link->lanes_per_sublink; - if (config->bit_clk_rate_hz_override == 0) { - if (config->panel_mode == DSI_OP_CMD_MODE) { - h_period = DSI_H_ACTIVE_DSC(timing); - h_period += timing->overlap_pixels; - v_period = timing->v_active; + config->common_config.num_data_lanes = num_of_lanes; + config->common_config.bpp = bpp; - do_div(refresh_rate, timing->mdp_transfer_time_us); - } else { - h_period = DSI_H_TOTAL_DSC(timing); - v_period = DSI_V_TOTAL(timing); - refresh_rate = timing->refresh_rate; - } - bit_rate = h_period * v_period * refresh_rate * bpp; - } else { + if (config->bit_clk_rate_hz_override != 0) { bit_rate = config->bit_clk_rate_hz_override * num_of_lanes; - if (host_cfg->phy_type == DSI_PHY_TYPE_CPHY) { - bit_rate *= bits_per_symbol; - do_div(bit_rate, num_of_symbols); - } + } else if (config->panel_mode == DSI_OP_CMD_MODE) { + /* Calculate the bit rate needed to match dsi transfer time */ + bit_rate = min_dsi_clk_hz * frame_time_us; + do_div(bit_rate, dsi_transfer_time_us); + bit_rate = bit_rate * num_of_lanes; + } else { + h_period = DSI_H_TOTAL_DSC(timing); + v_period = DSI_V_TOTAL(timing); + bit_rate = h_period * v_period * timing->refresh_rate * bpp; } pclk_rate = bit_rate; @@ -2935,6 +2933,7 @@ error: * dsi_ctrl_update_host_config() - update dsi host configuration * @dsi_ctrl: DSI controller handle. * @config: DSI host configuration. + * @mode: DSI host mode selected. * @flags: dsi_mode_flags modifying the behavior * * Updates driver with new Host configuration to use for host initialization. @@ -2945,6 +2944,7 @@ error: */ int dsi_ctrl_update_host_config(struct dsi_ctrl *ctrl, struct dsi_host_config *config, + struct dsi_display_mode *mode, int flags, void *clk_handle) { int rc = 0; @@ -2968,7 +2968,8 @@ int dsi_ctrl_update_host_config(struct dsi_ctrl *ctrl, * for dynamic clk switch case link frequence would * be updated dsi_display_dynamic_clk_switch(). */ - rc = dsi_ctrl_update_link_freqs(ctrl, config, clk_handle); + rc = dsi_ctrl_update_link_freqs(ctrl, config, clk_handle, + mode); if (rc) { pr_err("[%s] failed to update link frequencies, rc=%d\n", ctrl->name, rc); diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h index b839f23ce582..f99693265990 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -352,6 +352,7 @@ int dsi_ctrl_validate_timing(struct dsi_ctrl *dsi_ctrl, * dsi_ctrl_update_host_config() - update dsi host configuration * @dsi_ctrl: DSI controller handle. * @config: DSI host configuration. + * @mode: DSI host mode selected. * @flags: dsi_mode_flags modifying the behavior * @clk_handle: Clock handle for DSI clocks * @@ -363,6 +364,7 @@ int dsi_ctrl_validate_timing(struct dsi_ctrl *dsi_ctrl, */ int dsi_ctrl_update_host_config(struct dsi_ctrl *dsi_ctrl, struct dsi_host_config *config, + struct dsi_display_mode *mode, int flags, void *clk_handle); /** diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h b/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h index e479fa8e0b69..4cc58112f8f8 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h @@ -410,8 +410,10 @@ struct dsi_panel_cmd_set { * @v_sync_polarity: Polarity of VSYNC (false is active low). * @refresh_rate: Refresh rate in Hz. * @clk_rate_hz: DSI bit clock rate per lane in Hz. + * @min_dsi_clk_hz: Min DSI bit clock to transfer in vsync time. * @mdp_transfer_time_us: Specifies the mdp transfer time for command mode * panels in microseconds. + * @dsi_transfer_time_us: Specifies dsi transfer time for command mode. * @overlap_pixels: overlap pixels for certain panels. * @dsc_enabled: DSC compression enabled. * @dsc: DSC compression configuration. @@ -433,7 +435,9 @@ struct dsi_mode_info { u32 refresh_rate; u64 clk_rate_hz; + u64 min_dsi_clk_hz; u32 mdp_transfer_time_us; + u32 dsi_transfer_time_us; u32 overlap_pixels; bool dsc_enabled; struct msm_display_dsc_info *dsc; @@ -456,6 +460,8 @@ struct dsi_split_link_config { * struct dsi_host_common_cfg - Host configuration common to video and cmd mode * @dst_format: Destination pixel format. * @data_lanes: Physical data lanes to be enabled. + * @num_data_lanes: Number of physical data lanes. + * @bpp: Number of bits per pixel. * @en_crc_check: Enable CRC checks. * @en_ecc_check: Enable ECC checks. * @te_mode: Source for TE signalling. @@ -485,6 +491,8 @@ struct dsi_split_link_config { struct dsi_host_common_cfg { enum dsi_pixel_format dst_format; enum dsi_data_lanes data_lanes; + u8 num_data_lanes; + u8 bpp; bool en_crc_check; bool en_ecc_check; enum dsi_te_mode te_mode; @@ -589,7 +597,9 @@ struct dsi_host_config { * @panel_prefill_lines: Panel prefill lines for RSC * @mdp_transfer_time_us: Specifies the mdp transfer time for command mode * panels in microseconds. + * @dsi_transfer_time_us: Specifies the dsi transfer time for cmd panels. * @clk_rate_hz: DSI bit clock per lane in hz. + * @min_dsi_clk_hz: Min dsi clk per lane to transfer frame in vsync time. * @overlap_pixels: overlap pixels for certain panels. * @topology: Topology selected for the panel * @dsc: DSC compression info @@ -606,7 +616,9 @@ struct dsi_display_mode_priv_info { u32 panel_jitter_denom; u32 panel_prefill_lines; u32 mdp_transfer_time_us; + u32 dsi_transfer_time_us; u64 clk_rate_hz; + u64 min_dsi_clk_hz; u32 overlap_pixels; struct msm_display_topology topology; diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c index cf9e50a1f80d..6d14cdf29cc7 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c @@ -4570,7 +4570,7 @@ static int dsi_display_set_mode_sub(struct dsi_display *display, display_for_each_ctrl(i, display) { ctrl = &display->ctrl[i]; rc = dsi_ctrl_update_host_config(ctrl->ctrl, - &display->config, mode->dsi_mode_flags, + &display->config, mode, mode->dsi_mode_flags, display->dsi_clk_handle); if (rc) { pr_err("failed to update ctrl config\n"); @@ -4618,7 +4618,8 @@ static int dsi_display_set_mode_sub(struct dsi_display *display, display_for_each_ctrl(i, display) { ctrl = &display->ctrl[i]; rc = dsi_ctrl_update_host_config(ctrl->ctrl, &display->config, - mode->dsi_mode_flags, display->dsi_clk_handle); + mode, mode->dsi_mode_flags, + display->dsi_clk_handle); if (rc) { pr_err("[%s] failed to update ctrl config, rc=%d\n", display->name, rc); @@ -6328,6 +6329,22 @@ int dsi_display_get_modes(struct dsi_display *display, num_dfps_rates = ((!dfps_caps.dfps_support || is_cmd_mode) ? 1 : dfps_caps.dfps_list_len); + /* Calculate dsi frame transfer time */ + if (is_cmd_mode) { + dsi_panel_calc_dsi_transfer_time( + &display->panel->host_config, + &display_mode.timing); + display_mode.priv_info->dsi_transfer_time_us = + display_mode.timing.dsi_transfer_time_us; + display_mode.priv_info->min_dsi_clk_hz = + display_mode.timing.min_dsi_clk_hz; + + display_mode.priv_info->mdp_transfer_time_us = + display_mode.priv_info->dsi_transfer_time_us; + display_mode.timing.mdp_transfer_time_us = + display_mode.timing.dsi_transfer_time_us; + } + is_split_link = host->split_link.split_link_enabled; sublinks_count = host->split_link.num_sublinks; if (is_split_link && sublinks_count > 1) { @@ -6656,6 +6673,7 @@ int dsi_display_set_mode(struct dsi_display *display, { int rc = 0; struct dsi_display_mode adj_mode; + struct dsi_mode_info timing; if (!display || !mode || !display->panel) { pr_err("Invalid params\n"); @@ -6665,6 +6683,7 @@ int dsi_display_set_mode(struct dsi_display *display, mutex_lock(&display->display_lock); adj_mode = *mode; + timing = adj_mode.timing; adjust_timing_by_ctrl_count(display, &adj_mode); /*For dynamic DSI setting, use specified clock rate */ @@ -6692,6 +6711,11 @@ int dsi_display_set_mode(struct dsi_display *display, } } + pr_info("mdp_transfer_time_us=%d us\n", + adj_mode.priv_info->mdp_transfer_time_us); + pr_info("hactive= %d, vactive= %d, fps=%d", timing.h_active, + timing.v_active, timing.refresh_rate); + memcpy(display->panel->cur_mode, &adj_mode, sizeof(adj_mode)); error: mutex_unlock(&display->display_lock); diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c index 9c97298c74d6..bc1d8eb01418 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c @@ -967,6 +967,8 @@ static int dsi_panel_parse_pixel_format(struct dsi_host_common_cfg *host, return rc; } + host->bpp = bpp; + switch (bpp) { case 3: fmt = DSI_PIXEL_FORMAT_RGB111; @@ -1007,6 +1009,7 @@ static int dsi_panel_parse_lane_states(struct dsi_host_common_cfg *host, { int rc = 0; bool lane_enabled; + u32 num_of_lanes = 0; lane_enabled = utils->read_bool(utils->data, "qcom,mdss-dsi-lane-0-state"); @@ -1024,6 +1027,17 @@ static int dsi_panel_parse_lane_states(struct dsi_host_common_cfg *host, "qcom,mdss-dsi-lane-3-state"); host->data_lanes |= (lane_enabled ? DSI_DATA_LANE_3 : 0); + if (host->data_lanes & DSI_DATA_LANE_0) + num_of_lanes++; + if (host->data_lanes & DSI_DATA_LANE_1) + num_of_lanes++; + if (host->data_lanes & DSI_DATA_LANE_2) + num_of_lanes++; + if (host->data_lanes & DSI_DATA_LANE_3) + num_of_lanes++; + + host->num_data_lanes = num_of_lanes; + if (host->data_lanes == 0) { pr_err("[%s] No data lanes are enabled, rc=%d\n", name, rc); rc = -EINVAL; @@ -3616,6 +3630,57 @@ void dsi_panel_put_mode(struct dsi_display_mode *mode) kfree(mode->priv_info); } +void dsi_panel_calc_dsi_transfer_time(struct dsi_host_common_cfg *config, + struct dsi_mode_info *timing) +{ + u32 frame_time_us, nslices; + u64 min_bitclk, total_active_pixels, bits_per_line, + dsi_transfer_time_us; + struct msm_display_dsc_info *dsc = timing->dsc; + + /* Packet overlead in bits,2 bytes header + 2 bytes checksum + * + 1 byte dcs data command. + */ + const u32 packet_overhead = 56; + + /* Default time between pingpong done to TE in microsecs */ + const u32 max_tx_threshold_time = 2166; + + frame_time_us = mult_frac(1000, 1000, (timing->refresh_rate)); + + if (timing->dsc_enabled) { + nslices = (timing->h_active)/(dsc->slice_width); + /* (slice width x bit-per-pixel + packet overhead) x + * number of slices x height x fps / lane + */ + bits_per_line = ((dsc->slice_width * dsc->bpp) + + packet_overhead) * nslices; + bits_per_line = bits_per_line / (config->num_data_lanes); + + min_bitclk = (bits_per_line * timing->v_active * + timing->refresh_rate); + } else { + total_active_pixels = ((DSI_H_ACTIVE_DSC(timing) + * timing->v_active)); + /* calculate the actual bitclk needed to transfer the frame */ + min_bitclk = (total_active_pixels * (timing->refresh_rate) * + (config->bpp)); + do_div(min_bitclk, config->num_data_lanes); + } + + timing->min_dsi_clk_hz = min_bitclk; + + if (timing->clk_rate_hz) { + /* adjust the transfer time proportionately for bit clk*/ + dsi_transfer_time_us = frame_time_us * min_bitclk; + do_div(dsi_transfer_time_us, timing->clk_rate_hz); + timing->dsi_transfer_time_us = dsi_transfer_time_us; + } else { + timing->dsi_transfer_time_us = frame_time_us - + max_tx_threshold_time; + } +} + int dsi_panel_get_mode(struct dsi_panel *panel, u32 index, struct dsi_display_mode *mode, int topology_override) diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h index 4dcaf16020e5..59d99b0510cc 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h @@ -337,4 +337,7 @@ int dsi_panel_parse_esd_reg_read_configs(struct dsi_panel *panel); void dsi_panel_ext_bridge_put(struct dsi_panel *panel); +void dsi_panel_calc_dsi_transfer_time(struct dsi_host_common_cfg *config, + struct dsi_mode_info *timing); + #endif /* _DSI_PANEL_H_ */ From 1f4642125869815ec5800f1d0e56b5d70abeef22 Mon Sep 17 00:00:00 2001 From: Vara Reddy Date: Fri, 12 Jun 2020 20:19:12 +0800 Subject: [PATCH 110/592] drm/msm/dsi-staging: update frame transfer time calculations Change updates frame transfer time calculations. Frame threshold is provided as input to decide on the final transfer time. Panel dsi clock node followed by mdp transfer time node will take priority in selecting final transfer time than frame threshold time. Change-Id: I40c3abfc635cd9b338b705535612ac32e047ce6e Signed-off-by: Vara Reddy Signed-off-by: Ray Zhang Signed-off-by: Bruce Hoo --- drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c | 11 ++++++++++- drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h | 5 +++++ drivers/gpu/drm/msm/dsi-staging/dsi_display.c | 5 ++++- drivers/gpu/drm/msm/dsi-staging/dsi_panel.c | 17 ++++++++--------- drivers/gpu/drm/msm/dsi-staging/dsi_panel.h | 2 +- 5 files changed, 28 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c index 798ee09ae7bf..7e42b3469451 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c @@ -1746,7 +1746,7 @@ static int dsi_enable_io_clamp(struct dsi_ctrl *dsi_ctrl, static int dsi_ctrl_dts_parse(struct dsi_ctrl *dsi_ctrl, struct device_node *of_node) { - u32 index = 0; + u32 index = 0, frame_threshold_time_us = 0; int rc = 0; if (!dsi_ctrl || !of_node) { @@ -1775,6 +1775,15 @@ static int dsi_ctrl_dts_parse(struct dsi_ctrl *dsi_ctrl, dsi_ctrl->split_link_supported = of_property_read_bool(of_node, "qcom,split-link-supported"); + rc = of_property_read_u32(of_node, "frame-threshold-time-us", + &frame_threshold_time_us); + if (rc) { + pr_debug("frame-threshold-time not specified, defaulting\n"); + frame_threshold_time_us = 2666; + } + + dsi_ctrl->frame_threshold_time_us = frame_threshold_time_us; + return 0; } diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h index f99693265990..9198e28475bb 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h @@ -230,6 +230,9 @@ struct dsi_ctrl_interrupts { * @debugfs_root: Root for debugfs entries. * @misr_enable: Frame MISR enable/disable * @misr_cache: Cached Frame MISR value + * @frame_threshold_time_us: Frame threshold time in microseconds, where + * dsi data lane will be idle i.e from pingpong done to + * next TE for command mode. * @phy_isolation_enabled: A boolean property allows to isolate the phy from * dsi controller and run only dsi controller. * @null_insertion_enabled: A boolean property to allow dsi controller to @@ -282,6 +285,8 @@ struct dsi_ctrl { bool misr_enable; u32 misr_cache; + u32 frame_threshold_time_us; + /* Check for spurious interrupts */ unsigned long jiffies_start; unsigned int error_interrupt_count; diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c index 6d14cdf29cc7..d1a23cf37e86 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c @@ -6267,6 +6267,7 @@ int dsi_display_get_modes(struct dsi_display *display, struct dsi_display_mode **out_modes) { struct dsi_dfps_capabilities dfps_caps; + struct dsi_display_ctrl *ctrl; struct dsi_host_common_cfg *host = &display->panel->host_config; bool is_split_link, is_cmd_mode; u32 num_dfps_rates, timing_mode_count, display_mode_count; @@ -6280,6 +6281,7 @@ int dsi_display_get_modes(struct dsi_display *display, } *out_modes = NULL; + ctrl = &display->ctrl[0]; mutex_lock(&display->display_lock); @@ -6309,6 +6311,7 @@ int dsi_display_get_modes(struct dsi_display *display, for (mode_idx = 0; mode_idx < timing_mode_count; mode_idx++) { struct dsi_display_mode display_mode; int topology_override = NO_OVERRIDE; + u32 frame_threshold_us = ctrl->ctrl->frame_threshold_time_us; if (display->cmdline_timing == mode_idx) topology_override = display->cmdline_topology; @@ -6333,7 +6336,7 @@ int dsi_display_get_modes(struct dsi_display *display, if (is_cmd_mode) { dsi_panel_calc_dsi_transfer_time( &display->panel->host_config, - &display_mode.timing); + &display_mode, frame_threshold_us); display_mode.priv_info->dsi_transfer_time_us = display_mode.timing.dsi_transfer_time_us; display_mode.priv_info->min_dsi_clk_hz = diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c index bc1d8eb01418..29fd352bdcb6 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c @@ -35,8 +35,6 @@ #define DSI_PANEL_DEFAULT_LABEL "Default dsi panel" -#define DEFAULT_MDP_TRANSFER_TIME 14000 - #define DEFAULT_PANEL_JITTER_NUMERATOR 2 #define DEFAULT_PANEL_JITTER_DENOMINATOR 1 #define DEFAULT_PANEL_JITTER_ARRAY_SIZE 2 @@ -851,7 +849,7 @@ static int dsi_panel_parse_timing(struct dsi_mode_info *mode, &mode->mdp_transfer_time_us); if (rc) { pr_debug("fallback to default mdp-transfer-time-us\n"); - mode->mdp_transfer_time_us = DEFAULT_MDP_TRANSFER_TIME; + mode->mdp_transfer_time_us = 0; } display_mode->priv_info->mdp_transfer_time_us = mode->mdp_transfer_time_us; @@ -3631,21 +3629,19 @@ void dsi_panel_put_mode(struct dsi_display_mode *mode) } void dsi_panel_calc_dsi_transfer_time(struct dsi_host_common_cfg *config, - struct dsi_mode_info *timing) + struct dsi_display_mode *mode, u32 frame_threshold_us) { u32 frame_time_us, nslices; u64 min_bitclk, total_active_pixels, bits_per_line, dsi_transfer_time_us; - struct msm_display_dsc_info *dsc = timing->dsc; + struct msm_display_dsc_info *dsc = mode->timing.dsc; + struct dsi_mode_info *timing = &mode->timing; /* Packet overlead in bits,2 bytes header + 2 bytes checksum * + 1 byte dcs data command. */ const u32 packet_overhead = 56; - /* Default time between pingpong done to TE in microsecs */ - const u32 max_tx_threshold_time = 2166; - frame_time_us = mult_frac(1000, 1000, (timing->refresh_rate)); if (timing->dsc_enabled) { @@ -3675,9 +3671,12 @@ void dsi_panel_calc_dsi_transfer_time(struct dsi_host_common_cfg *config, dsi_transfer_time_us = frame_time_us * min_bitclk; do_div(dsi_transfer_time_us, timing->clk_rate_hz); timing->dsi_transfer_time_us = dsi_transfer_time_us; + } else if (mode->priv_info->mdp_transfer_time_us) { + timing->dsi_transfer_time_us = + mode->priv_info->mdp_transfer_time_us; } else { timing->dsi_transfer_time_us = frame_time_us - - max_tx_threshold_time; + frame_threshold_us; } } diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h index 59d99b0510cc..7d5a7e8c4715 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h @@ -338,6 +338,6 @@ int dsi_panel_parse_esd_reg_read_configs(struct dsi_panel *panel); void dsi_panel_ext_bridge_put(struct dsi_panel *panel); void dsi_panel_calc_dsi_transfer_time(struct dsi_host_common_cfg *config, - struct dsi_mode_info *timing); + struct dsi_display_mode *mode, u32 frame_threshold_us); #endif /* _DSI_PANEL_H_ */ From 64d303015644d2c74d7ea55dffef090762dc9b22 Mon Sep 17 00:00:00 2001 From: Vara Reddy Date: Fri, 12 Jun 2020 20:52:08 +0800 Subject: [PATCH 111/592] disp: msm: dsi: update dsi pclk in panel mode settings Change calculates and updates correct pclk that is being used to drm modes in kilo hertz. Change-Id: I7aab10c08689697120d4d7c152f30993defd36d3 Signed-off-by: Vara Reddy Signed-off-by: Ray Zhang Signed-off-by: Bruce Hoo --- drivers/gpu/drm/msm/dsi-staging/dsi_panel.c | 55 ++++++++++++--------- 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c index 29fd352bdcb6..dcdcd45c7648 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c @@ -2555,9 +2555,6 @@ static int dsi_panel_parse_phy_timing(struct dsi_display_mode *mode, u32 len, i; int rc = 0; struct dsi_display_mode_priv_info *priv_info; - u64 h_period, v_period; - u64 refresh_rate = TICKS_IN_MICRO_SECOND; - struct dsi_mode_info *timing = NULL; u64 pixel_clk_khz; if (!mode || !mode->priv_info) @@ -2581,22 +2578,19 @@ static int dsi_panel_parse_phy_timing(struct dsi_display_mode *mode, priv_info->phy_timing_len = len; }; - timing = &mode->timing; - - if (panel_mode == DSI_OP_CMD_MODE) { - h_period = DSI_H_ACTIVE_DSC(timing); - v_period = timing->v_active; - do_div(refresh_rate, priv_info->mdp_transfer_time_us); - } else { - h_period = DSI_H_TOTAL_DSC(timing); - v_period = DSI_V_TOTAL(timing); - refresh_rate = timing->refresh_rate; + if (panel_mode == DSI_OP_VIDEO_MODE) { + /* + * For command mode we update the pclk as part of + * function dsi_panel_calc_dsi_transfer_time( ) + * as we set it based on dsi clock or mdp transfer time. + */ + pixel_clk_khz = (DSI_H_TOTAL_DSC(&mode->timing) * + DSI_V_TOTAL(&mode->timing) * + mode->timing.refresh_rate); + do_div(pixel_clk_khz, 1000); + mode->pixel_clk_khz = pixel_clk_khz; } - pixel_clk_khz = h_period * v_period * refresh_rate; - do_div(pixel_clk_khz, 1000); - mode->pixel_clk_khz = pixel_clk_khz; - return rc; } @@ -3632,16 +3626,19 @@ void dsi_panel_calc_dsi_transfer_time(struct dsi_host_common_cfg *config, struct dsi_display_mode *mode, u32 frame_threshold_us) { u32 frame_time_us, nslices; - u64 min_bitclk, total_active_pixels, bits_per_line, - dsi_transfer_time_us; + u64 min_bitclk_hz, total_active_pixels, bits_per_line, pclk_rate_hz, + dsi_transfer_time_us, pixel_clk_khz; struct msm_display_dsc_info *dsc = mode->timing.dsc; struct dsi_mode_info *timing = &mode->timing; + struct dsi_display_mode *display_mode; /* Packet overlead in bits,2 bytes header + 2 bytes checksum * + 1 byte dcs data command. */ const u32 packet_overhead = 56; + display_mode = container_of(timing, struct dsi_display_mode, timing); + frame_time_us = mult_frac(1000, 1000, (timing->refresh_rate)); if (timing->dsc_enabled) { @@ -3653,22 +3650,22 @@ void dsi_panel_calc_dsi_transfer_time(struct dsi_host_common_cfg *config, packet_overhead) * nslices; bits_per_line = bits_per_line / (config->num_data_lanes); - min_bitclk = (bits_per_line * timing->v_active * + min_bitclk_hz = (bits_per_line * timing->v_active * timing->refresh_rate); } else { total_active_pixels = ((DSI_H_ACTIVE_DSC(timing) * timing->v_active)); /* calculate the actual bitclk needed to transfer the frame */ - min_bitclk = (total_active_pixels * (timing->refresh_rate) * + min_bitclk_hz = (total_active_pixels * (timing->refresh_rate) * (config->bpp)); - do_div(min_bitclk, config->num_data_lanes); + do_div(min_bitclk_hz, config->num_data_lanes); } - timing->min_dsi_clk_hz = min_bitclk; + timing->min_dsi_clk_hz = min_bitclk_hz; if (timing->clk_rate_hz) { /* adjust the transfer time proportionately for bit clk*/ - dsi_transfer_time_us = frame_time_us * min_bitclk; + dsi_transfer_time_us = frame_time_us * min_bitclk_hz; do_div(dsi_transfer_time_us, timing->clk_rate_hz); timing->dsi_transfer_time_us = dsi_transfer_time_us; } else if (mode->priv_info->mdp_transfer_time_us) { @@ -3678,6 +3675,16 @@ void dsi_panel_calc_dsi_transfer_time(struct dsi_host_common_cfg *config, timing->dsi_transfer_time_us = frame_time_us - frame_threshold_us; } + + /* Calculate pclk_khz to update modeinfo */ + pclk_rate_hz = min_bitclk_hz * frame_time_us; + do_div(pclk_rate_hz, timing->dsi_transfer_time_us); + + pixel_clk_khz = pclk_rate_hz * config->num_data_lanes; + do_div(pixel_clk_khz, config->bpp); + display_mode->pixel_clk_khz = pixel_clk_khz; + + display_mode->pixel_clk_khz = display_mode->pixel_clk_khz / 1000; } int dsi_panel_get_mode(struct dsi_panel *panel, From 33003ffcd787d8c003b0feb744115dc19af045fd Mon Sep 17 00:00:00 2001 From: Vara Reddy Date: Fri, 12 Jun 2020 21:02:54 +0800 Subject: [PATCH 112/592] dt-bindings: Add frame threshold property for dsi controller Change adds frame threshold time property in microseconds to the controller. This specifies the idle time of controller in command mode operation and is used to calculate the dsi clocks if there is no preferred clock for the panel. Change-Id: I24519602c48bffa8b13fcb49f7d3648b09733708 Signed-off-by: Vara Reddy Signed-off-by: Ray Zhang Signed-off-by: Bruce Hoo --- Documentation/devicetree/bindings/display/msm/dsi.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Documentation/devicetree/bindings/display/msm/dsi.txt b/Documentation/devicetree/bindings/display/msm/dsi.txt index 17f9d7516ffb..d9e3421c34ca 100644 --- a/Documentation/devicetree/bindings/display/msm/dsi.txt +++ b/Documentation/devicetree/bindings/display/msm/dsi.txt @@ -127,6 +127,13 @@ Optional properties: turns off PHY pmic power supply, phy ldo and DSI Lane ldo during idle screen (footswitch control off) when this property is enabled. - qcom,dsi-phy-regulator-min-datarate-bps: Minimum per lane data rate (bps) to turn on PHY regulator. +- frame-threshold-time-us: For command mode panel, this specifies the idle + time for dsi controller where no active data is + sent to the panel, as controller is done sending + active pixels. If there is no desired DSI clocks + specified, then clocks will be derived from this + threshold time, which has a default value in chipset + based on the CPU processing power. [1] Documentation/devicetree/bindings/clock/clock-bindings.txt [2] Documentation/devicetree/bindings/graph.txt @@ -178,6 +185,7 @@ Example: qcom,sync-dual-dsi; qcom,mdss-mdp-transfer-time-us = <12000>; + frame-threshold-time-us = <800>; pinctrl-names = "default", "sleep"; pinctrl-0 = <&dsi_active>; From b39742a9027aa743cdb90bfe80c277566df9ca17 Mon Sep 17 00:00:00 2001 From: Bruce Hoo Date: Fri, 12 Jun 2020 20:47:52 +0800 Subject: [PATCH 113/592] ARM: dts: msm: update frame threshold time for atoll Change adds 800 microseconds as frame threshold time for atoll as posted start feature enables us to have lower threshold time. Change-Id: I67cbc612270f866ec40a99aba200d03abe48c7cd Signed-off-by: Bruce Hoo Signed-off-by: Ray Zhang --- arch/arm64/boot/dts/qcom/atoll-sde.dtsi | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/atoll-sde.dtsi b/arch/arm64/boot/dts/qcom/atoll-sde.dtsi index af9ccda50f6f..5455b376e056 100644 --- a/arch/arm64/boot/dts/qcom/atoll-sde.dtsi +++ b/arch/arm64/boot/dts/qcom/atoll-sde.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -419,6 +419,7 @@ compatible = "qcom,dsi-ctrl-hw-v2.4"; label = "dsi-ctrl-0"; cell-index = <0>; + frame-threshold-time-us = <800>; reg = <0xae94000 0x400>, <0xaf08000 0x4>; reg-names = "dsi_ctrl", "disp_cc_base"; From 5ed908ddf9e492694346c7bf802734b3344e4a63 Mon Sep 17 00:00:00 2001 From: Vatsal Bucha Date: Thu, 18 Jun 2020 09:12:46 +0530 Subject: [PATCH 114/592] ASoC: bolero: Resolve glitch during amic record Glitch is observed during amic record due to improper sequence being followed. Reduce delay between toggle of hpf gate to depending on sample rate to resolve glitch. Change-Id: I8d9810dbc00264662f24532be9338198e6d7316d Signed-off-by: Vatsal Bucha --- 4.0/asoc/codecs/bolero/tx-macro.c | 34 ++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/4.0/asoc/codecs/bolero/tx-macro.c b/4.0/asoc/codecs/bolero/tx-macro.c index 880a6748fa0e..5fa9d6c6f619 100644 --- a/4.0/asoc/codecs/bolero/tx-macro.c +++ b/4.0/asoc/codecs/bolero/tx-macro.c @@ -175,6 +175,7 @@ struct tx_macro_priv { int dec_mode[NUM_DECIMATORS]; bool bcs_clk_en; bool hs_slow_insert_complete; + int amic_sample_rate; }; static bool tx_macro_get_data(struct snd_soc_codec *codec, @@ -494,6 +495,29 @@ static void tx_macro_tx_hpf_corner_freq_callback(struct work_struct *work) hpf_cut_off_freq << 5); snd_soc_update_bits(codec, hpf_gate_reg, 0x03, 0x02); + /* Add delay between toggle hpf gate based on sample rate */ + switch(tx_priv->amic_sample_rate) { + case 8000: + usleep_range(125, 130); + break; + case 16000: + usleep_range(62, 65); + break; + case 32000: + usleep_range(31, 32); + break; + case 48000: + usleep_range(20, 21); + break; + case 96000: + usleep_range(10, 11); + break; + case 192000: + usleep_range(5, 6); + break; + default: + usleep_range(125, 130); + } snd_soc_update_bits(codec, hpf_gate_reg, 0x03, 0x01); } else { @@ -829,6 +853,7 @@ static int tx_macro_enable_dec(struct snd_soc_dapm_widget *w, u16 dec_cfg_reg = 0; u16 hpf_gate_reg = 0; u16 tx_gain_ctl_reg = 0; + u16 tx_fs_reg = 0; u8 hpf_cut_off_freq = 0; int hpf_delay = TX_MACRO_DMIC_HPF_DELAY_MS; int unmute_delay = TX_MACRO_DMIC_UNMUTE_DELAY_MS; @@ -853,6 +878,10 @@ static int tx_macro_enable_dec(struct snd_soc_dapm_widget *w, TX_MACRO_TX_PATH_OFFSET * decimator; tx_gain_ctl_reg = BOLERO_CDC_TX0_TX_VOL_CTL + TX_MACRO_TX_PATH_OFFSET * decimator; + tx_fs_reg = BOLERO_CDC_TX0_TX_PATH_CTL + + TX_MACRO_TX_PATH_OFFSET * decimator; + + tx_priv->amic_sample_rate = (snd_soc_read(codec, tx_fs_reg) & 0x0F); switch (event) { case SND_SOC_DAPM_PRE_PMU: @@ -880,7 +909,7 @@ static int tx_macro_enable_dec(struct snd_soc_dapm_widget *w, break; case SND_SOC_DAPM_POST_PMU: snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x20, 0x20); - if (!(is_amic_enabled(codec, decimator) < BOLERO_ADC_MAX)) { + if (!is_amic_enabled(codec, decimator)) { snd_soc_update_bits(codec, hpf_gate_reg, 0x01, 0x00); /* @@ -948,8 +977,7 @@ static int tx_macro_enable_dec(struct snd_soc_dapm_widget *w, snd_soc_update_bits(codec, dec_cfg_reg, TX_HPF_CUT_OFF_FREQ_MASK, hpf_cut_off_freq << 5); - if (is_amic_enabled(codec, decimator) < - BOLERO_ADC_MAX) + if (is_amic_enabled(codec, decimator)) snd_soc_update_bits(codec, hpf_gate_reg, 0x03, 0x02); From 74101d027320c752390cd0a73674d0be7bd170ae Mon Sep 17 00:00:00 2001 From: Jianmin Zhu Date: Mon, 6 Jan 2020 15:44:09 +0800 Subject: [PATCH 115/592] qcacld-3.0: Fix assert in sme_store_nss_chains_cfg Check whether vdev is NULL when pass to sme_store_nss_chains_cfg. Change-Id: I1bfa62c8a898ad28e7771e27583e5775d515924a CRs-Fixed: 2597475 --- core/hdd/src/wlan_hdd_main.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index c30f848e7fcd..cace88bf45b2 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -4749,7 +4749,11 @@ hdd_store_nss_chains_cfg_in_vdev(struct hdd_adapter *adapter) hdd_fill_nss_chain_params(hdd_ctx, &vdev_ini_cfg, adapter->device_mode); /* Store the nss chain config into the vdev */ - sme_store_nss_chains_cfg_in_vdev(adapter->vdev, &vdev_ini_cfg); + if (adapter->vdev) + sme_store_nss_chains_cfg_in_vdev(adapter->vdev, &vdev_ini_cfg); + else + hdd_err("Vdev is NULL"); + } #ifdef WLAN_FEATURE_NAN From 0906dbbf20fa8dcc0ac929e8ce95310746464f32 Mon Sep 17 00:00:00 2001 From: nshrivas Date: Thu, 2 Jul 2020 05:49:09 -0700 Subject: [PATCH 116/592] Release 5.2.03.28W Release 5.2.03.28W Change-Id: I133e6793e59009330a2c0b077e2acc8f1e4a632e CRs-Fixed: 774533 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index 80b3729ec5ab..ced704c921cb 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -32,9 +32,9 @@ #define QWLAN_VERSION_MAJOR 5 #define QWLAN_VERSION_MINOR 2 #define QWLAN_VERSION_PATCH 03 -#define QWLAN_VERSION_EXTRA "V" +#define QWLAN_VERSION_EXTRA "W" #define QWLAN_VERSION_BUILD 28 -#define QWLAN_VERSIONSTR "5.2.03.28V" +#define QWLAN_VERSIONSTR "5.2.03.28W" #endif /* QWLAN_VERSION_H */ From 6119533eea33d1b6d6936fda0aec24bd9d6fc13e Mon Sep 17 00:00:00 2001 From: Jianmin Zhu Date: Fri, 12 Jun 2020 08:46:12 +0800 Subject: [PATCH 117/592] qcacld-3.0: Add reference when access vdev adapter->vdev should never be referenced directly, and instead must be accessed only via hdd_objmgr_get_vdev() and hdd_objmgr_put_vdev() so that proper reference counting is enforced. Change-Id: Ib3efc05426105494f13ada7efed6175f88c5d141 CRs-Fixed: 2708758 --- core/hdd/src/wlan_hdd_main.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index cace88bf45b2..b453893c3fdb 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -4744,16 +4744,19 @@ hdd_store_nss_chains_cfg_in_vdev(struct hdd_adapter *adapter) { struct mlme_nss_chains vdev_ini_cfg; struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + struct wlan_objmgr_vdev *vdev; /* Populate the nss chain params from ini for this vdev type */ hdd_fill_nss_chain_params(hdd_ctx, &vdev_ini_cfg, adapter->device_mode); + vdev = hdd_objmgr_get_vdev(adapter); /* Store the nss chain config into the vdev */ - if (adapter->vdev) + if (vdev) { sme_store_nss_chains_cfg_in_vdev(adapter->vdev, &vdev_ini_cfg); - else + hdd_objmgr_put_vdev(vdev); + } else { hdd_err("Vdev is NULL"); - + } } #ifdef WLAN_FEATURE_NAN From a5fe13c688386881ae970664409661836ee95f62 Mon Sep 17 00:00:00 2001 From: nshrivas Date: Thu, 2 Jul 2020 06:57:50 -0700 Subject: [PATCH 118/592] Release 5.2.03.28X Release 5.2.03.28X Change-Id: I0d3671d5e6932c84f3994dc88fb15ba9be614c8c CRs-Fixed: 774533 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index ced704c921cb..37669e48da88 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -32,9 +32,9 @@ #define QWLAN_VERSION_MAJOR 5 #define QWLAN_VERSION_MINOR 2 #define QWLAN_VERSION_PATCH 03 -#define QWLAN_VERSION_EXTRA "W" +#define QWLAN_VERSION_EXTRA "X" #define QWLAN_VERSION_BUILD 28 -#define QWLAN_VERSIONSTR "5.2.03.28W" +#define QWLAN_VERSIONSTR "5.2.03.28X" #endif /* QWLAN_VERSION_H */ From 5b73d4239a584646543b0a742e2945904f50e682 Mon Sep 17 00:00:00 2001 From: Vevek Venkatesan Date: Fri, 26 Jun 2020 18:04:29 +0530 Subject: [PATCH 119/592] qcacld-3.0: initialize peer hang_data in recovery_notifier_cb Initialize peer_hang_data in ol_peer_recovery_notifier_cb. Change-Id: I04d819ba9048b1877dadd4d0678424f2e6fa5b1a CRs-Fixed: 2719727 --- core/dp/txrx/ol_txrx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/dp/txrx/ol_txrx.c b/core/dp/txrx/ol_txrx.c index c53d00b4aa41..bc83a452b27e 100644 --- a/core/dp/txrx/ol_txrx.c +++ b/core/dp/txrx/ol_txrx.c @@ -138,7 +138,7 @@ int ol_peer_recovery_notifier_cb(struct notifier_block *block, struct qdf_notifer_data *notif_data = data; qdf_notif_block *notif_block; struct ol_txrx_peer_t *peer; - struct peer_hang_data hang_data; + struct peer_hang_data hang_data = {0}; enum peer_debug_id_type dbg_id; if (!data || !block) From c1e8b32b20f10d3ecc9e1ee645f5dec0a378d1f3 Mon Sep 17 00:00:00 2001 From: nshrivas Date: Thu, 2 Jul 2020 10:49:10 -0700 Subject: [PATCH 120/592] Release 5.2.03.28Y Release 5.2.03.28Y Change-Id: I9b6bb9fc181458f591a2cd7175f16f4a9fccaaa0 CRs-Fixed: 774533 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index 37669e48da88..b90300fc4dbb 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -32,9 +32,9 @@ #define QWLAN_VERSION_MAJOR 5 #define QWLAN_VERSION_MINOR 2 #define QWLAN_VERSION_PATCH 03 -#define QWLAN_VERSION_EXTRA "X" +#define QWLAN_VERSION_EXTRA "Y" #define QWLAN_VERSION_BUILD 28 -#define QWLAN_VERSIONSTR "5.2.03.28X" +#define QWLAN_VERSIONSTR "5.2.03.28Y" #endif /* QWLAN_VERSION_H */ From bea5e5cf48cf1e87535c57dd970d9ebef7423f21 Mon Sep 17 00:00:00 2001 From: Vevek Venkatesan Date: Wed, 24 Jun 2020 17:13:05 +0530 Subject: [PATCH 121/592] qcacmn: fix format specifier in qdf_dpt_dump_stats_debugfs Fix proper format specifier for qdf_debugfs_printf in qdf_dpt_dump_stats_debugfs. Change-Id: I3d357cb677c6419e13c3c2333b43d4cae2f2df41 CRs-Fixed: 2717408 --- qdf/linux/src/qdf_trace.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/qdf/linux/src/qdf_trace.c b/qdf/linux/src/qdf_trace.c index 6bbdc4a7d62c..0790478e3e48 100644 --- a/qdf/linux/src/qdf_trace.c +++ b/qdf/linux/src/qdf_trace.c @@ -2783,26 +2783,27 @@ QDF_STATUS qdf_dpt_dump_stats_debugfs(qdf_debugfs_file_t file, break; case QDF_DP_TRACE_HDD_TX_TIMEOUT: - qdf_debugfs_printf(file, "DPT: %04d: %s %s\n", - i, p_record.time, - qdf_dp_code_to_string(p_record.code)); - qdf_debugfs_printf(file, "%s: HDD TX Timeout\n"); + qdf_debugfs_printf( + file, "DPT: %04d: %llu %s\n", + i, p_record.time, + qdf_dp_code_to_string(p_record.code)); + qdf_debugfs_printf(file, "HDD TX Timeout\n"); break; case QDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT: - qdf_debugfs_printf(file, "%04d: %s %s\n", - i, p_record.time, - qdf_dp_code_to_string(p_record.code)); - qdf_debugfs_printf(file, - "%s: HDD SoftAP TX Timeout\n"); + qdf_debugfs_printf( + file, "DPT: %04d: %llu %s\n", + i, p_record.time, + qdf_dp_code_to_string(p_record.code)); + qdf_debugfs_printf(file, "HDD SoftAP TX Timeout\n"); break; case QDF_DP_TRACE_CE_FAST_PACKET_ERR_RECORD: - qdf_debugfs_printf(file, "DPT: %04d: %s %s\n", - i, p_record.time, - qdf_dp_code_to_string(p_record.code)); - qdf_debugfs_printf(file, - "%s: CE Fast Packet Error\n"); + qdf_debugfs_printf( + file, "DPT: %04d: %llu %s\n", + i, p_record.time, + qdf_dp_code_to_string(p_record.code)); + qdf_debugfs_printf(file, "CE Fast Packet Error\n"); break; case QDF_DP_TRACE_MAX: From 016c5d47ee074c4b1208402ad0d8fa1d2001492d Mon Sep 17 00:00:00 2001 From: Rohith Kollalsi Date: Fri, 3 Jul 2020 15:04:01 +0530 Subject: [PATCH 122/592] net: usb: Initialize retval with zero as it might be used uninitialized If at the start of usbnet_start_xmit function sk_buff is null then there is a chance that retval could be used uninitialized. To avoid such scenario initialize retval with zero. Change-Id: I2d5b68075338f7d19b6bc76a4ce7cdbe422daadb Signed-off-by: Rohith Kollalsi --- drivers/net/usb/usbnet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 854ca8cd57a9..df99787836cd 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -1442,7 +1442,7 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb, struct skb_data *entry; struct driver_info *info = dev->driver_info; unsigned long flags; - int retval; + int retval = 0; struct timespec64 now; if (skb) From c24fa13873560351f3e3ed7828d7329eb08ef718 Mon Sep 17 00:00:00 2001 From: Ganesh Keethol Date: Tue, 26 May 2020 20:03:13 +0530 Subject: [PATCH 123/592] soc: qcom: bgcom: use pm_runtime_status_suspended of spi use pm_runtime_status_suspended of spi driver to confirm if spi resource is released. Change-Id: Id343077983645869222393ea7debf3c121b885fa Signed-off-by: Ganesh Keethol --- drivers/soc/qcom/bgcom_interface.c | 5 ----- drivers/soc/qcom/bgcom_spi.c | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/soc/qcom/bgcom_interface.c b/drivers/soc/qcom/bgcom_interface.c index bcb51a249e54..0705bc7ad16d 100644 --- a/drivers/soc/qcom/bgcom_interface.c +++ b/drivers/soc/qcom/bgcom_interface.c @@ -45,7 +45,6 @@ #define MPPS_DOWN_EVENT_TO_BG_TIMEOUT 3000 #define ADSP_DOWN_EVENT_TO_BG_TIMEOUT 3000 -#define SLEEP_FOR_SPI_BUS 2000 enum { SSR_DOMAIN_BG, @@ -401,8 +400,6 @@ static long bg_com_ioctl(struct file *filp, break; case SET_SPI_BUSY: ret = bgcom_set_spi_state(BGCOM_SPI_BUSY); - /* Add sleep for SPI Bus to release*/ - msleep(SLEEP_FOR_SPI_BUS); break; case BG_SOFT_RESET: ret = bg_soft_reset(); @@ -619,8 +616,6 @@ static int ssr_bg_cb(struct notifier_block *this, send_uevent(&bge); break; case SUBSYS_AFTER_SHUTDOWN: - /* Add sleep for SPI Bus to release*/ - msleep(SLEEP_FOR_SPI_BUS); if (dev->pending_bg_twm_wear_load) { /* Load bg-twm-wear */ dev->pending_bg_twm_wear_load = false; diff --git a/drivers/soc/qcom/bgcom_spi.c b/drivers/soc/qcom/bgcom_spi.c index e7993251a4d8..66343e58c06d 100644 --- a/drivers/soc/qcom/bgcom_spi.c +++ b/drivers/soc/qcom/bgcom_spi.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "bgcom.h" #include "bgrsb.h" #include "bgcom_interface.h" @@ -160,6 +161,10 @@ int bgcom_set_spi_state(enum bgcom_spi_state state) { struct bg_spi_priv *bg_spi = container_of(bg_com_drv, struct bg_spi_priv, lhandle); + struct device spi_dev = bg_spi->spi->master->dev; + ktime_t time_start, delta; + s64 time_elapsed; + if (state < 0 || state > 1) return -EINVAL; @@ -167,6 +172,15 @@ int bgcom_set_spi_state(enum bgcom_spi_state state) return 0; mutex_lock(&bg_spi->xfer_mutex); + if (state == BGCOM_SPI_BUSY) { + time_start = ktime_get(); + while (!pm_runtime_status_suspended(spi_dev.parent)) { + delta = ktime_sub(ktime_get(), time_start); + time_elapsed = ktime_to_ms(delta); + BUG_ON(time_elapsed > 5 * MSEC_PER_SEC); + msleep(100); + } + } spi_state = state; mutex_unlock(&bg_spi->xfer_mutex); return 0; From 7d18654d012133579377f3a4e9511b0354493e24 Mon Sep 17 00:00:00 2001 From: Surabhi Vishnoi Date: Mon, 8 Jun 2020 10:23:04 +0530 Subject: [PATCH 124/592] qcacmn: Add support for WMI_VDEV_BCN_LATENCY event Add interface changes for WMI_VDEV_BCN_LATENCY_EVENTID which is sent by firmware to indicate the latency IE received from connected AP in beacon. Change-Id: Ia6cec01be89f13885b011414f0d77f64c6eb05ee CRs-Fixed: 2723226 --- wmi/inc/wmi_unified_param.h | 1 + wmi/src/wmi_unified_tlv.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/wmi/inc/wmi_unified_param.h b/wmi/inc/wmi_unified_param.h index f5a54a46e1d8..3aaaf3f2bb91 100644 --- a/wmi/inc/wmi_unified_param.h +++ b/wmi/inc/wmi_unified_param.h @@ -5790,6 +5790,7 @@ typedef enum { #endif wmi_roam_stats_event_id, wmi_roam_scan_chan_list_id, + wmi_vdev_bcn_latency_event_id, wmi_events_max, } wmi_conv_event_id; diff --git a/wmi/src/wmi_unified_tlv.c b/wmi/src/wmi_unified_tlv.c index bbc976ce8500..e3e76bf0e698 100644 --- a/wmi/src/wmi_unified_tlv.c +++ b/wmi/src/wmi_unified_tlv.c @@ -24991,6 +24991,8 @@ static void populate_tlv_events_id(uint32_t *event_ids) event_ids[wmi_roam_scan_chan_list_id] = WMI_ROAM_SCAN_CHANNEL_LIST_EVENTID; + event_ids[wmi_vdev_bcn_latency_event_id] = + WMI_VDEV_BCN_LATENCY_EVENTID; } /** From 9ad969f6a7219940a81268eac946329aebd55756 Mon Sep 17 00:00:00 2001 From: spuligil Date: Thu, 25 Jun 2020 18:02:48 -0700 Subject: [PATCH 125/592] fw-api: CL 10859209 - update fw common interface files Change-Id: Iab1732e8763d69bcb050b765c929cfe16c055661 WMI: add VDEV_PARAM_ENABLE_DISABLE_NAN_CONFIG_FEATURES def CRs-Fixed: 2262693 --- fw/wmi_unified.h | 11 +++++++++++ fw/wmi_version.h | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/fw/wmi_unified.h b/fw/wmi_unified.h index f16457b42283..dba951717131 100644 --- a/fw/wmi_unified.h +++ b/fw/wmi_unified.h @@ -10434,6 +10434,11 @@ typedef enum { */ #define WMI_VDEV_ROAM_11KV_CTRL_DONOT_SEND_DISASSOC_ON_BTM_DI_SET 0x4 + +/** NAN vdev config Feature flags */ +#define WMI_VDEV_NAN_ALLOW_DW_CONFIG_CHANGE_IN_SYNC_ROLE 0x1 + + /** the definition of different VDEV parameters */ typedef enum { /** RTS Threshold */ @@ -11281,6 +11286,12 @@ typedef enum { */ WMI_VDEV_PARAM_ROAM_11KV_CTRL, /* 0xA2 */ + /* vdev param to enable or disable various NAN config features + * param value bitmap set to 1 for enable and 0 for disable respectively + */ + WMI_VDEV_PARAM_ENABLE_DISABLE_NAN_CONFIG_FEATURES, /* 0xA3 */ + + /*=== ADD NEW VDEV PARAM TYPES ABOVE THIS LINE === * The below vdev param types are used for prototyping, and are * prone to change. diff --git a/fw/wmi_version.h b/fw/wmi_version.h index 9c7c836fc990..9a6abc678abc 100644 --- a/fw/wmi_version.h +++ b/fw/wmi_version.h @@ -36,7 +36,7 @@ #define __WMI_VER_MINOR_ 0 /** WMI revision number has to be incremented when there is a * change that may or may not break compatibility. */ -#define __WMI_REVISION_ 854 +#define __WMI_REVISION_ 855 /** The Version Namespace should not be normally changed. Only * host and firmware of the same WMI namespace will work From bf6b1c2e81439d81b149a49cab33df8e70efddc3 Mon Sep 17 00:00:00 2001 From: spuligil Date: Fri, 26 Jun 2020 06:00:38 -0700 Subject: [PATCH 126/592] fw-api: CL 10864082 - update fw common interface files add WMI_TWT_SESSION_STATS_EVENT msg def Change-Id: I48ad89ad44216deaed2c70853fde64d8894afd97 CRs-Fixed: 2262693 --- fw/wmi_tlv_defs.h | 10 ++++++++++ fw/wmi_unified.h | 51 +++++++++++++++++++++++++++++++++++++++++++++++ fw/wmi_version.h | 2 +- 3 files changed, 62 insertions(+), 1 deletion(-) diff --git a/fw/wmi_tlv_defs.h b/fw/wmi_tlv_defs.h index e85d2481edc9..5feb474f7d92 100644 --- a/fw/wmi_tlv_defs.h +++ b/fw/wmi_tlv_defs.h @@ -1095,6 +1095,8 @@ typedef enum { WMITLV_TAG_STRUC_wmi_vdev_disconnect_event_fixed_param, WMITLV_TAG_STRUC_wmi_roam_btm_response_info_tlv_param, WMITLV_TAG_STRUC_wmi_roam_initial_info_tlv_param, + WMITLV_TAG_STRUC_wmi_pdev_twt_session_stats_event_fixed_param, + WMITLV_TAG_STRUC_wmi_twt_session_stats_info, } WMITLV_TAG_ID; /* @@ -1798,6 +1800,7 @@ typedef enum { OP(WMI_VDEV_BCN_LATENCY_EVENTID) \ OP(WMI_AUDIO_AGGR_SCHED_METHOD_EVENTID) \ OP(WMI_VDEV_DISCONNECT_EVENTID) \ + OP(WMI_TWT_SESSION_STATS_EVENTID) \ /* add new EVT_LIST elements above this line */ @@ -6025,6 +6028,13 @@ WMITLV_CREATE_PARAM_STRUC(WMI_PDEV_GET_TPC_STATS_EVENTID); WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_vdev_bcn_latency_fixed_param, wmi_vdev_bcn_latency_fixed_param, fixed_param, WMITLV_SIZE_FIX) WMITLV_CREATE_PARAM_STRUC(WMI_VDEV_BCN_LATENCY_EVENTID); +/* TWT Stats session event */ +#define WMITLV_TABLE_WMI_TWT_SESSION_STATS_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_pdev_twt_session_stats_event_fixed_param, wmi_pdev_twt_session_stats_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_twt_session_stats_info, twt_sessions, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_TWT_SESSION_STATS_EVENTID); + + #ifdef __cplusplus } #endif diff --git a/fw/wmi_unified.h b/fw/wmi_unified.h index dba951717131..d100fae80d47 100644 --- a/fw/wmi_unified.h +++ b/fw/wmi_unified.h @@ -1991,6 +1991,7 @@ typedef enum { WMI_TWT_RESUME_DIALOG_COMPLETE_EVENTID, WMI_TWT_BTWT_INVITE_STA_COMPLETE_EVENTID, WMI_TWT_BTWT_REMOVE_STA_COMPLETE_EVENTID, + WMI_TWT_SESSION_STATS_EVENTID, /** Events in Prototyping phase */ WMI_NDI_CAP_RSP_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_PROTOTYPE), @@ -31216,6 +31217,56 @@ typedef struct { */ } wmi_simulation_test_cmd_fixed_param; +#define WMI_TWT_SESSION_FLAG_FLOW_ID_GET(_var) WMI_GET_BITS(_var, 0, 16) +#define WMI_TWT_SESSION_FLAG_FLOW_ID_SET(_var, _val) WMI_SET_BITS(_var, 0, 16, _val) + +#define WMI_TWT_SESSION_FLAG_BCAST_TWT_GET(_var) WMI_GET_BITS(_var, 16, 1) +#define WMI_TWT_SESSION_FLAG_BCAST_TWT_SET(_var, _val) WMI_SET_BITS(_var, 16, 1, _val) + +#define WMI_TWT_SESSION_FLAG_TRIGGER_TWT_GET(_var) WMI_GET_BITS(_var, 17, 1) +#define WMI_TWT_SESSION_FLAG_TRIGGER_TWT_SET(_var, _val) WMI_SET_BITS(_var, 17, 1, _val) + +#define WMI_TWT_SESSION_FLAG_ANNOUN_TWT_GET(_var) WMI_GET_BITS(_var, 18, 1) +#define WMI_TWT_SESSION_FLAG_ANNOUN_TWT_SET(_var, _val) WMI_SET_BITS(_var, 18, 1, _val) + +typedef struct { + /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_twt_session_stats_info */ + A_UINT32 tlv_hdr; + + A_UINT32 vdev_id; + wmi_mac_addr peer_mac; + A_UINT32 event_type; /* event type - defined in enum wmi_twt_session_stats_type */ + /* + * Flags to provide information on TWT session and session types. + * This field is filled with the bitwise combination of the flag values + * defined by WMI_TWT_SESSION_FLAG_xxx + */ + A_UINT32 flow_id_flags; + A_UINT32 dialog_id; + A_UINT32 wake_dura_us; + A_UINT32 wake_intvl_us; + /* this long time after TWT resumed the 1st Service Period will start */ + A_UINT32 sp_offset_us; +} wmi_twt_session_stats_info; + +enum wmi_twt_session_stats_type { + WMI_TWT_SESSION_SETUP = 1, + WMI_TWT_SESSION_TEARDOWN = 2, + WMI_TWT_SESSION_UPDATE = 3, +}; + +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_pdev_twt_session_stats_event_fixed_param */ + A_UINT32 tlv_header; + + A_UINT32 pdev_id; /* ID of the pdev this response belongs to */ + + /* The TLVs follows this structure: + * wmi_twt_session_stats_info twt_sessions[]; <--- Array of twt_session. + */ +} wmi_pdev_twt_session_stats_event_fixed_param; + /* ADD NEW DEFS HERE */ diff --git a/fw/wmi_version.h b/fw/wmi_version.h index 9a6abc678abc..419d60eecb22 100644 --- a/fw/wmi_version.h +++ b/fw/wmi_version.h @@ -36,7 +36,7 @@ #define __WMI_VER_MINOR_ 0 /** WMI revision number has to be incremented when there is a * change that may or may not break compatibility. */ -#define __WMI_REVISION_ 855 +#define __WMI_REVISION_ 856 /** The Version Namespace should not be normally changed. Only * host and firmware of the same WMI namespace will work From 2756c84c4e163b56594ec0672ccb4b1efbc15143 Mon Sep 17 00:00:00 2001 From: spuligil Date: Sat, 27 Jun 2020 12:00:48 -0700 Subject: [PATCH 127/592] fw-api: CL 10874626 - update fw common interface files Change-Id: I0e540333264f2c3768e44ae416e5438cd2d84899 WMI: add MBSS capability flags in vdev start cmd CRs-Fixed: 2262693 --- fw/wmi_services.h | 1 + fw/wmi_unified.h | 21 +++++++++++++++++++-- fw/wmi_version.h | 2 +- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/fw/wmi_services.h b/fw/wmi_services.h index 6d9e867d5aa1..2388b88823db 100644 --- a/fw/wmi_services.h +++ b/fw/wmi_services.h @@ -445,6 +445,7 @@ typedef enum { WMI_REQUEST_CTRL_PATH_STATS_REQUEST = 250, /* FW supports control path stats */ WMI_SERVICE_TPC_STATS_EVENT = 251, /* FW support to dump the TPC tables */ WMI_SERVICE_NO_INTERBAND_MCC_SUPPORT = 252, /* Indicates FW doesn't support interband MCC */ + WMI_SERVICE_MBSS_PARAM_IN_VDEV_START_SUPPORT = 253, /* FW supports VDEV's MBSS param exchange in VDEV start command */ /******* ADD NEW SERVICES UP TO 256 HERE *******/ diff --git a/fw/wmi_unified.h b/fw/wmi_unified.h index d100fae80d47..6dc4a8f45859 100644 --- a/fw/wmi_unified.h +++ b/fw/wmi_unified.h @@ -9486,9 +9486,13 @@ typedef struct { * See macros starting with WMI_PDEV_ID_ for values. */ A_UINT32 pdev_id; - /** control flags for this vdev */ + /** control flags for this vdev (DEPRECATED) + * Use @mbss_capability_flags in vdev start instead. + */ A_UINT32 flags; - /** vdevid of transmitted AP (mbssid case) */ + /** vdevid of transmitted AP (mbssid case) (DEPRECATED) + * Use @vdevid_trans in vdev start instead. + */ A_UINT32 vdevid_trans; /* This TLV is followed by another TLV of array of structures * wmi_vdev_txrx_streams cfg_txrx_streams[]; @@ -10249,6 +10253,19 @@ typedef struct { A_UINT32 regdomain; /* min data rate to be used in BSS in Mbps */ A_UINT32 min_data_rate; + + /** @mbss_capability_flags: Bitmap of vdev's MBSS/EMA capability. + * Capabilities are combination of below flags: + * VDEV_FLAGS_NON_MBSSID_AP + * VDEV_FLAGS_TRANSMIT_AP + * VDEV_FLAGS_NON_TRANSMIT_AP + * VDEV_FLAGS_EMA_MODE + */ + A_UINT32 mbss_capability_flags; + + /** vdevid of transmitting VAP (mbssid case). Ignored for non mbssid case */ + A_UINT32 vdevid_trans; + /* The TLVs follows this structure: * wmi_channel chan; <-- WMI channel * wmi_p2p_noa_descriptor noa_descriptors[]; <-- actual p2p NOA descriptor from scan entry diff --git a/fw/wmi_version.h b/fw/wmi_version.h index 419d60eecb22..332eb170d6f7 100644 --- a/fw/wmi_version.h +++ b/fw/wmi_version.h @@ -36,7 +36,7 @@ #define __WMI_VER_MINOR_ 0 /** WMI revision number has to be incremented when there is a * change that may or may not break compatibility. */ -#define __WMI_REVISION_ 856 +#define __WMI_REVISION_ 857 /** The Version Namespace should not be normally changed. Only * host and firmware of the same WMI namespace will work From bb1444584479a07404b2643d1ec304855947a9f4 Mon Sep 17 00:00:00 2001 From: spuligil Date: Sun, 28 Jun 2020 06:00:40 -0700 Subject: [PATCH 128/592] fw-api: CL 10878097 - update fw common interface files Change-Id: I3138eadc6cf9f326152e67fb3271f2b47d8755d1 WMI: add pdev param for SR dB margin; HTT stats: add psr_tx flag CRs-Fixed: 2262693 --- fw/htt_ppdu_stats.h | 7 +++++-- fw/wmi_unified.h | 7 +++++++ fw/wmi_version.h | 2 +- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/fw/htt_ppdu_stats.h b/fw/htt_ppdu_stats.h index 1f70b5a8f42d..a9f25643a649 100644 --- a/fw/htt_ppdu_stats.h +++ b/fw/htt_ppdu_stats.h @@ -719,9 +719,11 @@ typedef struct { * BIT [15: 8] - RSSI of the aborted OBSS frame (in dB w.r.t. noise floor) * by which SRG/Non-SRG based spatial reuse opportunity * was created. - * BIT [31:16] - reserved + * BIT [16:16] - PPDU transmitted using PSR opportunity + * BIT [31:17] - reserved */ union { + A_UINT32 reserved__psr_tx__aborted_obss_rssi__srg_tx__non_srg_tx___bss_color_id; A_UINT32 reserved__aborted_obss_rssi__srg_tx__non_srg_tx___bss_color_id; A_UINT32 reserved__bss_color_id; struct { @@ -729,7 +731,8 @@ typedef struct { non_srg_tx: 1, srg_tx: 1, aborted_obss_rssi: 8, - reserved2: 16; + psr_tx: 1, + reserved2: 15; }; }; } htt_ppdu_stats_common_tlv; diff --git a/fw/wmi_unified.h b/fw/wmi_unified.h index 6dc4a8f45859..a26fc5196cbb 100644 --- a/fw/wmi_unified.h +++ b/fw/wmi_unified.h @@ -6844,6 +6844,13 @@ typedef enum { */ WMI_PDEV_PARAM_SET_PREAM_PUNCT_BW, + /* + * Parameter used to set the Margin dB value to be included for calculating + * the spatial reuse value in common info field of the UL Trigger frame. + * Accepted value as per Spec are 0 to 5 dB (inclusive). + */ + WMI_PDEV_PARAM_SR_TRIGGER_MARGIN, + } WMI_PDEV_PARAM; #define WMI_PDEV_ONLY_BSR_TRIG_IS_ENABLED(trig_type) WMI_GET_BITS(trig_type, 0, 1) diff --git a/fw/wmi_version.h b/fw/wmi_version.h index 332eb170d6f7..39da0fb186cc 100644 --- a/fw/wmi_version.h +++ b/fw/wmi_version.h @@ -36,7 +36,7 @@ #define __WMI_VER_MINOR_ 0 /** WMI revision number has to be incremented when there is a * change that may or may not break compatibility. */ -#define __WMI_REVISION_ 857 +#define __WMI_REVISION_ 858 /** The Version Namespace should not be normally changed. Only * host and firmware of the same WMI namespace will work From 39979d0332571b32ec1bb1152d6072e16e22c2f5 Mon Sep 17 00:00:00 2001 From: spuligil Date: Tue, 30 Jun 2020 06:00:55 -0700 Subject: [PATCH 129/592] fw-api: CL 10894153 - update fw common interface files Change-Id: I72b9f04847ff3b6e95cd88938b7ecdf8541bd100 WMI: add max AP vdevs to resource config CRs-Fixed: 2262693 --- fw/wmi_unified.h | 7 +++++++ fw/wmi_version.h | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/fw/wmi_unified.h b/fw/wmi_unified.h index a26fc5196cbb..4a77073eaf8b 100644 --- a/fw/wmi_unified.h +++ b/fw/wmi_unified.h @@ -3696,6 +3696,13 @@ typedef struct { * specified by the host's ini configuration. */ A_UINT32 max_ndi_interfaces; + + /** @brief max_ap_vaps + * Maximum number of AP mode vdevs created at any time. + * This value is minimum of the number of AP vdevs supported by + * the target and host. + */ + A_UINT32 max_ap_vaps; } wmi_resource_config; #define WMI_MSDU_FLOW_AST_ENABLE_GET(msdu_flow_config0, ast_x) \ diff --git a/fw/wmi_version.h b/fw/wmi_version.h index 39da0fb186cc..e1806c44ed62 100644 --- a/fw/wmi_version.h +++ b/fw/wmi_version.h @@ -36,7 +36,7 @@ #define __WMI_VER_MINOR_ 0 /** WMI revision number has to be incremented when there is a * change that may or may not break compatibility. */ -#define __WMI_REVISION_ 858 +#define __WMI_REVISION_ 859 /** The Version Namespace should not be normally changed. Only * host and firmware of the same WMI namespace will work From 5984a09becc45e20d4b960c1f3099aa76b6f076e Mon Sep 17 00:00:00 2001 From: spuligil Date: Tue, 30 Jun 2020 12:00:49 -0700 Subject: [PATCH 130/592] fw-api: CL 10899787 - update fw common interface files add code coverage module ID Change-Id: Ia48f213fc39066aa607b20d9f0d84675383a6edd CRs-Fixed: 2262693 --- fw/wlan_module_ids.h | 1 + 1 file changed, 1 insertion(+) diff --git a/fw/wlan_module_ids.h b/fw/wlan_module_ids.h index 13f5b1d9a38f..4e701bc241e9 100644 --- a/fw/wlan_module_ids.h +++ b/fw/wlan_module_ids.h @@ -116,6 +116,7 @@ typedef enum { WLAN_MODULE_QUIET_IE, /* 0x52 */ WLAN_MODULE_SHMEM_MGR, /* 0x53 */ WLAN_MODULE_CFIR, /* 0x54 */ /* Channel Capture */ + WLAN_MODULE_CODE_COVER, /* 0x55 */ /* code coverage */ WLAN_MODULE_ID_MAX, WLAN_MODULE_ID_INVALID = WLAN_MODULE_ID_MAX, From 39a5c371818a7a266d383520c9d1f312c7f8b6df Mon Sep 17 00:00:00 2001 From: spuligil Date: Wed, 1 Jul 2020 18:00:45 -0700 Subject: [PATCH 131/592] fw-api: CL 10917877 - update fw common interface files Change-Id: Ice552f8b689099ae124fa409df00bc10a2fb8a4f WMI: add config_roam_trigger_param TLV in ROAM TRIGGER_REASON msg CRs-Fixed: 2262693 --- fw/wmi_services.h | 1 + fw/wmi_tlv_defs.h | 4 +++- fw/wmi_unified.h | 46 ++++++++++++++++++++++++++++++++++++++++++++++ fw/wmi_version.h | 2 +- 4 files changed, 51 insertions(+), 2 deletions(-) diff --git a/fw/wmi_services.h b/fw/wmi_services.h index 2388b88823db..322e25c6de25 100644 --- a/fw/wmi_services.h +++ b/fw/wmi_services.h @@ -446,6 +446,7 @@ typedef enum { WMI_SERVICE_TPC_STATS_EVENT = 251, /* FW support to dump the TPC tables */ WMI_SERVICE_NO_INTERBAND_MCC_SUPPORT = 252, /* Indicates FW doesn't support interband MCC */ WMI_SERVICE_MBSS_PARAM_IN_VDEV_START_SUPPORT = 253, /* FW supports VDEV's MBSS param exchange in VDEV start command */ + WMI_SERVICE_CONFIGURE_ROAM_TRIGGER_PARAM_SUPPORT = 254, /* FW supports ROAM trigger configuration param TLV */ /******* ADD NEW SERVICES UP TO 256 HERE *******/ diff --git a/fw/wmi_tlv_defs.h b/fw/wmi_tlv_defs.h index 5feb474f7d92..c4f271960d39 100644 --- a/fw/wmi_tlv_defs.h +++ b/fw/wmi_tlv_defs.h @@ -1097,6 +1097,7 @@ typedef enum { WMITLV_TAG_STRUC_wmi_roam_initial_info_tlv_param, WMITLV_TAG_STRUC_wmi_pdev_twt_session_stats_event_fixed_param, WMITLV_TAG_STRUC_wmi_twt_session_stats_info, + WMITLV_TAG_STRUC_wmi_configure_roam_trigger_parameters, } WMITLV_TAG_ID; /* @@ -3287,7 +3288,8 @@ WMITLV_CREATE_PARAM_STRUC(WMI_IDLE_TRIGGER_MONITOR_CMDID); /* Enable or disable roaming trigger reason */ #define WMITLV_TABLE_WMI_ROAM_ENABLE_DISABLE_TRIGGER_REASON_CMDID(id,op,buf,len) \ - WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_roam_enable_disable_trigger_reason_fixed_param, wmi_roam_enable_disable_trigger_reason_fixed_param, fixed_param, WMITLV_SIZE_FIX) + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_roam_enable_disable_trigger_reason_fixed_param, wmi_roam_enable_disable_trigger_reason_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_configure_roam_trigger_parameters, config_roam_trigger_param, WMITLV_SIZE_VAR) WMITLV_CREATE_PARAM_STRUC(WMI_ROAM_ENABLE_DISABLE_TRIGGER_REASON_CMDID); /* DSM filter parameters */ diff --git a/fw/wmi_unified.h b/fw/wmi_unified.h index 4a77073eaf8b..703c1e4f73b5 100644 --- a/fw/wmi_unified.h +++ b/fw/wmi_unified.h @@ -14868,6 +14868,43 @@ typedef struct { **/ } wmi_roam_subnet_change_config_fixed_param; +typedef enum { + /** No change in scan mode, use legacy modes */ + ROAM_TRIGGER_SCAN_MODE_NONE = 0, + /** Trigger only partial roam scan */ + ROAM_TRIGGER_SCAN_MODE_PARTIAL, + /** Trigger only FULL roam scan */ + ROAM_TRIGGER_SCAN_MODE_FULL, + /** Don't trigger any roam scan and disconnect from AP */ + ROAM_TRIGGER_SCAN_MODE_NO_SCAN_DISCONNECTION, +} WMI_ROAM_TRIGGER_SCAN_MODE; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_configure_roam_trigger_parameters */ + A_UINT32 trigger_reason; /** Roam trigger reason from WMI_ROAM_TRIGGER_REASON_ID */ + A_UINT32 enable; /** 0 - Disable, non-zero - enable */ + A_UINT32 scan_mode; /** Scan mode from WMI_ROAM_TRIGGER_SCAN_MODE */ + /** consider roam trigger if connected AP rssi is worse than trigger_rssi_threshold */ + A_INT32 trigger_rssi_threshold; /* Units in dbm*/ + /* + * Consider AP as roam candidate only if AP rssi is better than + * cand_ap_min_rssi_threshold + */ + A_INT32 cand_ap_min_rssi_threshold; /* Units in dbm */ + /* Roam score delta in %. + * Consider AP as roam candidate only if AP score is at least + * roam_score_delta % better than connected AP score. + * Ex: roam_score_delta = 20, and connected AP score is 4000, + * then consider candidate AP only if its score is at least + * 4800 (= 4000 * 120%) + */ + A_UINT32 roam_score_delta_percentage; + /* Reason code to be filled in the response frame from STA. + Ex: Reason code in the BTM response frame + Valid values are 0 - 255 */ + A_UINT32 reason_code; +} wmi_configure_roam_trigger_parameters; + /** * WMI_ROAM_ENABLE_DISABLE_TRIGGER_REASON: * Enable or disable roaming triggers in FW. @@ -14883,6 +14920,15 @@ typedef struct { * bit value equal 0x0. */ A_UINT32 trigger_reason_bitmask; + +/** + * The following TLVs will follow this fixed_param TLV: + * + * wmi_configure_roam_trigger_parameters config_roam_trigger_param[] + * Roam trigger configuration per roam trigger. + * The number of elements in this TLV array is limited to + * WMI_ROAM_TRIGGER_EXT_REASON_MAX + */ } wmi_roam_enable_disable_trigger_reason_fixed_param; /** WMI_PROFILE_MATCH_EVENT: offload scan diff --git a/fw/wmi_version.h b/fw/wmi_version.h index e1806c44ed62..bb8e0016414b 100644 --- a/fw/wmi_version.h +++ b/fw/wmi_version.h @@ -36,7 +36,7 @@ #define __WMI_VER_MINOR_ 0 /** WMI revision number has to be incremented when there is a * change that may or may not break compatibility. */ -#define __WMI_REVISION_ 859 +#define __WMI_REVISION_ 860 /** The Version Namespace should not be normally changed. Only * host and firmware of the same WMI namespace will work From 980e3a90476b696fe9b71a2e46263c206bd1ae2e Mon Sep 17 00:00:00 2001 From: Ajay Agarwal Date: Wed, 8 Jul 2020 10:05:47 +0530 Subject: [PATCH 132/592] usb: host: xhci: Increase number of event ring segments to 4 Currently the event ring has just a single segment consisting of 256 TRBs. When features like ECM which have very fast completions due to short packet sizes are exercised, then the CPU is not able to drain the event ring as fast as the USB HW fills it up with new completion events. This leads to USB HW finding the event ring to be full which can result in watchdog error. Fix this by increasing the number of ER segments to 4. Change-Id: Icc0ed65e5042179729315a8fd96f87b8b99e87f3 Signed-off-by: Ajay Agarwal --- drivers/usb/host/xhci.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 76c839717f16..4c6519248b11 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1633,7 +1633,7 @@ struct urb_priv { * (1K bytes * 8bytes/bit) / (4*32 bits) = 64 segment entries in the table, * meaning 64 ring segments. * Initial allocated size of the ERST, in number of entries */ -#define ERST_NUM_SEGS 1 +#define ERST_NUM_SEGS 4 /* Initial allocated size of the ERST, in number of entries */ #define ERST_SIZE 64 /* Initial number of event segment rings allocated */ From a18b815f64275e0e6ccf4659d742477d1a643443 Mon Sep 17 00:00:00 2001 From: Vulupala Shashank Reddy Date: Tue, 7 Jul 2020 19:44:59 +0530 Subject: [PATCH 133/592] qcacld-3.0: Remove unnecessary clone of skb Mgmt txrx component clones skb and sends cloned skb to its clients ex: packet capture component. Remove extra allocation of skb. Change-Id: Ic130c13c9fcc52f250b52196b86c761d36a77ba2 CRs-Fixed: 2727370 --- .../core/src/wlan_pkt_capture_mgmt_txrx.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/components/pkt_capture/core/src/wlan_pkt_capture_mgmt_txrx.c b/components/pkt_capture/core/src/wlan_pkt_capture_mgmt_txrx.c index 0c427ff61cb3..38d74112b877 100644 --- a/components/pkt_capture/core/src/wlan_pkt_capture_mgmt_txrx.c +++ b/components/pkt_capture/core/src/wlan_pkt_capture_mgmt_txrx.c @@ -418,36 +418,24 @@ pkt_capture_mgmt_tx_completion(struct wlan_objmgr_pdev *pdev, /** * process_pktcapture_mgmt_rx_data_cb() - process management rx packets * @rx_params: mgmt rx event params - * @wbuf: netbuf + * @nbuf: netbuf * * Return: none */ static QDF_STATUS pkt_capture_mgmt_rx_data_cb(struct wlan_objmgr_psoc *psoc, struct wlan_objmgr_peer *peer, - qdf_nbuf_t wbuf, + qdf_nbuf_t nbuf, struct mgmt_rx_event_params *rx_params, enum mgmt_frame_type frm_type) { struct mon_rx_status txrx_status = {0}; struct ieee80211_frame *wh; uint8_t type, sub_type; - qdf_nbuf_t nbuf; - int buf_len; if (!(pkt_capture_get_pktcap_mode() & PACKET_CAPTURE_MODE_MGMT_ONLY)) return QDF_STATUS_E_FAILURE; - buf_len = qdf_nbuf_len(wbuf); - nbuf = qdf_nbuf_alloc(NULL, roundup( - buf_len + RESERVE_BYTES, 4), - RESERVE_BYTES, 4, false); - if (!nbuf) - return QDF_STATUS_E_FAILURE; - - qdf_nbuf_put_tail(nbuf, buf_len); - qdf_mem_copy(qdf_nbuf_data(nbuf), qdf_nbuf_data(wbuf), buf_len); - wh = (struct ieee80211_frame *)qdf_nbuf_data(nbuf); type = (wh)->i_fc[0] & IEEE80211_FC0_TYPE_MASK; sub_type = (wh)->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; From e45a81f7920fab0c098339d09d306e37c9ec1129 Mon Sep 17 00:00:00 2001 From: Aditya Bavanari Date: Wed, 29 Apr 2020 09:40:56 +0530 Subject: [PATCH 134/592] asoc: Add digital mute callback function for cdc dma Add a new digital mute callback function for cdc dma as it uses a different dai structure. Change-Id: I8db4e9610aee0d519ccc50975a779b9d2d8c671e Signed-off-by: Aditya Bavanari --- asoc/msm-dai-q6-v2.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/asoc/msm-dai-q6-v2.c b/asoc/msm-dai-q6-v2.c index b71091b21d81..7aae0dbe83f5 100644 --- a/asoc/msm-dai-q6-v2.c +++ b/asoc/msm-dai-q6-v2.c @@ -2645,7 +2645,6 @@ static int msm_dai_q6_set_channel_map(struct snd_soc_dai *dai, return rc; } -/* all ports with excursion logging requirement can use this digital_mute api */ static int msm_dai_q6_spk_digital_mute(struct snd_soc_dai *dai, int mute) { @@ -10596,7 +10595,8 @@ static int msm_dai_q6_cdc_dma_prepare(struct snd_pcm_substream *substream, static void msm_dai_q6_cdc_dma_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev); + struct msm_dai_q6_cdc_dma_dai_data *dai_data = + dev_get_drvdata(dai->dev); int rc = 0; if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) { @@ -10615,6 +10615,19 @@ static void msm_dai_q6_cdc_dma_shutdown(struct snd_pcm_substream *substream, clear_bit(STATUS_PORT_STARTED, dai_data->hwfree_status); } +static int msm_dai_q6_cdc_dma_digital_mute(struct snd_soc_dai *dai, + int mute) +{ + int port_id = dai->id; + struct msm_dai_q6_cdc_dma_dai_data *dai_data = + dev_get_drvdata(dai->dev); + + if (mute && !dai_data->xt_logging_disable) + afe_get_sp_xt_logging_data(port_id); + + return 0; +} + static struct snd_soc_dai_ops msm_dai_q6_cdc_dma_ops = { .prepare = msm_dai_q6_cdc_dma_prepare, .hw_params = msm_dai_q6_cdc_dma_hw_params, @@ -10627,7 +10640,7 @@ static struct snd_soc_dai_ops msm_dai_q6_cdc_wsa_dma_ops = { .hw_params = msm_dai_q6_cdc_dma_hw_params, .shutdown = msm_dai_q6_cdc_dma_shutdown, .set_channel_map = msm_dai_q6_cdc_dma_set_channel_map, - .digital_mute = msm_dai_q6_spk_digital_mute, + .digital_mute = msm_dai_q6_cdc_dma_digital_mute, }; static struct snd_soc_dai_driver msm_dai_q6_cdc_dma_dai[] = { From 5cc21d71900f0b745be67cc1253e01b7d5e9cbb1 Mon Sep 17 00:00:00 2001 From: nshrivas Date: Wed, 8 Jul 2020 11:43:38 -0700 Subject: [PATCH 135/592] Release 5.2.03.28Z Release 5.2.03.28Z Change-Id: Id6f4f1e7c11630f4994baf6380c6d8f8d14d73c9 CRs-Fixed: 774533 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index b90300fc4dbb..ab1db7811cf9 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -32,9 +32,9 @@ #define QWLAN_VERSION_MAJOR 5 #define QWLAN_VERSION_MINOR 2 #define QWLAN_VERSION_PATCH 03 -#define QWLAN_VERSION_EXTRA "Y" +#define QWLAN_VERSION_EXTRA "Z" #define QWLAN_VERSION_BUILD 28 -#define QWLAN_VERSIONSTR "5.2.03.28Y" +#define QWLAN_VERSIONSTR "5.2.03.28Z" #endif /* QWLAN_VERSION_H */ From 69a23eff74cb351adfb50ac41a79aa8a074e7db4 Mon Sep 17 00:00:00 2001 From: Surabhi Vishnoi Date: Fri, 10 Jul 2020 11:13:02 +0530 Subject: [PATCH 136/592] qcacld-3.0: Add handler for WMI_VDEV_BCN_LATENCY_EVENTID WMI_VDEV_BCN_LATENCY_EVENTID is sent by firmware when it receives the latency IE from connected AP in beacon. Add handler for this event and when latency_level received is ultra low in latency IE, update request pm qos type PM_QOS_CPU_DMA_LATENCY to level DISABLE_KRAIT_IDLE_PS_VAL to speed up CPU efficiency and irq response. This is needed for Voice and Music products where extreme low latency is needed while playing music and high power consumption is accepted. Change-Id: I3c63ef247f4f4a1add68111ef1bcee6daafd148a CRs-Fixed: 2723205 --- core/hdd/inc/wlan_hdd_main.h | 14 ++++++++++++ core/hdd/src/wlan_hdd_main.c | 20 ++++++++++++++++++ core/sme/inc/sme_api.h | 23 ++++++++++++++++++++ core/sme/inc/sme_internal.h | 3 +++ core/sme/src/common/sme_api.c | 21 ++++++++++++++++++ core/wma/inc/wma_internal.h | 20 ++++++++++++++++++ core/wma/src/wma_features.c | 40 +++++++++++++++++++++++++++++++++++ core/wma/src/wma_main.c | 6 ++++++ 8 files changed, 147 insertions(+) diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 9e548357fd2f..ed2f7a55657e 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -4132,4 +4132,18 @@ static inline void hdd_send_update_owe_info_event(struct hdd_adapter *adapter, } #endif +#if defined(CLD_PM_QOS) && defined(WLAN_FEATURE_LL_MODE) +/** + * hdd_beacon_latency_event_cb() - Callback function to get latency level + * @latency_level: latency level received from firmware + * + * Return: None + */ +void hdd_beacon_latency_event_cb(uint32_t latency_level); +#else +static inline void hdd_beacon_latency_event_cb(uint32_t latency_level) +{ +} +#endif + #endif /* end #if !defined(WLAN_HDD_MAIN_H) */ diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index b453893c3fdb..e7c5db79d79d 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -13223,6 +13223,12 @@ int hdd_register_cb(struct hdd_context *hdd_ctx) sme_set_roam_scan_ch_event_cb(mac_handle, hdd_get_roam_scan_ch_cb); + status = sme_set_beacon_latency_event_cb(mac_handle, + hdd_beacon_latency_event_cb); + if (QDF_IS_STATUS_ERROR(status)) + hdd_err_rl("Register beacon latency event callback failed"); + + hdd_exit(); return ret; @@ -16530,6 +16536,20 @@ void hdd_hidden_ssid_enable_roaming(hdd_handle_t hdd_handle, uint8_t vdev_id) wlan_hdd_enable_roaming(adapter); } +#if defined(CLD_PM_QOS) && defined(WLAN_FEATURE_LL_MODE) +void hdd_beacon_latency_event_cb(uint32_t latency_level) +{ + struct hdd_context *hdd_ctx; + + hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); + if (!hdd_ctx) { + hdd_err_rl("Invalid HDD_CTX"); + return; + } + wlan_hdd_set_wlm_mode(hdd_ctx, latency_level); +} +#endif + #ifdef WLAN_FEATURE_PKT_CAPTURE /** diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index c1c5da5ef686..61add962964c 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -3238,4 +3238,27 @@ QDF_STATUS sme_handle_peer_cleanup(tHalHandle hal, uint8_t vdev_id); */ QDF_STATUS sme_update_owe_info(tpAniSirGlobal mac, tSirSmeAssocInd *assoc_ind); + +#if defined(CLD_PM_QOS) && defined(WLAN_FEATURE_LL_MODE) +/** + * sme_set_beacon_latency_event_cb() - Register beacon latency IE callback + * @mac_handle: Opaque handle to the MAC context + * @beacon_latency_event_cb: callback to be registered + * + * Return: QDF_STATUS + */ +QDF_STATUS +sme_set_beacon_latency_event_cb(mac_handle_t mac_handle, + void (*beacon_latency_event_cb) + (uint32_t latency_level)); +#else +static inline QDF_STATUS +sme_set_beacon_latency_event_cb(mac_handle_t mac_handle, + void (*beacon_latency_event_cb) + (uint32_t latency_level)) +{ + return QDF_STATUS_SUCCESS; +} +#endif + #endif /* #if !defined( __SME_API_H ) */ diff --git a/core/sme/inc/sme_internal.h b/core/sme/inc/sme_internal.h index bf7f34f3eada..d82b2630d774 100644 --- a/core/sme/inc/sme_internal.h +++ b/core/sme/inc/sme_internal.h @@ -355,6 +355,9 @@ typedef struct tagSmeStruct { sme_get_raom_scan_ch_Callback roam_scan_ch_callback; void *roam_scan_ch_get_context; #endif +#if defined(CLD_PM_QOS) && defined(WLAN_FEATURE_LL_MODE) + void (*beacon_latency_event_cb)(uint32_t latency_level); +#endif } tSmeStruct, *tpSmeStruct; #endif /* #if !defined( __SMEINTERNAL_H ) */ diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 9bd5e11aa4b3..50d4d2ffb40a 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -17291,3 +17291,24 @@ QDF_STATUS sme_update_owe_info(tpAniSirGlobal mac, { return csr_update_owe_info(mac, assoc_ind); } + +#if defined(CLD_PM_QOS) && defined(WLAN_FEATURE_LL_MODE) +QDF_STATUS +sme_set_beacon_latency_event_cb(mac_handle_t mac_handle, + void (*beacon_latency_event_cb) + (uint32_t latency_level)) +{ + QDF_STATUS qdf_status; + struct sAniSirGlobal *mac = MAC_CONTEXT(mac_handle); + + qdf_status = sme_acquire_global_lock(&mac->sme); + if (QDF_IS_STATUS_ERROR(qdf_status)) { + sme_err("Failed to acquire sme lock; status: %d", qdf_status); + return qdf_status; + } + mac->sme.beacon_latency_event_cb = beacon_latency_event_cb; + sme_release_global_lock(&mac->sme); + + return qdf_status; +} +#endif diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h index 30e2a4af8636..8a88e68f6696 100644 --- a/core/wma/inc/wma_internal.h +++ b/core/wma/inc/wma_internal.h @@ -1308,6 +1308,26 @@ int wma_unified_beacon_debug_stats_event_handler(void *handle, uint8_t *cmd_param_info, uint32_t len); +#if defined(CLD_PM_QOS) && defined(WLAN_FEATURE_LL_MODE) +/** + * wma_vdev_bcn_latency_event_handler() - Get the latency info received in bcn + * @handle: WMA handle + * @event: data in event + * @len: length + * + * Return: 0 for success or error code + */ +int wma_vdev_bcn_latency_event_handler(void *handle, uint8_t *event, + uint32_t len); +#else +static inline int wma_vdev_bcn_latency_event_handler(void *handle, + uint8_t *event, + uint32_t len) +{ + return 0; +} +#endif + #ifdef FEATURE_WLAN_DIAG_SUPPORT /** * wma_sta_kickout_event()- send sta kickout event diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index 8d29c547b1fa..398c1b1e7db5 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -5837,6 +5837,46 @@ int wma_unified_beacon_debug_stats_event_handler(void *handle, } #endif +#if defined(CLD_PM_QOS) && defined(WLAN_FEATURE_LL_MODE) +int +wma_vdev_bcn_latency_event_handler(void *handle, + uint8_t *event_info, + uint32_t len) +{ + WMI_VDEV_BCN_LATENCY_EVENTID_param_tlvs *param_buf = NULL; + wmi_vdev_bcn_latency_fixed_param *bcn_latency = NULL; + tpAniSirGlobal mac = + (tpAniSirGlobal)cds_get_context(QDF_MODULE_ID_PE); + uint32_t latency_level; + + param_buf = (WMI_VDEV_BCN_LATENCY_EVENTID_param_tlvs *)event_info; + if (!param_buf) { + wma_err("Invalid bcn latency event"); + return -EINVAL; + } + + bcn_latency = param_buf->fixed_param; + if (!bcn_latency) { + wma_debug("beacon latency event fixed param is NULL"); + return -EINVAL; + } + + /* Map the latency value to the level which host expects + * 1 - normal, 2 - moderate, 3 - low, 4 - ultralow + */ + latency_level = bcn_latency->latency_level + 1; + if (latency_level < 1 || latency_level > 4) { + wma_debug("invalid beacon latency level value"); + return -EINVAL; + } + + /* Call the registered sme callback */ + mac->sme.beacon_latency_event_cb(latency_level); + + return 0; +} +#endif + int wma_chan_info_event_handler(void *handle, uint8_t *event_buf, uint32_t len) { diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index e1410b4ad86e..24deedd0ad57 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -3566,6 +3566,12 @@ QDF_STATUS wma_open(struct wlan_objmgr_psoc *psoc, WMA_RX_SERIALIZER_CTX); #endif +#if defined(CLD_PM_QOS) && defined(WLAN_FEATURE_LL_MODE) + wmi_unified_register_event_handler(wma_handle->wmi_handle, + wmi_vdev_bcn_latency_event_id, + wma_vdev_bcn_latency_event_handler, + WMA_RX_SERIALIZER_CTX); +#endif /* register for linkspeed response event */ wmi_unified_register_event_handler(wma_handle->wmi_handle, wmi_peer_estimated_linkspeed_event_id, From b22dfd78f3726a337fc5adae7488b7250696525b Mon Sep 17 00:00:00 2001 From: Amit Kushwaha Date: Fri, 10 Jul 2020 11:59:38 +0530 Subject: [PATCH 137/592] ARM: dts: msm: Disable GPU mempools for QCS610 IoT Disable it to release memory reserved by GPU memory pools. Change-Id: I541386602cdf7bff611ae6c6187283856befb5a4 Signed-off-by: Amit Kushwaha --- arch/arm64/boot/dts/qcom/qcs610-iot.dtsi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcs610-iot.dtsi b/arch/arm64/boot/dts/qcom/qcs610-iot.dtsi index 733d9335b4fd..c65dae42e904 100644 --- a/arch/arm64/boot/dts/qcom/qcs610-iot.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs610-iot.dtsi @@ -324,6 +324,10 @@ reg = <0 0x97115000 0 0x2000>; }; +&msm_gpu { + /delete-node/qcom,gpu-mempools; +}; + &sdhc_1 { vdd-supply = <&pm6150l_l11>; qcom,vdd-voltage-level = <2950000 2950000>; From 09dd78e8e1d1f1963d1e5e217efb381248ab0c8b Mon Sep 17 00:00:00 2001 From: nshrivas Date: Fri, 10 Jul 2020 03:47:29 -0700 Subject: [PATCH 138/592] Release 5.2.03.29 Release 5.2.03.29 Change-Id: Ib1f1b42581c8655e8b47d1c7680106b0150c8583 CRs-Fixed: 774533 --- core/mac/inc/qwlan_version.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index ab1db7811cf9..20add75cdb58 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -32,9 +32,9 @@ #define QWLAN_VERSION_MAJOR 5 #define QWLAN_VERSION_MINOR 2 #define QWLAN_VERSION_PATCH 03 -#define QWLAN_VERSION_EXTRA "Z" -#define QWLAN_VERSION_BUILD 28 +#define QWLAN_VERSION_EXTRA "" +#define QWLAN_VERSION_BUILD 29 -#define QWLAN_VERSIONSTR "5.2.03.28Z" +#define QWLAN_VERSIONSTR "5.2.03.29" #endif /* QWLAN_VERSION_H */ From 882c25d82a2b71f6acba54c05100214f647a14bd Mon Sep 17 00:00:00 2001 From: Tiger Yu Date: Thu, 29 Nov 2018 18:11:22 +0800 Subject: [PATCH 139/592] qcacld-3.0: Change the policy & priority of RX thread Change the policy & priority of RX thread to improve the RX throughput for Specified platform. Change-Id: Ie9df5de6f34d75264c4f3b7bdcb59ab92845a128 CRs-Fixed: 2354502 --- Kbuild | 8 ++++++++ core/cds/src/cds_sched.c | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/Kbuild b/Kbuild index deb8e2da5daa..1f067755cd53 100644 --- a/Kbuild +++ b/Kbuild @@ -1980,6 +1980,14 @@ ifeq ($(CONFIG_ARCH_SDX20), y) cppflags-y += -DSYNC_IPA_READY endif +ifeq ($(CONFIG_ARCH_MSM8996), y) +CONFIG_RX_THREAD_PRIORITY := y +endif + +ifeq ($(CONFIG_RX_THREAD_PRIORITY), y) +cppflags-y += -DRX_THREAD_PRIORITY +endif + #Enable wbuff cppflags-$(CONFIG_WLAN_WBUFF) += -DWLAN_FEATURE_WBUFF diff --git a/core/cds/src/cds_sched.c b/core/cds/src/cds_sched.c index 99f89c4621f8..0da486925705 100644 --- a/core/cds/src/cds_sched.c +++ b/core/cds/src/cds_sched.c @@ -795,7 +795,15 @@ static int cds_ol_rx_thread(void *arg) bool shutdown = false; int status; +#ifdef RX_THREAD_PRIORITY + struct sched_param scheduler_params = {0}; + + scheduler_params.sched_priority = 1; + sched_setscheduler(current, SCHED_FIFO, &scheduler_params); +#else set_user_nice(current, -1); +#endif + #ifdef MSM_PLATFORM set_wake_up_idle(true); #endif From 69654cba5690018697a4635f0303abc70ae0d72a Mon Sep 17 00:00:00 2001 From: nshrivas Date: Fri, 10 Jul 2020 05:46:56 -0700 Subject: [PATCH 140/592] Release 5.2.03.29A Release 5.2.03.29A Change-Id: I4d0a1294a26ee16204bd4ba09e3c719fc5131b74 CRs-Fixed: 774533 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index 20add75cdb58..338b03176c16 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -32,9 +32,9 @@ #define QWLAN_VERSION_MAJOR 5 #define QWLAN_VERSION_MINOR 2 #define QWLAN_VERSION_PATCH 03 -#define QWLAN_VERSION_EXTRA "" +#define QWLAN_VERSION_EXTRA "A" #define QWLAN_VERSION_BUILD 29 -#define QWLAN_VERSIONSTR "5.2.03.29" +#define QWLAN_VERSIONSTR "5.2.03.29A" #endif /* QWLAN_VERSION_H */ From 91bef59ea20b1199439d5dcd859ddcc04b805192 Mon Sep 17 00:00:00 2001 From: Alistair Delva Date: Fri, 10 Jul 2020 14:42:52 -0700 Subject: [PATCH 141/592] ANDROID: cuttlefish_defconfig: Drop built-in cmdline This fixes duplicate kernel log messages. Only earlycon from ttyS0 should be logged, after virtio-console is loaded it should come only from there. Bug: 160341724 Change-Id: I194343fcaff822b31c8d8b6138196cb4e077613c Signed-off-by: Alistair Delva --- arch/x86/configs/x86_64_cuttlefish_defconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/x86/configs/x86_64_cuttlefish_defconfig b/arch/x86/configs/x86_64_cuttlefish_defconfig index 88eb2873f4e4..9bcef659c79e 100644 --- a/arch/x86/configs/x86_64_cuttlefish_defconfig +++ b/arch/x86/configs/x86_64_cuttlefish_defconfig @@ -64,7 +64,6 @@ CONFIG_CRASH_DUMP=y CONFIG_PHYSICAL_START=0x200000 CONFIG_PHYSICAL_ALIGN=0x1000000 CONFIG_CMDLINE_BOOL=y -CONFIG_CMDLINE="console=ttyS0 reboot=p" CONFIG_PM_WAKELOCKS=y CONFIG_PM_WAKELOCKS_LIMIT=0 # CONFIG_PM_WAKELOCKS_GC is not set From c237d7a5711960ec1aabc646ccc9bfd5ac1537d8 Mon Sep 17 00:00:00 2001 From: Hai Li Date: Sun, 31 May 2020 21:41:28 -0400 Subject: [PATCH 142/592] kgsl: Parse secure mapping size from dts Some targets require bigger secure mapping size in GPU address space to support multiple instances of DRM video playback. Change-Id: I63d507da75b6a7ac87f975ddff6ed4736e3f5df8 Signed-off-by: Hai Li --- .../devicetree/bindings/gpu/adreno-iommu.txt | 2 ++ drivers/gpu/msm/adreno.c | 4 +-- drivers/gpu/msm/kgsl_iommu.c | 33 ++++++++++++------- drivers/gpu/msm/kgsl_iommu.h | 4 +-- drivers/gpu/msm/kgsl_mmu.h | 4 ++- 5 files changed, 29 insertions(+), 18 deletions(-) diff --git a/Documentation/devicetree/bindings/gpu/adreno-iommu.txt b/Documentation/devicetree/bindings/gpu/adreno-iommu.txt index df29ef5d26a1..9ddca43a93d9 100644 --- a/Documentation/devicetree/bindings/gpu/adreno-iommu.txt +++ b/Documentation/devicetree/bindings/gpu/adreno-iommu.txt @@ -38,6 +38,8 @@ Optional properties: be aligned - qcom,unmap_fast : A boolean specifying if iommu unmap fast is supported on this target. +- qcom,secure-size : Specifies the size of gpu address region to be used for + secure memory mapping. - List of sub nodes, one for each of the translation context banks supported. The driver uses the names of these nodes to determine how they are used, diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index e3fd8f3acdbb..54e8fb6200e7 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -1814,10 +1814,10 @@ static void _set_secvid(struct kgsl_device *device) adreno_writereg64(adreno_dev, ADRENO_REG_RBBM_SECVID_TSB_TRUSTED_BASE, ADRENO_REG_RBBM_SECVID_TSB_TRUSTED_BASE_HI, - KGSL_IOMMU_SECURE_BASE(&device->mmu)); + device->mmu.secure_base); adreno_writereg(adreno_dev, ADRENO_REG_RBBM_SECVID_TSB_TRUSTED_SIZE, - KGSL_IOMMU_SECURE_SIZE); + device->mmu.secure_size); if (ADRENO_QUIRK(adreno_dev, ADRENO_QUIRK_SECVID_SET_ONCE)) set = true; } diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c index b338a1568476..ca65e8fc0dfd 100644 --- a/drivers/gpu/msm/kgsl_iommu.c +++ b/drivers/gpu/msm/kgsl_iommu.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -189,7 +189,7 @@ int kgsl_iommu_map_global_secure_pt_entry(struct kgsl_device *device, struct kgsl_pagetable *pagetable = device->mmu.securepagetable; entry->pagetable = pagetable; - entry->gpuaddr = KGSL_IOMMU_SECURE_BASE(&device->mmu) + + entry->gpuaddr = device->mmu.secure_base + secure_global_size; ret = kgsl_mmu_map(pagetable, entry); @@ -1097,13 +1097,13 @@ static void setup_64bit_pagetable(struct kgsl_mmu *mmu, struct kgsl_iommu_pt *pt) { if (mmu->secured && pagetable->name == KGSL_MMU_SECURE_PT) { - pt->compat_va_start = KGSL_IOMMU_SECURE_BASE(mmu); + pt->compat_va_start = mmu->secure_base; pt->compat_va_end = KGSL_IOMMU_SECURE_END(mmu); - pt->va_start = KGSL_IOMMU_SECURE_BASE(mmu); + pt->va_start = mmu->secure_base; pt->va_end = KGSL_IOMMU_SECURE_END(mmu); } else { pt->compat_va_start = mmu->svm_base32; - pt->compat_va_end = KGSL_IOMMU_SECURE_BASE(mmu); + pt->compat_va_end = mmu->secure_base; pt->va_start = KGSL_IOMMU_VA_BASE64; pt->va_end = KGSL_IOMMU_VA_END64; } @@ -1112,7 +1112,7 @@ static void setup_64bit_pagetable(struct kgsl_mmu *mmu, pagetable->name != KGSL_MMU_SECURE_PT) { if (kgsl_is_compat_task()) { pt->svm_start = mmu->svm_base32; - pt->svm_end = KGSL_IOMMU_SECURE_BASE(mmu); + pt->svm_end = mmu->secure_base; } else { pt->svm_start = KGSL_IOMMU_SVM_BASE64; pt->svm_end = KGSL_IOMMU_SVM_END64; @@ -1126,13 +1126,13 @@ static void setup_32bit_pagetable(struct kgsl_mmu *mmu, { if (mmu->secured) { if (pagetable->name == KGSL_MMU_SECURE_PT) { - pt->compat_va_start = KGSL_IOMMU_SECURE_BASE(mmu); + pt->compat_va_start = mmu->secure_base; pt->compat_va_end = KGSL_IOMMU_SECURE_END(mmu); - pt->va_start = KGSL_IOMMU_SECURE_BASE(mmu); + pt->va_start = mmu->secure_base; pt->va_end = KGSL_IOMMU_SECURE_END(mmu); } else { pt->va_start = mmu->svm_base32; - pt->va_end = KGSL_IOMMU_SECURE_BASE(mmu); + pt->va_end = mmu->secure_base; pt->compat_va_start = pt->va_start; pt->compat_va_end = pt->va_end; } @@ -2725,6 +2725,7 @@ static int _kgsl_iommu_probe(struct kgsl_device *device, u32 reg_val[2]; int i = 0; struct kgsl_iommu *iommu = KGSL_IOMMU_PRIV(device); + struct kgsl_mmu *mmu = &device->mmu; struct kgsl_pwrctrl *pwr = &device->pwrctrl; struct device_node *child; struct platform_device *pdev = of_find_device_by_node(node); @@ -2769,7 +2770,7 @@ static int _kgsl_iommu_probe(struct kgsl_device *device, for (i = 0; i < ARRAY_SIZE(kgsl_iommu_features); i++) { if (of_property_read_bool(node, kgsl_iommu_features[i].feature)) - device->mmu.features |= kgsl_iommu_features[i].bit; + mmu->features |= kgsl_iommu_features[i].bit; } /* @@ -2790,8 +2791,16 @@ static int _kgsl_iommu_probe(struct kgsl_device *device, iommu->micro_mmu_ctrl = UINT_MAX; if (of_property_read_u32(node, "qcom,secure_align_mask", - &device->mmu.secure_align_mask)) - device->mmu.secure_align_mask = 0xfff; + &mmu->secure_align_mask)) + mmu->secure_align_mask = 0xfff; + + if (of_property_read_u32(node, "qcom,secure-size", &mmu->secure_size)) + mmu->secure_size = KGSL_IOMMU_SECURE_SIZE; + else if (mmu->secure_size > + (KGSL_IOMMU_SECURE_END(mmu) - mmu->svm_base32)) + mmu->secure_size = KGSL_IOMMU_SECURE_SIZE; + + mmu->secure_base = KGSL_IOMMU_SECURE_END(mmu) - mmu->secure_size; /* Fill out the rest of the devices in the node */ of_platform_populate(node, NULL, NULL, &pdev->dev); diff --git a/drivers/gpu/msm/kgsl_iommu.h b/drivers/gpu/msm/kgsl_iommu.h index 79eee71a0cd7..4660717b99b1 100644 --- a/drivers/gpu/msm/kgsl_iommu.h +++ b/drivers/gpu/msm/kgsl_iommu.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -33,8 +33,6 @@ #define KGSL_IOMMU_SECURE_SIZE SZ_256M #define KGSL_IOMMU_SECURE_END(_mmu) KGSL_IOMMU_GLOBAL_MEM_BASE(_mmu) -#define KGSL_IOMMU_SECURE_BASE(_mmu) \ - (KGSL_IOMMU_GLOBAL_MEM_BASE(_mmu) - KGSL_IOMMU_SECURE_SIZE) #define KGSL_IOMMU_SVM_BASE32 0x300000 #define KGSL_IOMMU_SVM_END32 (0xC0000000 - SZ_16M) diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h index 06d0ae387f1c..b10d079448f8 100644 --- a/drivers/gpu/msm/kgsl_mmu.h +++ b/drivers/gpu/msm/kgsl_mmu.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2002,2007-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2002,2007-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -170,6 +170,8 @@ struct kgsl_mmu { unsigned int secure_align_mask; uint64_t va_padding; unsigned int svm_base32; + unsigned int secure_base; + unsigned int secure_size; union { struct kgsl_iommu iommu; } priv; From dcc5d3e24d44aa7107aa5fe7b96a00720b3f6d21 Mon Sep 17 00:00:00 2001 From: Govind Singh Date: Thu, 9 Jul 2020 16:59:21 +0530 Subject: [PATCH 143/592] qcacld-3.0: Change the RX thread policy for qcs40x soc Change the policy & priority of RX thread to improve the rx latency. Change-Id: Icd93da424fc4a7e2d836c348e84fbfe5bb9fac66 --- configs/default_defconfig | 1 + configs/qcs40x.snoc.perf_defconfig | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/configs/default_defconfig b/configs/default_defconfig index eb588609b424..67a4e65f9e8a 100644 --- a/configs/default_defconfig +++ b/configs/default_defconfig @@ -79,6 +79,7 @@ ifeq ($(CONFIG_ARCH_QCS40X), y) CONFIG_MULTI_IF_LOG := y CONFIG_DFS_PRI_MULTIPLIER := y CONFIG_DFS_OVERRIDE_RF_THRESHOLD := y + CONFIG_RX_THREAD_PRIORITY := y endif #Flag to enable Legacy Fast Roaming2(LFR2) diff --git a/configs/qcs40x.snoc.perf_defconfig b/configs/qcs40x.snoc.perf_defconfig index 0452f8be72be..b5b63f68a79c 100644 --- a/configs/qcs40x.snoc.perf_defconfig +++ b/configs/qcs40x.snoc.perf_defconfig @@ -195,5 +195,5 @@ CONFIG_CFG_NUM_WMI_MGMT_EVENT_HISTORY := 16 CONFIG_CFG_NUM_TX_RX_HISTOGRAM := 16 # CONFIG_CFG_NUM_RX_IND_RECORD := 1024 - +CONFIG_RX_THREAD_PRIORITY := y ################################### From 043f7c1631f4d6ce7fa38e11d616a4aecf93c867 Mon Sep 17 00:00:00 2001 From: nshrivas Date: Sat, 11 Jul 2020 01:49:56 -0700 Subject: [PATCH 144/592] Release 5.2.03.29B Release 5.2.03.29B Change-Id: I0a03a3280321be3be379cd34544fcd5dfe57d44c CRs-Fixed: 774533 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index 338b03176c16..dcbdfe105b2a 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -32,9 +32,9 @@ #define QWLAN_VERSION_MAJOR 5 #define QWLAN_VERSION_MINOR 2 #define QWLAN_VERSION_PATCH 03 -#define QWLAN_VERSION_EXTRA "A" +#define QWLAN_VERSION_EXTRA "B" #define QWLAN_VERSION_BUILD 29 -#define QWLAN_VERSIONSTR "5.2.03.29A" +#define QWLAN_VERSIONSTR "5.2.03.29B" #endif /* QWLAN_VERSION_H */ From 74bced0fb2de540a541f782b7746bdcf2535bc29 Mon Sep 17 00:00:00 2001 From: Arun Prakash Date: Sat, 11 Jul 2020 14:55:26 +0530 Subject: [PATCH 145/592] soc: qcom: smem: Increase total host number Addition of GVM LA increases total number of host to 13 which requires modification in smem definition. Change-Id: Ibe3b0e184f373ce89507fbab37ba41c65ddc0cb1 Signed-off-by: Arun Prakash --- drivers/soc/qcom/smem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c index 0cdd98ca48f3..72117972b7e5 100644 --- a/drivers/soc/qcom/smem.c +++ b/drivers/soc/qcom/smem.c @@ -92,7 +92,7 @@ #define SMEM_GLOBAL_HOST 0xfffe /* Max number of processors/hosts in a system */ -#define SMEM_HOST_COUNT 11 +#define SMEM_HOST_COUNT 13 /** * struct smem_proc_comm - proc_comm communication struct (legacy) From 4e96f736224e05a6eeb99717c534dc5afca3a4ba Mon Sep 17 00:00:00 2001 From: Arun Prakash Date: Sat, 11 Jul 2020 15:05:02 +0530 Subject: [PATCH 146/592] ARM: dts: msm: Change smem host id for gvm la Change smem host id value for gvm la to match with new value defined in other sub systems. Change-Id: Iab078b2a781433dacd4736f11daf9c43a3a4442f Signed-off-by: Arun Prakash --- arch/arm64/boot/dts/qcom/sa8155-vm.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/sa8155-vm.dtsi b/arch/arm64/boot/dts/qcom/sa8155-vm.dtsi index 540e18690a99..56778f0e58b1 100644 --- a/arch/arm64/boot/dts/qcom/sa8155-vm.dtsi +++ b/arch/arm64/boot/dts/qcom/sa8155-vm.dtsi @@ -997,7 +997,7 @@ compatible = "qcom,smem"; memory-region = <&smem_region>; hwlocks = <&tcsr_mutex 3>; - smem-host-id = <10>; + smem-host-id = <12>; }; gvm_intr: mailbox@17c00000 { From ba934d0b64245001962225df4c5a901cb63c323a Mon Sep 17 00:00:00 2001 From: Darshan Kumsi Srinivasa Date: Tue, 7 Jul 2020 23:42:48 +0530 Subject: [PATCH 147/592] msm: camera: Fix KW issues Initialize variables to fix KW issues Change-Id: I68ea4aa3b43416ed0f7d952a76306c67bb91a52e Signed-off-by: Darshan Kumsi Srinivasa --- .../media/platform/msm/camera/cam_core/cam_context_utils.c | 4 ++-- .../platform/msm/camera/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c | 3 ++- .../msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 1 + .../media/platform/msm/camera/cam_isp/cam_isp_context.c | 7 ++++--- .../msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 1 + .../platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c | 3 ++- .../msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c | 1 + .../media/platform/msm/camera/cam_utils/cam_packet_util.c | 4 ++-- 8 files changed, 15 insertions(+), 9 deletions(-) diff --git a/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c b/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c index 3c61d883d457..60e11681b604 100644 --- a/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c +++ b/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c @@ -1053,8 +1053,8 @@ static int cam_context_dump_context(struct cam_context *ctx, struct cam_context_dump_header *hdr; char *dst; uint64_t *addr, *start; - uintptr_t cpu_addr; - size_t buf_len; + uintptr_t cpu_addr = 0; + size_t buf_len = 0; uint32_t min_len, remain_len; struct cam_ctx_request *req; int i; diff --git a/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c b/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c index 91a1b141e659..2caf6d0a844d 100644 --- a/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c +++ b/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1579,6 +1579,7 @@ hw_dump: frame_req->submit_timestamp.tv_usec, cur_time.tv_sec, cur_time.tv_usec); + memset(&fd_dump_args, 0, sizeof(fd_dump_args)); rc = cam_mem_get_cpu_buf(dump_args->buf_handle, &fd_dump_args.cpu_addr, &fd_dump_args.buf_len); if (!fd_dump_args.cpu_addr || !fd_dump_args.buf_len || rc) { diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index 2143bb70afea..e3b5bb3d8902 100644 --- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -4611,6 +4611,7 @@ hw_dump: frm_process->submit_timestamp[i].tv_usec, cur_time.tv_sec, cur_time.tv_usec); + memset(&icp_dump_args, 0, sizeof(icp_dump_args)); rc = cam_mem_get_cpu_buf(dump_args->buf_handle, &icp_dump_args.cpu_addr, &icp_dump_args.buf_len); if (!icp_dump_args.cpu_addr || !icp_dump_args.buf_len || rc) { diff --git a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c index 3e410e53bb23..ee7d6eb9b183 100644 --- a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c +++ b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c @@ -905,7 +905,7 @@ static int __cam_isp_ctx_reg_upd_in_activated_state( list_del_init(&req->list); req_isp = (struct cam_isp_ctx_req *) req->req_priv; - if (req_isp->num_fence_map_out != 0) { + if (req_isp && req_isp->num_fence_map_out != 0) { list_add_tail(&req->list, &ctx->active_req_list); ctx_isp->active_req_cnt++; CAM_DBG(CAM_REQ, @@ -1885,7 +1885,7 @@ static int __cam_isp_ctx_fs2_reg_upd_in_applied_state( list_del_init(&req->list); req_isp = (struct cam_isp_ctx_req *) req->req_priv; - if (req_isp->num_fence_map_out != 0) { + if (req_isp && req_isp->num_fence_map_out != 0) { list_add_tail(&req->list, &ctx->active_req_list); ctx_isp->active_req_cnt++; CAM_DBG(CAM_REQ, "move request %lld to active list(cnt = %d)", @@ -1903,7 +1903,7 @@ static int __cam_isp_ctx_fs2_reg_upd_in_applied_state( * state so change substate here. */ ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_EPOCH; - if (req_isp->num_fence_map_out != 1) + if (req_isp && req_isp->num_fence_map_out != 1) goto end; if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_trigger && @@ -2343,6 +2343,7 @@ hw_dump: is_dump_only_event_record = true; } ctx_isp = (struct cam_isp_context *) ctx->ctx_priv; + memset(&cpu_addr, 0, sizeof(cpu_addr)); rc = cam_mem_get_cpu_buf(dump_info->buf_handle, &cpu_addr, &buf_len); if (!cpu_addr || !buf_len || rc) { diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 2b1c98df6420..0e9c34e52976 100644 --- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -4664,6 +4664,7 @@ static int cam_ife_mgr_dump(void *hw_mgr_priv, void *args) int i; int rc = 0; + memset(&isp_hw_dump_args, 0, sizeof(isp_hw_dump_args)); rc = cam_mem_get_cpu_buf(dump_args->buf_handle, &isp_hw_dump_args.cpu_addr, &isp_hw_dump_args.buf_len); diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c index 1a995646a947..ae26f61d717a 100644 --- a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c +++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1103,6 +1103,7 @@ hw_dump: p_cfg_req->submit_timestamp.tv_usec, cur_time.tv_sec, cur_time.tv_usec); + memset(&jpeg_dump_args, 0, sizeof(jpeg_dump_args)); rc = cam_mem_get_cpu_buf(dump_args->buf_handle, &jpeg_dump_args.cpu_addr, &jpeg_dump_args.buf_len); if (!jpeg_dump_args.cpu_addr || !jpeg_dump_args.buf_len || rc) { diff --git a/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c b/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c index f6fa30c7c646..cb03a57acd36 100644 --- a/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c +++ b/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c @@ -695,6 +695,7 @@ static int cam_lrme_mgr_hw_dump(void *hw_mgr_priv, void *hw_dump_args) CAM_ERR(CAM_LRME, "Failed to get hw device"); return rc; } + memset(&lrme_dump_args, 0, sizeof(lrme_dump_args)); rc = cam_mem_get_cpu_buf(dump_args->buf_handle, &lrme_dump_args.cpu_addr, &lrme_dump_args.buf_len); diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_packet_util.c b/drivers/media/platform/msm/camera/cam_utils/cam_packet_util.c index 593bed9b137d..bb950a7bade7 100644 --- a/drivers/media/platform/msm/camera/cam_utils/cam_packet_util.c +++ b/drivers/media/platform/msm/camera/cam_utils/cam_packet_util.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -177,7 +177,7 @@ int cam_packet_util_process_patches(struct cam_packet *packet, uint32_t temp; uint32_t *dst_cpu_addr; uint32_t *src_buf_iova_addr; - size_t dst_buf_len; + size_t dst_buf_len = 0; size_t src_buf_size; int i; int rc = 0; From 81558e3649f4ecbc921e30a73fa4e5c0b35d278b Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 1 Jul 2019 09:58:43 +0900 Subject: [PATCH 148/592] kheaders: remove meaningless -R option of 'ls' The -R option of 'ls' is supposed to be used for directories. -R, --recursive list subdirectories recursively Since 'find ... -type f' only matches to regular files, we do not expect directories passed to the 'ls' command here. Giving -R is harmless at least, but unneeded. Change-Id: I9948f3e92802719b393c52990f51955a867750a4 Signed-off-by: Masahiro Yamada Reviewed-by: Joel Fernandes (Google) Git-commit: b60b7c2ea9b7f854d457fefd592c77f621a86580 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Signed-off-by: Gaurav Kohli --- kernel/gen_kheaders.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/kernel/gen_kheaders.sh b/kernel/gen_kheaders.sh index 9a34e1d9bd7f..86a666f5cb17 100755 --- a/kernel/gen_kheaders.sh +++ b/kernel/gen_kheaders.sh @@ -33,8 +33,8 @@ arch/$SRCARCH/include/ # Uncomment it for debugging. # if [ ! -f /tmp/iter ]; then iter=1; echo 1 > /tmp/iter; # else iter=$(($(cat /tmp/iter) + 1)); echo $iter > /tmp/iter; fi -# find $src_file_list -type f | xargs ls -lR > /tmp/src-ls-$iter -# find $obj_file_list -type f | xargs ls -lR > /tmp/obj-ls-$iter +# find $src_file_list -type f | xargs ls -l > /tmp/src-ls-$iter +# find $obj_file_list -type f | xargs ls -l > /tmp/obj-ls-$iter # include/generated/compile.h is ignored because it is touched even when none # of the source files changed. This causes pointless regeneration, so let us @@ -46,7 +46,7 @@ src_files_md5="$(find $src_file_list -type f | grep -v "include/config/auto.conf" | grep -v "include/config/auto.conf.cmd" | grep -v "include/config/tristate.conf" | - xargs ls -lR | md5sum | cut -d ' ' -f1)" + xargs ls -l | md5sum | cut -d ' ' -f1)" popd > /dev/null obj_files_md5="$(find $obj_file_list -type f | grep -v "include/generated/compile.h" | @@ -54,7 +54,7 @@ obj_files_md5="$(find $obj_file_list -type f | grep -v "include/config/auto.conf" | grep -v "include/config/auto.conf.cmd" | grep -v "include/config/tristate.conf" | - xargs ls -lR | md5sum | cut -d ' ' -f1)" + xargs ls -l | md5sum | cut -d ' ' -f1)" if [ -f $tarfile ]; then tarfile_md5="$(md5sum $tarfile | cut -d ' ' -f1)"; fi if [ -f kernel/kheaders.md5 ] && From d544891fd09a943e15fdb0f3dccfc99e8ee00898 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 1 Jul 2019 09:58:44 +0900 Subject: [PATCH 149/592] kheaders: include only headers into kheaders_data.tar.xz Currently, kheaders_data.tar.xz contains some build scripts as well as headers. None of them is needed in the header archive. For ARCH=x86, this commit excludes the following from the archive: arch/x86/include/asm/Kbuild arch/x86/include/uapi/asm/Kbuild include/asm-generic/Kbuild include/config/auto.conf include/config/kernel.release include/config/tristate.conf include/uapi/asm-generic/Kbuild include/uapi/Kbuild kernel/gen_kheaders.sh This change is actually motivated for the planned header compile-testing because it will generate more build artifacts, which should not be included in the archive. Change-Id: I9df4bd8ab4b771051ad063035bd7b48b280b018f Signed-off-by: Masahiro Yamada Reviewed-by: Joel Fernandes (Google) Git-commit: 199ff7d74003b5aad1e6328bf6128cd8ceea735 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Signed-off-by: Gaurav Kohli --- kernel/gen_kheaders.sh | 47 ++++++++++++++---------------------------- 1 file changed, 16 insertions(+), 31 deletions(-) diff --git a/kernel/gen_kheaders.sh b/kernel/gen_kheaders.sh index 86a666f5cb17..9ff449888d9c 100755 --- a/kernel/gen_kheaders.sh +++ b/kernel/gen_kheaders.sh @@ -4,24 +4,12 @@ # This script generates an archive consisting of kernel headers # for CONFIG_IKHEADERS. set -e -spath="$(dirname "$(readlink -f "$0")")" -kroot="$spath/.." +sfile="$(readlink -f "$0")" outdir="$(pwd)" tarfile=$1 cpio_dir=$outdir/$tarfile.tmp -# Script filename relative to the kernel source root -# We add it to the archive because it is small and any changes -# to this script will also cause a rebuild of the archive. -sfile="$(realpath --relative-to $kroot "$(readlink -f "$0")")" - -src_file_list=" -include/ -arch/$SRCARCH/include/ -$sfile -" - -obj_file_list=" +dir_list=" include/ arch/$SRCARCH/include/ " @@ -33,33 +21,29 @@ arch/$SRCARCH/include/ # Uncomment it for debugging. # if [ ! -f /tmp/iter ]; then iter=1; echo 1 > /tmp/iter; # else iter=$(($(cat /tmp/iter) + 1)); echo $iter > /tmp/iter; fi -# find $src_file_list -type f | xargs ls -l > /tmp/src-ls-$iter -# find $obj_file_list -type f | xargs ls -l > /tmp/obj-ls-$iter +# find $src_file_list -name "*.h" | xargs ls -l > /tmp/src-ls-$iter +# find $obj_file_list -name "*.h" | xargs ls -l > /tmp/obj-ls-$iter # include/generated/compile.h is ignored because it is touched even when none # of the source files changed. This causes pointless regeneration, so let us # ignore them for md5 calculation. -pushd $kroot > /dev/null -src_files_md5="$(find $src_file_list -type f | +pushd $srctree > /dev/null +src_files_md5="$(find $dir_list -name "*.h" | grep -v "include/generated/compile.h" | grep -v "include/generated/autoconf.h" | - grep -v "include/config/auto.conf" | - grep -v "include/config/auto.conf.cmd" | - grep -v "include/config/tristate.conf" | xargs ls -l | md5sum | cut -d ' ' -f1)" popd > /dev/null -obj_files_md5="$(find $obj_file_list -type f | +obj_files_md5="$(find $dir_list -name "*.h" | grep -v "include/generated/compile.h" | grep -v "include/generated/autoconf.h" | - grep -v "include/config/auto.conf" | - grep -v "include/config/auto.conf.cmd" | - grep -v "include/config/tristate.conf" | xargs ls -l | md5sum | cut -d ' ' -f1)" - +# Any changes to this script will also cause a rebuild of the archive. +this_file_md5="$(ls -l $sfile | md5sum | cut -d ' ' -f1)" if [ -f $tarfile ]; then tarfile_md5="$(md5sum $tarfile | cut -d ' ' -f1)"; fi if [ -f kernel/kheaders.md5 ] && [ "$(cat kernel/kheaders.md5|head -1)" == "$src_files_md5" ] && [ "$(cat kernel/kheaders.md5|head -2|tail -1)" == "$obj_files_md5" ] && + [ "$(cat kernel/kheaders.md5|head -3|tail -1)" == "$this_file_md5" ] && [ "$(cat kernel/kheaders.md5|tail -1)" == "$tarfile_md5" ]; then exit fi @@ -71,16 +55,16 @@ fi rm -rf $cpio_dir mkdir $cpio_dir -pushd $kroot > /dev/null -for f in $src_file_list; - do find "$f" ! -name "*.cmd" ! -name ".*"; +pushd $srctree > /dev/null +for f in $dir_list; + do find "$f" -name "*.h"; done | cpio --quiet -pd $cpio_dir popd > /dev/null # The second CPIO can complain if files already exist which can # happen with out of tree builds. Just silence CPIO for now. -for f in $obj_file_list; - do find "$f" ! -name "*.cmd" ! -name ".*"; +for f in $dir_list; + do find "$f" -name "*.h"; done | cpio --quiet -pd $cpio_dir >/dev/null 2>&1 # Remove comments except SDPX lines @@ -91,6 +75,7 @@ tar -Jcf $tarfile -C $cpio_dir/ . > /dev/null echo "$src_files_md5" > kernel/kheaders.md5 echo "$obj_files_md5" >> kernel/kheaders.md5 +echo "$this_file_md5" >> kernel/kheaders.md5 echo "$(md5sum $tarfile | cut -d ' ' -f1)" >> kernel/kheaders.md5 rm -rf $cpio_dir From 604f66f0f704a492ee816b8e9cc3c03b695911a9 Mon Sep 17 00:00:00 2001 From: sheenam monga Date: Wed, 8 Jul 2020 10:34:46 +0530 Subject: [PATCH 150/592] qcacmn: Fix OOB issue in wlan_parse_rsn_ie Issue: Currently, host doesn't validate pkid_count before populating data in rsn->pmkid. rsn->pmkid array can store only 4/MAX_PMKID pmkids which may cause OOB write if host tries to copy pmkids more than MAX_PMKID. Fix: validate pkid_count before populating rsn->pmkid and return Failure in case pkid_count becomes greater than MAX_PMKID to avoid OOB. Change-Id: I211ea791a52ecb84872d139929f999a89db240d5 CRs-Fixed: 2724407 --- umac/cmn_services/cmn_defs/inc/wlan_cmn_ieee80211.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/umac/cmn_services/cmn_defs/inc/wlan_cmn_ieee80211.h b/umac/cmn_services/cmn_defs/inc/wlan_cmn_ieee80211.h index c10b9d604009..448bf9c67000 100644 --- a/umac/cmn_services/cmn_defs/inc/wlan_cmn_ieee80211.h +++ b/umac/cmn_services/cmn_defs/inc/wlan_cmn_ieee80211.h @@ -1510,7 +1510,8 @@ static inline QDF_STATUS wlan_parse_rsn_ie(uint8_t *rsn_ie, rsn->pmkid_count = LE_READ_2(ie); ie += 2; rem_len -= 2; - if (rsn->pmkid_count > (unsigned int) rem_len / PMKID_LEN) { + if (rsn->pmkid_count > MAX_PMKID || + rsn->pmkid_count > (unsigned int)rem_len / PMKID_LEN) { rsn->pmkid_count = 0; return QDF_STATUS_E_INVAL; } From c5f00b7802c73f4f8fe6505ee3fb3423e513b604 Mon Sep 17 00:00:00 2001 From: Vulupala Shashank Reddy Date: Sun, 12 Jul 2020 22:16:22 +0530 Subject: [PATCH 151/592] qcacld-3.0: Allocate required memory for skb and radiotap Mgmt txrx component clones skb and sends cloned skb to its clients ex: packet capture component. Need to Allocate memory and copy skb so that there is enough space to copy radiotap header in skb for packet capture mode. Free skb cloned by Mgmt txrx component. Change-Id: I6bc66b5916ec5a8cf28741e4fcb72f14650fdbfa CRs-Fixed: 2730559 --- .../core/src/wlan_pkt_capture_mgmt_txrx.c | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/components/pkt_capture/core/src/wlan_pkt_capture_mgmt_txrx.c b/components/pkt_capture/core/src/wlan_pkt_capture_mgmt_txrx.c index 38d74112b877..96aa113fe3b1 100644 --- a/components/pkt_capture/core/src/wlan_pkt_capture_mgmt_txrx.c +++ b/components/pkt_capture/core/src/wlan_pkt_capture_mgmt_txrx.c @@ -418,23 +418,41 @@ pkt_capture_mgmt_tx_completion(struct wlan_objmgr_pdev *pdev, /** * process_pktcapture_mgmt_rx_data_cb() - process management rx packets * @rx_params: mgmt rx event params - * @nbuf: netbuf + * @wbuf: netbuf * * Return: none */ static QDF_STATUS pkt_capture_mgmt_rx_data_cb(struct wlan_objmgr_psoc *psoc, struct wlan_objmgr_peer *peer, - qdf_nbuf_t nbuf, + qdf_nbuf_t wbuf, struct mgmt_rx_event_params *rx_params, enum mgmt_frame_type frm_type) { struct mon_rx_status txrx_status = {0}; struct ieee80211_frame *wh; uint8_t type, sub_type; + qdf_nbuf_t nbuf; + int buf_len; - if (!(pkt_capture_get_pktcap_mode() & PACKET_CAPTURE_MODE_MGMT_ONLY)) + if (!(pkt_capture_get_pktcap_mode() & PACKET_CAPTURE_MODE_MGMT_ONLY)) { + qdf_nbuf_free(wbuf); return QDF_STATUS_E_FAILURE; + } + + buf_len = qdf_nbuf_len(wbuf); + nbuf = qdf_nbuf_alloc(NULL, roundup( + buf_len + RESERVE_BYTES, 4), + RESERVE_BYTES, 4, false); + if (!nbuf) { + qdf_nbuf_free(wbuf); + return QDF_STATUS_E_FAILURE; + } + + qdf_nbuf_put_tail(nbuf, buf_len); + qdf_mem_copy(qdf_nbuf_data(nbuf), qdf_nbuf_data(wbuf), buf_len); + + qdf_nbuf_free(wbuf); wh = (struct ieee80211_frame *)qdf_nbuf_data(nbuf); type = (wh)->i_fc[0] & IEEE80211_FC0_TYPE_MASK; From d9fc4e33bea5c9a645c6cd45fed9f253b6fe33f5 Mon Sep 17 00:00:00 2001 From: Ashish Kumar Dhanotiya Date: Fri, 10 Jul 2020 20:09:47 +0530 Subject: [PATCH 152/592] qcacmn: Make freq to chan and vice versa conversion more generic Add conversion from frequency to channel, for frequency falling within two consecutive supported channels. Use the master channel list of the pdev for the same. Add new API wlan_reg_legacy_chan_to_freq to convert legacy 2G and 5G channel number to frequency. Existing API wlan_reg_chan_to_freq would be slowly deprecated. Change-Id: Id7e1939b9e05b78c17751d13bb0b02a891f999ad CRs-Fixed: 2526886 --- umac/regulatory/core/src/reg_services.c | 112 +++++++++++++++++- umac/regulatory/core/src/reg_services.h | 10 ++ .../dispatcher/inc/wlan_reg_services_api.h | 10 ++ .../dispatcher/src/wlan_reg_services_api.c | 6 + 4 files changed, 132 insertions(+), 6 deletions(-) diff --git a/umac/regulatory/core/src/reg_services.c b/umac/regulatory/core/src/reg_services.c index eb64ab629874..f1551c36f80f 100644 --- a/umac/regulatory/core/src/reg_services.c +++ b/umac/regulatory/core/src/reg_services.c @@ -1854,24 +1854,124 @@ uint32_t reg_freq_to_chan(struct wlan_objmgr_pdev *pdev, struct regulatory_channel *chan_list; struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + if (freq == 0) { + reg_err("Invalid freq %d", freq); + return 0; + } + pdev_priv_obj = reg_get_pdev_obj(pdev); if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { reg_err("reg pdev priv obj is NULL"); - return QDF_STATUS_E_FAILURE; + return 0; } - chan_list = pdev_priv_obj->cur_chan_list; + chan_list = pdev_priv_obj->mas_chan_list; + for (count = 0; count < NUM_CHANNELS; count++) { + if (chan_list[count].center_freq >= freq) + break; + } - for (count = 0; count < NUM_CHANNELS; count++) - if (chan_list[count].center_freq == freq) - return chan_list[count].chan_num; + if (count == NUM_CHANNELS) + goto end; + if (chan_list[count].center_freq == freq) + return chan_list[count].chan_num; + + if (count == 0) + goto end; + + if ((chan_list[count - 1].chan_num == INVALID_CHANNEL_NUM) || + (chan_list[count].chan_num == INVALID_CHANNEL_NUM)) { + reg_err("Frequency %d invalid in current reg domain", freq); + return 0; + } + + return (chan_list[count - 1].chan_num + + (freq - chan_list[count - 1].center_freq) / 5); + +end: reg_err("invalid frequency %d", freq); - return 0; } +static uint16_t reg_compute_chan_to_freq(struct wlan_objmgr_pdev *pdev, + uint8_t chan_num, + enum channel_enum min_chan_range, + enum channel_enum max_chan_range) +{ + uint16_t count; + struct regulatory_channel *chan_list; + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + + pdev_priv_obj = reg_get_pdev_obj(pdev); + + if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { + reg_err("reg pdev priv obj is NULL"); + return 0; + } + + chan_list = pdev_priv_obj->mas_chan_list; + + for (count = min_chan_range; count <= max_chan_range; count++) { + if (reg_chan_is_49ghz(pdev, chan_list[count].chan_num)) { + if (chan_list[count].chan_num == chan_num) + break; + continue; + } else if ((chan_list[count].chan_num >= chan_num) && + (chan_list[count].state != CHANNEL_STATE_DISABLE) && + !(chan_list[count].chan_flags & + REGULATORY_CHAN_DISABLED) && + (chan_list[count].chan_num != INVALID_CHANNEL_NUM)) + break; + } + + if (count == max_chan_range + 1) + goto end; + + if (chan_list[count].chan_num == chan_num) { + if (chan_list[count].chan_flags & REGULATORY_CHAN_DISABLED) + reg_err("Channel %d disabled in current reg domain", + chan_num); + return chan_list[count].center_freq; + } + + if (count == min_chan_range) + goto end; + + if ((chan_list[count - 1].chan_num == INVALID_CHANNEL_NUM) || + reg_chan_is_49ghz(pdev, chan_list[count - 1].chan_num) || + (chan_list[count].chan_num == INVALID_CHANNEL_NUM)) { + reg_err("Channel %d invalid in current reg domain", + chan_num); + return 0; + } + + return (chan_list[count - 1].center_freq + + (chan_num - chan_list[count - 1].chan_num) * 5); + +end: + + reg_debug_rl("Invalid channel %d", chan_num); + return 0; +} + +uint16_t reg_legacy_chan_to_freq(struct wlan_objmgr_pdev *pdev, + uint8_t chan_num) +{ + uint16_t min_chan_range = MIN_24GHZ_CHANNEL; + uint16_t max_chan_range = MAX_5GHZ_CHANNEL; + + if (chan_num == 0) { + reg_err("Invalid channel %d", chan_num); + return 0; + } + + return reg_compute_chan_to_freq(pdev, chan_num, + min_chan_range, + max_chan_range); +} + uint32_t reg_chan_to_freq(struct wlan_objmgr_pdev *pdev, uint32_t chan_num) { diff --git a/umac/regulatory/core/src/reg_services.h b/umac/regulatory/core/src/reg_services.h index 1b4440902198..b7a7e220eeff 100644 --- a/umac/regulatory/core/src/reg_services.h +++ b/umac/regulatory/core/src/reg_services.h @@ -461,6 +461,16 @@ uint32_t reg_freq_to_chan(struct wlan_objmgr_pdev *pdev, uint32_t freq); uint32_t reg_chan_to_freq(struct wlan_objmgr_pdev *pdev, uint32_t chan_num); +/** + * reg_legacy_chan_to_freq() - Get freq from chan noumber, for 2G and 5G + * @pdev: Pointer to pdev + * @chan_num: Channel number + * + * Return: Channel frequency if success, otherwise 0 + */ +uint16_t reg_legacy_chan_to_freq(struct wlan_objmgr_pdev *pdev, + uint8_t chan_num); + /** * reg_chan_is_49ghz() - Check if the input channel number is 4.9GHz * @pdev: Pdev pointer diff --git a/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h b/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h index 42174be1976c..93056b2d344d 100644 --- a/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h +++ b/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h @@ -447,6 +447,16 @@ uint32_t wlan_reg_chan_to_freq(struct wlan_objmgr_pdev *pdev, * * Return: true or false */ + +/** + * wlan_reg_legacy_chan_to_freq () - convert chan to freq, for 2G and 5G + * @chan: channel number + * + * Return: frequency + */ +uint16_t wlan_reg_legacy_chan_to_freq(struct wlan_objmgr_pdev *pdev, + uint8_t chan); + bool wlan_reg_is_world(uint8_t *country); /** diff --git a/umac/regulatory/dispatcher/src/wlan_reg_services_api.c b/umac/regulatory/dispatcher/src/wlan_reg_services_api.c index 8166292c7c30..9569f6f08e35 100644 --- a/umac/regulatory/dispatcher/src/wlan_reg_services_api.c +++ b/umac/regulatory/dispatcher/src/wlan_reg_services_api.c @@ -469,6 +469,12 @@ uint32_t wlan_reg_chan_to_freq(struct wlan_objmgr_pdev *pdev, return reg_chan_to_freq(pdev, chan_num); } +uint16_t wlan_reg_legacy_chan_to_freq(struct wlan_objmgr_pdev *pdev, + uint8_t chan_num) +{ + return reg_legacy_chan_to_freq(pdev, chan_num); +} + bool wlan_reg_chan_is_49ghz(struct wlan_objmgr_pdev *pdev, uint8_t chan_num) { From 0c27e5ad475fd05eafb8e65a7a48db834cd2526c Mon Sep 17 00:00:00 2001 From: Ashish Kumar Dhanotiya Date: Wed, 16 Oct 2019 18:50:45 +0530 Subject: [PATCH 153/592] qcacmn: Invoke correct api to convert channel to frequency Currently wifi update channel bw api is using legacy api wlan reg get chan freq to convert channel numbers to the frequency which does not take care of the bonded channels and returns invalid channel number error code for bonded channels which results in undefined behavior on the user space application which is using the result of this api. To address above issue, use the correct api to convert channel number to frequency. Change-Id: I80295b0ff502747d5655642f2506283bd3ba0b52 CRs-fixed: 2547546 --- umac/wifi_pos/src/wifi_pos_main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/umac/wifi_pos/src/wifi_pos_main.c b/umac/wifi_pos/src/wifi_pos_main.c index 086321d7e117..1434fea3207b 100644 --- a/umac/wifi_pos/src/wifi_pos_main.c +++ b/umac/wifi_pos/src/wifi_pos_main.c @@ -233,8 +233,9 @@ static void wifi_update_channel_bw_info(struct wlan_objmgr_psoc *psoc, wlan_reg_set_channel_params(pdev, chan, sec_ch_2g, &ch_params); if (ch_params.center_freq_seg0) chan_info->band_center_freq1 = - wlan_reg_get_channel_freq(pdev, - ch_params.center_freq_seg0); + wlan_reg_legacy_chan_to_freq( + pdev, + ch_params.center_freq_seg0); wifi_pos_psoc->wifi_pos_get_phy_mode(chan, ch_params.ch_width, &phy_mode); From 0134c891754a04e457d41d2fec0ad96964781806 Mon Sep 17 00:00:00 2001 From: Rohith Kollalsi Date: Mon, 6 Jul 2020 19:00:12 +0530 Subject: [PATCH 154/592] usb: u_ether: Add null pointer check for sk_buff in eth_start_xmit There is a possibility of null pointer dereference for sk_buff in the function eth_start_xmit. Fix this by removing sk_buff from if check at the start of the function eth_start_xmit so that if sk_buff is null dev_kfree_skb_any will return without proceeding further. Change-Id: I105e42c59aaa83c8d74cc5a9e894ae4fc87c3c9f Signed-off-by: Rohith Kollalsi --- drivers/usb/gadget/function/u_ether.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/function/u_ether.c b/drivers/usb/gadget/function/u_ether.c index 7fdcc368fc91..214fad87ce05 100644 --- a/drivers/usb/gadget/function/u_ether.c +++ b/drivers/usb/gadget/function/u_ether.c @@ -798,7 +798,7 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb, } spin_unlock_irqrestore(&dev->lock, flags); - if (skb && !in) { + if (!in) { dev_kfree_skb_any(skb); return NETDEV_TX_OK; } From 22bebdd23b6e80ab7b9445fb2e19b5cc27218106 Mon Sep 17 00:00:00 2001 From: nshrivas Date: Mon, 13 Jul 2020 05:47:22 -0700 Subject: [PATCH 155/592] Release 5.2.03.29C Release 5.2.03.29C Change-Id: Ie4d35ee5a7ed28f654c0f8b3227f0df56975e203 CRs-Fixed: 774533 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index dcbdfe105b2a..c56e23373507 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -32,9 +32,9 @@ #define QWLAN_VERSION_MAJOR 5 #define QWLAN_VERSION_MINOR 2 #define QWLAN_VERSION_PATCH 03 -#define QWLAN_VERSION_EXTRA "B" +#define QWLAN_VERSION_EXTRA "C" #define QWLAN_VERSION_BUILD 29 -#define QWLAN_VERSIONSTR "5.2.03.29B" +#define QWLAN_VERSIONSTR "5.2.03.29C" #endif /* QWLAN_VERSION_H */ From 496c0191115b80ba302ac98b322d5ac7fdcfdbd5 Mon Sep 17 00:00:00 2001 From: Ajay Prathi Date: Fri, 3 Jul 2020 15:12:22 +0530 Subject: [PATCH 156/592] msm: sps: Assign proper BAM destination values Fix NOC error caused due to incorrect BAM destination value. Assign correct destination and destination pipe index values to peer BAM. Change-Id: Ifc8f0c308cc388924dce3e32709dad47fc69bf70 Signed-off-by: Ajay Prathi --- drivers/platform/msm/sps/sps_bam.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/platform/msm/sps/sps_bam.c b/drivers/platform/msm/sps/sps_bam.c index 68f4e3e91c90..3a8ccbdea296 100644 --- a/drivers/platform/msm/sps/sps_bam.c +++ b/drivers/platform/msm/sps/sps_bam.c @@ -899,14 +899,12 @@ int sps_bam_pipe_connect(struct sps_pipe *bam_pipe, peer_bam->props.phys_addr; } if (!(bam_pipe->connect.options & SPS_O_DUMMY_PEER)) { - hw_params.peer_phys_addr = - bam_pipe->connect.destination; - hw_params.peer_pipe = - bam_pipe->connect.dest_pipe_index; + hw_params.peer_pipe = other_pipe->pipe_index; } else { hw_params.peer_phys_addr = bam_pipe->connect.destination; - hw_params.peer_pipe = other_pipe->pipe_index; + hw_params.peer_pipe = + bam_pipe->connect.dest_pipe_index; hw_params.dummy_peer = true; } /* Verify FIFO buffers are allocated for BAM-to-BAM pipes */ From a43abc6da37f6079295e6138afabf6da3502c6c0 Mon Sep 17 00:00:00 2001 From: Srinivas Dasari Date: Mon, 13 Jul 2020 14:00:44 +0530 Subject: [PATCH 157/592] qcacld-3.0: Ini bitmap to enable/disable a particular NAN feature NAN protocol runs in firmware and controlled by framework. Framework configures multiple NAN discovery params while enabling NAN. Framework configurations would be based on the framework constraints or realtime scenarios like resource(memory/power/..) consumption. But some of these params might need to be controlled explicitly based on the usage. NAN DW is one such parameter, which is configured as 4 seconds when the device is in sync role and the screen is off. But for some usecases, this param might have to be 512ms always irrespective of screen off/on for some targets. Add an ini param "nan_feature_config" to set a bit to indicate firmware whether to honor framework configured DW value or the firmware default value. Send the vdev param on NAN supported vdev by setting the "bit 0" to indicate firmware to allow framework configured DW value. If this bit is not set, firmware shall consider its default value. Change-Id: I0476bca2bbe676beccfff207f5b4ea31e89031e2 CRs-Fixed: 2721970 --- core/hdd/inc/wlan_hdd_cfg.h | 30 ++++++++++++++++++++++++++++++ core/hdd/inc/wlan_hdd_main.h | 1 + core/hdd/src/wlan_hdd_cfg.c | 7 +++++++ core/hdd/src/wlan_hdd_main.c | 22 ++++++++++++++++++++++ 4 files changed, 60 insertions(+) diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index a4f083a5b159..602e385ecd60 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -8512,6 +8512,35 @@ enum hdd_link_speed_rpt_type { #define CFG_NDP_KEEP_ALIVE_PERIOD_MAX (30) #define CFG_NDP_KEEP_ALIVE_PERIOD_DEFAULT (20) +/* + * + * nan_feature_config - Bitmap to enable/disable a particular NAN/NDP feature + * + * @Min: 0 + * @Max: 0xFFFF + * @Default: 0x1 + * + * This parameter helps to enable/disable a particular feature config by setting + * corresponding bit and send to firmware through the VDEV param + * WMI_VDEV_PARAM_ENABLE_DISABLE_NAN_CONFIG_FEATURES + * Acceptable values for this: + * BIT(0): Allow DW configuration from framework in sync role. + * If this is not set, firmware shall follow the spec/default behavior. + * BIT(1) to BIT(31): Reserved + * + * Related: None + * + * Supported Feature: NAN + * + * Usage: External + * + * + */ +#define CFG_NAN_FEATURE_CONFIG "nan_feature_config" +#define CFG_NAN_FEATURE_CONFIG_MIN (0) +#define CFG_NAN_FEATURE_CONFIG_MAX (0xFFFF) +#define CFG_NAN_FEATURE_CONFIG_DEFAULT (1) + /* * * gSupportMp0Discovery - To support discovery of NAN cluster with @@ -18318,6 +18347,7 @@ struct hdd_config { bool nan_separate_iface_support; uint16_t ndp_keep_alive_period; bool support_mp0_discovery; + uint32_t nan_feature_config; #endif bool enableSelfRecovery; #ifdef FEATURE_WLAN_FORCE_SAP_SCC diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index ed2f7a55657e..ea84f343c9af 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -2099,6 +2099,7 @@ struct hdd_context { struct wlan_mlme_chain_cfg fw_chain_cfg; struct sar_limit_cmd_params *sar_cmd_params; bool nan_seperate_vdev_supported; + uint32_t nan_feature_config; #ifdef SAR_SAFETY_FEATURE qdf_mc_timer_t sar_safety_timer; diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c index 0d6257906076..01ae60d8f241 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/core/hdd/src/wlan_hdd_cfg.c @@ -3293,6 +3293,13 @@ struct reg_table_entry g_registry_table[] = { CFG_SUPPORT_MP0_DISCOVERY_DEFAULT, CFG_SUPPORT_MP0_DISCOVERY_MIN, CFG_SUPPORT_MP0_DISCOVERY_MAX), + + REG_VARIABLE(CFG_NAN_FEATURE_CONFIG, WLAN_PARAM_Integer, + struct hdd_config, nan_feature_config, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_NAN_FEATURE_CONFIG_DEFAULT, + CFG_NAN_FEATURE_CONFIG_MIN, + CFG_NAN_FEATURE_CONFIG_MAX), #endif REG_VARIABLE(CFG_ENABLE_SELF_RECOVERY, WLAN_PARAM_Integer, diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index e7c5db79d79d..3d40c58ff0d8 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -15273,6 +15273,24 @@ static int hdd_update_pkt_capture_config(struct hdd_context *hdd_ctx) return qdf_status_to_os_return(status); } +/** + * hdd_update_nan_config - Update nan config + * @hdd_ctx: HDD context + * + * Return: 0 on success / error on failure + */ +static int hdd_update_nan_config(struct hdd_context *hdd_ctx) +{ + QDF_STATUS status; + uint32_t nan_feature_config = hdd_ctx->config->nan_feature_config; + + status = ucfg_set_nan_feature_config(hdd_ctx->psoc, nan_feature_config); + if (QDF_IS_STATUS_ERROR(status)) + hdd_err("nan config failed"); + + return qdf_status_to_os_return(status); +} + #ifdef FEATURE_WLAN_TIME_SYNC_FTM /** * hdd_update_time_sync_ftm_config - Update time sync ftm config parameters @@ -15641,6 +15659,10 @@ int hdd_update_components_config(struct hdd_context *hdd_ctx) if (ret) return ret; + ret = hdd_update_nan_config(hdd_ctx); + if (ret) + return ret; + ret = hdd_update_time_sync_ftm_config(hdd_ctx); return ret; From d3c82340a55ce7c596bd5ba6b97eb1509a58b40a Mon Sep 17 00:00:00 2001 From: nshrivas Date: Mon, 13 Jul 2020 10:59:17 -0700 Subject: [PATCH 158/592] Release 5.2.03.29D Release 5.2.03.29D Change-Id: I12c1f34aab73639b73f3818bd3f50c3e0a056943 CRs-Fixed: 774533 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index c56e23373507..2cff48351085 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -32,9 +32,9 @@ #define QWLAN_VERSION_MAJOR 5 #define QWLAN_VERSION_MINOR 2 #define QWLAN_VERSION_PATCH 03 -#define QWLAN_VERSION_EXTRA "C" +#define QWLAN_VERSION_EXTRA "D" #define QWLAN_VERSION_BUILD 29 -#define QWLAN_VERSIONSTR "5.2.03.29C" +#define QWLAN_VERSIONSTR "5.2.03.29D" #endif /* QWLAN_VERSION_H */ From 2e8122cce1f32b7537353d5b39e3412a48d6116a Mon Sep 17 00:00:00 2001 From: Srinivas Dasari Date: Mon, 13 Jul 2020 14:00:01 +0530 Subject: [PATCH 159/592] qcacmn: Add vdev param to configure NAN feature bitmap to firmware Define a new vdev param to set corresponding bit to enable/disable a particular NAN feature. Currently, Framework configures NAN DW as 4 seconds when the device is in sync role and the screen is off. But customers might want this to be 512ms always irrespective of screen off/on. Send the vdev param on NAN vdev by setting the "bit 0" to 0 to indicate firmware to ignore framework configured DW value and consider the firmware default value. Change-Id: Idcbdae94bd6a96fbbe15ec103a0aa558cdfcd572 CRs-Fixed: 2721980 --- target_if/nan/inc/target_if_nan.h | 13 +++++++- target_if/nan/src/target_if_nan.c | 42 ++++++++++++++++++++++++++ umac/nan/core/src/nan_api.c | 10 ++++++ umac/nan/core/src/nan_main_i.h | 4 +++ umac/nan/dispatcher/inc/nan_ucfg_api.h | 21 ++++++++++++- umac/nan/dispatcher/src/nan_ucfg_api.c | 30 ++++++++++++++++++ wmi/inc/wmi_unified_param.h | 1 + wmi/src/wmi_unified_non_tlv.c | 2 ++ wmi/src/wmi_unified_tlv.c | 2 ++ 9 files changed, 123 insertions(+), 2 deletions(-) diff --git a/target_if/nan/inc/target_if_nan.h b/target_if/nan/inc/target_if_nan.h index 2563efae7d0e..7333b3cc731e 100644 --- a/target_if/nan/inc/target_if_nan.h +++ b/target_if/nan/inc/target_if_nan.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2017, 2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -94,4 +94,15 @@ QDF_STATUS target_if_nan_register_events(struct wlan_objmgr_psoc *psoc); */ QDF_STATUS target_if_nan_deregister_events(struct wlan_objmgr_psoc *psoc); +/** + * target_if_nan_set_vdev_feature_config() - Init NAN feature config params + * @psoc: Pointer to PSOC Object + * @vdev_id: vdev_id of the current vdev + * @mode: Opmode of the vdev + * + * This function updates NAN feature config bitmap to firmware + */ +void target_if_nan_set_vdev_feature_config(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, + enum QDF_OPMODE mode); #endif /* _WIFI_POS_TGT_IF_H_ */ diff --git a/target_if/nan/src/target_if_nan.c b/target_if/nan/src/target_if_nan.c index 9522169827d0..827aad997a84 100644 --- a/target_if/nan/src/target_if_nan.c +++ b/target_if/nan/src/target_if_nan.c @@ -26,6 +26,7 @@ #include "target_if_nan.h" #include "wmi_unified_api.h" #include "scheduler_api.h" +#include static QDF_STATUS target_if_nan_event_flush_cb(struct scheduler_msg *msg) { @@ -885,3 +886,44 @@ QDF_STATUS target_if_nan_deregister_events(struct wlan_objmgr_psoc *psoc) else return QDF_STATUS_SUCCESS; } + +void target_if_nan_set_vdev_feature_config(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, + enum QDF_OPMODE mode) +{ + QDF_STATUS status; + uint32_t nan_features = 0; + struct vdev_set_params param; + wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + struct target_psoc_info *tgt_hdl; + target_resource_config *wlan_res_cfg; + + if (!wmi_handle) { + target_if_err("Invalid wmi handle"); + return; + } + + tgt_hdl = wlan_psoc_get_tgt_if_handle(psoc); + if (!tgt_hdl) { + target_if_err("target psoc info is NULL"); + return; + } + wlan_res_cfg = target_psoc_get_wlan_res_cfg(tgt_hdl); + + if (!(mode == QDF_NAN_DISC_MODE || + (!wlan_res_cfg->nan_separate_iface_support && + mode == QDF_STA_MODE))) + return; + + ucfg_get_nan_feature_config(psoc, &nan_features); + target_if_debug("vdev_id:%d NAN features:0x%x", vdev_id, nan_features); + + param.if_id = vdev_id; + param.param_id = WMI_VDEV_PARAM_ENABLE_DISABLE_NAN_CONFIG_FEATURES; + param.param_value = nan_features; + + status = wmi_unified_vdev_set_param_send(wmi_handle, ¶m); + if (QDF_IS_STATUS_ERROR(status)) + target_if_err("failed to set NAN_CONFIG_FEATURES(status = %d)", + status); +} diff --git a/umac/nan/core/src/nan_api.c b/umac/nan/core/src/nan_api.c index 592dadbb2f96..d66cc53d7b3b 100644 --- a/umac/nan/core/src/nan_api.c +++ b/umac/nan/core/src/nan_api.c @@ -125,8 +125,18 @@ static QDF_STATUS nan_vdev_obj_created_notification( { struct nan_vdev_priv_obj *nan_obj; QDF_STATUS status = QDF_STATUS_SUCCESS; + struct wlan_objmgr_psoc *psoc; nan_debug("nan_vdev_create_notif called"); + + psoc = wlan_vdev_get_psoc(vdev); + if (!psoc) { + nan_err("psoc is NULL"); + return QDF_STATUS_E_INVAL; + } + target_if_nan_set_vdev_feature_config(psoc, + wlan_vdev_get_id(vdev), + wlan_vdev_mlme_get_opmode(vdev)); if (wlan_vdev_mlme_get_opmode(vdev) != QDF_NDI_MODE) { nan_debug("not a ndi vdev. do nothing"); return QDF_STATUS_SUCCESS; diff --git a/umac/nan/core/src/nan_main_i.h b/umac/nan/core/src/nan_main_i.h index e1d4323968f7..0c9494fcc7bc 100644 --- a/umac/nan/core/src/nan_main_i.h +++ b/umac/nan/core/src/nan_main_i.h @@ -61,12 +61,16 @@ struct scheduler_msg; * @cb_obj: struct contaning callback pointers * @request_context: NAN context to carry cookie for wait_for_complete * @ndp_active_sessions: active ndp sessions + * @nan_feature_config: Bitmap to enable/disable a particular NAN feature + * configuration in firmware. It's sent to firmware through + * WMI_VDEV_PARAM_ENABLE_DISABLE_NAN_CONFIG_FEATURES */ struct nan_psoc_priv_obj { qdf_spinlock_t lock; struct nan_callbacks cb_obj; void *request_context; uint8_t ndp_active_sessions; + uint32_t nan_feature_config; }; /** diff --git a/umac/nan/dispatcher/inc/nan_ucfg_api.h b/umac/nan/dispatcher/inc/nan_ucfg_api.h index fa2d990e1aed..520766dd3245 100644 --- a/umac/nan/dispatcher/inc/nan_ucfg_api.h +++ b/umac/nan/dispatcher/inc/nan_ucfg_api.h @@ -278,5 +278,24 @@ int ucfg_nan_register_lim_callbacks(struct wlan_objmgr_psoc *psoc, QDF_STATUS ucfg_nan_get_callbacks(struct wlan_objmgr_psoc *psoc, struct nan_callbacks *cb_obj); -#endif /* _NAN_UCFG_API_H_ */ +/** + * ucfg_set_nan_feature_config() - Set NAN feature bitmap + * @psoc: pointer to psoc object + * @nan_feature_config: NAN feature config bitmap configured by user + * + * Return: QDF_STATUS + */ +QDF_STATUS ucfg_set_nan_feature_config(struct wlan_objmgr_psoc *psoc, + uint32_t nan_feature_config); +/** + * ucfg_get_nan_feature_config() - Get NAN feature bitmap + * @psoc: pointer to psoc object + * @nan_feature_config: NAN feature config bitmap to be enabled in firmware + * + * Return: QDF_STATUS + */ +QDF_STATUS ucfg_get_nan_feature_config(struct wlan_objmgr_psoc *psoc, + uint32_t *nan_feature_config); + +#endif /* _NAN_UCFG_API_H_ */ diff --git a/umac/nan/dispatcher/src/nan_ucfg_api.c b/umac/nan/dispatcher/src/nan_ucfg_api.c index 3f0d37d3a36e..5119c8d85b7a 100644 --- a/umac/nan/dispatcher/src/nan_ucfg_api.c +++ b/umac/nan/dispatcher/src/nan_ucfg_api.c @@ -485,3 +485,33 @@ int ucfg_nan_register_lim_callbacks(struct wlan_objmgr_psoc *psoc, return 0; } + +QDF_STATUS ucfg_set_nan_feature_config(struct wlan_objmgr_psoc *psoc, + uint32_t nan_feature_config) +{ + struct nan_psoc_priv_obj *psoc_nan_obj; + + psoc_nan_obj = nan_get_psoc_priv_obj(psoc); + if (!psoc_nan_obj) { + nan_err("psoc_nan_obj is null"); + return QDF_STATUS_E_INVAL; + } + + psoc_nan_obj->nan_feature_config = nan_feature_config; + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS ucfg_get_nan_feature_config(struct wlan_objmgr_psoc *psoc, + uint32_t *nan_feature_config) +{ + struct nan_psoc_priv_obj *psoc_nan_obj; + + psoc_nan_obj = nan_get_psoc_priv_obj(psoc); + if (!psoc_nan_obj) { + nan_err("psoc_nan_obj is null"); + return QDF_STATUS_E_INVAL; + } + + *nan_feature_config = psoc_nan_obj->nan_feature_config; + return QDF_STATUS_SUCCESS; +} diff --git a/wmi/inc/wmi_unified_param.h b/wmi/inc/wmi_unified_param.h index 3aaaf3f2bb91..d307f96796fa 100644 --- a/wmi/inc/wmi_unified_param.h +++ b/wmi/inc/wmi_unified_param.h @@ -6055,6 +6055,7 @@ typedef enum { wmi_vdev_param_set_ba_mode, wmi_vdev_param_autorate_misc_cfg, wmi_vdev_param_amsdu_subframe_size_per_ac, + wmi_vdev_param_nan_config_features, wmi_vdev_param_max, } wmi_conv_vdev_param_id; diff --git a/wmi/src/wmi_unified_non_tlv.c b/wmi/src/wmi_unified_non_tlv.c index c18bb20a5394..35b14b3fef2a 100644 --- a/wmi/src/wmi_unified_non_tlv.c +++ b/wmi/src/wmi_unified_non_tlv.c @@ -9413,6 +9413,8 @@ static void populate_vdev_param_non_tlv(uint32_t *vdev_param) WMI_VDEV_PARAM_DISABLE_CABQ; vdev_param[wmi_vdev_param_amsdu_subframe_size_per_ac] = WMI_VDEV_PARAM_AMSDU_SUBFRAME_SIZE_PER_AC; + vdev_param[wmi_vdev_param_nan_config_features] = + WMI_VDEV_PARAM_ENABLE_DISABLE_NAN_CONFIG_FEATURES; } #endif diff --git a/wmi/src/wmi_unified_tlv.c b/wmi/src/wmi_unified_tlv.c index e3e76bf0e698..015484e47c06 100644 --- a/wmi/src/wmi_unified_tlv.c +++ b/wmi/src/wmi_unified_tlv.c @@ -25666,6 +25666,8 @@ static void populate_vdev_param_tlv(uint32_t *vdev_param) WMI_VDEV_PARAM_CAPABILITIES; vdev_param[wmi_vdev_param_autorate_misc_cfg] = WMI_VDEV_PARAM_AUTORATE_MISC_CFG; + vdev_param[wmi_vdev_param_nan_config_features] = + WMI_VDEV_PARAM_ENABLE_DISABLE_NAN_CONFIG_FEATURES; } #endif From f11ea532bb078f7cd26657a636eedaa03270d0c0 Mon Sep 17 00:00:00 2001 From: Mohit Khanna Date: Tue, 18 Jun 2019 20:06:45 -0700 Subject: [PATCH 160/592] qcacmn: Add QDF API to set thread cpu mask Add QDF API to set cpu mask - qdf_thread_set_cpus_allowed_ptr. Linux version of this API is implemented using set_cpus_allowed_ptr linux API. Change-Id: I3122e2b30c6d3f02e9c874c19db610e5f09ec064 CRs-Fixed: 2474323 --- qdf/inc/qdf_threads.h | 12 +++++++++++- qdf/inc/qdf_types.h | 5 +++++ qdf/linux/src/i_qdf_types.h | 1 + qdf/linux/src/qdf_threads.c | 10 +++++++++- 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/qdf/inc/qdf_threads.h b/qdf/inc/qdf_threads.h index 82c0fcccfb84..4e3d5f83b24d 100644 --- a/qdf/inc/qdf_threads.h +++ b/qdf/inc/qdf_threads.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -111,4 +111,14 @@ void qdf_print_thread_trace(qdf_thread_t *thread); * Return: pointer to task struct */ qdf_thread_t *qdf_get_current_task(void); + +/** + * qdf_thread_set_cpus_allowed_mask() - set cpu mask for a particular thread + * @thread: thread for which new cpu mask is set + * @new_mask: new cpu mask to be set for the thread + * + * Return: None + */ +void +qdf_thread_set_cpus_allowed_mask(qdf_thread_t *thread, qdf_cpu_mask *new_mask); #endif /* __QDF_THREADS_H */ diff --git a/qdf/inc/qdf_types.h b/qdf/inc/qdf_types.h index c06f86e27312..6d0f98523d96 100644 --- a/qdf/inc/qdf_types.h +++ b/qdf/inc/qdf_types.h @@ -155,6 +155,11 @@ typedef __qdf_dma_context_t qdf_dma_context_t; typedef __qdf_mem_info_t qdf_mem_info_t; typedef __sgtable_t sgtable_t; +/** + * typepdef qdf_cpu_mask - CPU Mask + */ +typedef __qdf_cpu_mask qdf_cpu_mask; + /** * pointer to net device */ diff --git a/qdf/linux/src/i_qdf_types.h b/qdf/linux/src/i_qdf_types.h index eb0044ff0faa..5e1cce58cdf3 100644 --- a/qdf/linux/src/i_qdf_types.h +++ b/qdf/linux/src/i_qdf_types.h @@ -156,6 +156,7 @@ typedef dma_addr_t __qdf_dma_addr_t; typedef size_t __qdf_dma_size_t; typedef dma_addr_t __qdf_dma_context_t; typedef struct net_device *__qdf_netdev_t; +typedef struct cpumask __qdf_cpu_mask; typedef __le16 __qdf_le16_t; typedef __le32 __qdf_le32_t; typedef __le64 __qdf_le64_t; diff --git a/qdf/linux/src/qdf_threads.c b/qdf/linux/src/qdf_threads.c index ad4540cf0f81..82519e9acf7a 100644 --- a/qdf/linux/src/qdf_threads.c +++ b/qdf/linux/src/qdf_threads.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -196,3 +196,11 @@ qdf_thread_t *qdf_get_current_task(void) return current; } qdf_export_symbol(qdf_get_current_task); + +void +qdf_thread_set_cpus_allowed_mask(qdf_thread_t *thread, qdf_cpu_mask *new_mask) +{ + set_cpus_allowed_ptr(thread, new_mask); +} + +qdf_export_symbol(qdf_thread_set_cpus_allowed_mask); From 9a0db519800363f89f36806caf66d75bc546dabe Mon Sep 17 00:00:00 2001 From: Saket Jha Date: Mon, 13 Jul 2020 20:11:29 +0530 Subject: [PATCH 161/592] qcacmn: Define QDF API for cpumask abstraction Defines QDF APIs for abstraction of cpumask_clear, cpumask_set_cpu, and cpumask_setall. Change-Id: I1678c600c7043b1d4a19e0479ceab9af0ce83d01 CRs-Fixed: 2478893 --- qdf/inc/qdf_threads.h | 25 +++++++++++++++++++++++++ qdf/linux/src/qdf_threads.c | 21 +++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/qdf/inc/qdf_threads.h b/qdf/inc/qdf_threads.h index 4e3d5f83b24d..da598a5ea08a 100644 --- a/qdf/inc/qdf_threads.h +++ b/qdf/inc/qdf_threads.h @@ -121,4 +121,29 @@ qdf_thread_t *qdf_get_current_task(void); */ void qdf_thread_set_cpus_allowed_mask(qdf_thread_t *thread, qdf_cpu_mask *new_mask); + +/** + * qdf_cpumask_clear() - clear all cpus in a cpumask + * @dstp: cpumask pointer + * + * Return: None + */ +void qdf_cpumask_clear(qdf_cpu_mask *dstp); + +/** + * qdf_cpumask_set_cpu() - set a cpu in a cpumask + * @cpu: cpu number + * @dstp: cpumask pointer + * + * Return: None + */ +void qdf_cpumask_set_cpu(unsigned int cpu, qdf_cpu_mask *dstp); + +/** + * qdf_cpumask_setall - set all cpus + * @dstp: cpumask pointer + * + * Return: None + */ +void qdf_cpumask_setall(qdf_cpu_mask *dstp); #endif /* __QDF_THREADS_H */ diff --git a/qdf/linux/src/qdf_threads.c b/qdf/linux/src/qdf_threads.c index 82519e9acf7a..0d56a41fa92d 100644 --- a/qdf/linux/src/qdf_threads.c +++ b/qdf/linux/src/qdf_threads.c @@ -204,3 +204,24 @@ qdf_thread_set_cpus_allowed_mask(qdf_thread_t *thread, qdf_cpu_mask *new_mask) } qdf_export_symbol(qdf_thread_set_cpus_allowed_mask); + +void qdf_cpumask_clear(qdf_cpu_mask *dstp) +{ + cpumask_clear(dstp); +} + +qdf_export_symbol(qdf_cpumask_clear); + +void qdf_cpumask_set_cpu(unsigned int cpu, qdf_cpu_mask *dstp) +{ + cpumask_set_cpu(cpu, dstp); +} + +qdf_export_symbol(qdf_cpumask_set_cpu); + +void qdf_cpumask_setall(qdf_cpu_mask *dstp) +{ + cpumask_setall(dstp); +} + +qdf_export_symbol(qdf_cpumask_setall); From 2d7cd3744a8579d2b4bc3d325818e948fcac716e Mon Sep 17 00:00:00 2001 From: Surabhi Vishnoi Date: Mon, 13 Jul 2020 22:42:59 +0530 Subject: [PATCH 162/592] qcacld-3.0: Update pm_qos request only if vote or tx or rx level changes Call the hdd_pm_qos_update_request only if vote level or tx level or rx level changes. Change-Id: I29933ecdfbc4a10e58b8d72baa91efbca5a994c0 CRs-Fixed: 2730910 --- core/hdd/src/wlan_hdd_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 3d40c58ff0d8..8e879c493c70 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -8953,13 +8953,13 @@ static void hdd_pld_request_bus_bandwidth(struct hdd_context *hdd_ctx, hdd_ctx->hdd_txrx_hist[index].qtime = qdf_get_log_timestamp(); hdd_ctx->hdd_txrx_hist_idx++; hdd_ctx->hdd_txrx_hist_idx &= NUM_TX_RX_HISTOGRAM_MASK; - } /* Clear all the mask if no silver/gold vote is required */ if (next_vote_level < PLD_BUS_WIDTH_MEDIUM) cpumask_clear(&pm_qos_cpu_mask); hdd_pm_qos_update_request(hdd_ctx, &pm_qos_cpu_mask); + } hdd_display_periodic_stats(hdd_ctx, (total_pkts > 0) ? true : false); From 993457be270fea32321f6c99ce440aaa5bb16c82 Mon Sep 17 00:00:00 2001 From: nshrivas Date: Mon, 13 Jul 2020 13:47:59 -0700 Subject: [PATCH 163/592] Release 5.2.03.29E Release 5.2.03.29E Change-Id: I10554928561b7e12700b6407ed4d3bfa5fa4ba06 CRs-Fixed: 774533 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index 2cff48351085..2b0b60cdcf6b 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -32,9 +32,9 @@ #define QWLAN_VERSION_MAJOR 5 #define QWLAN_VERSION_MINOR 2 #define QWLAN_VERSION_PATCH 03 -#define QWLAN_VERSION_EXTRA "D" +#define QWLAN_VERSION_EXTRA "E" #define QWLAN_VERSION_BUILD 29 -#define QWLAN_VERSIONSTR "5.2.03.29D" +#define QWLAN_VERSIONSTR "5.2.03.29E" #endif /* QWLAN_VERSION_H */ From 8ade5805628c5c8c3ea1b00438d869a15fa93507 Mon Sep 17 00:00:00 2001 From: Sathishkumar Muruganandam Date: Tue, 28 Aug 2018 17:51:38 +0530 Subject: [PATCH 164/592] UPSTREAM: mac80211: add missing WFA Multi-AP backhaul STA Rx requirement MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current mac80211 WDS (4-address mode) can be used to cover most of the Multi-AP requirements for Data frames per the WFA Multi-AP Specification v1.0. When configuring AP/STA interfaces in 4-address mode, they are able to function as fronthaul AP/backhaul STA of Multi-AP device complying below Tx, Rx requirements except one missing STA Rx requirement added by this patch. Multi-AP specification section 14.1 describes the following requirements: Transmitter requirements ------------------------ 1. Fronthaul AP i) When DA!=RA of backhaul STA, must use 4-address format ii) When DA==RA of backhaul STA, shall use either 3-address or 4-address format with RA updated with STA MAC (mac80211 support 4-address format via AP/VLAN interface) 2. Backhaul STA i) When SA!=TA of backhaul STA, must use 4-address format ii) When SA==TA of backhaul STA, shall use either 3-address or 4-address format with RA updated with AP MAC (mac80211 support 4-address format via use_4addr) Receiver requirements --------------------- 1. Fronthaul AP i) When SA!=TA of backhaul STA, must support receiving 4-address format frames ii) When SA==TA of backhaul STA, must support receiving both 3-address and 4-address format frames (mac80211 support both 3-addr & 4-addr via AP/VLAN interface) 2. Backhaul STA i) When DA!=RA of backhaul STA, must support receiving 4-address format frames ii) When DA==RA of backhaul STA, must support receiving both 3-address and 4-address format frames (mac80211 support only receiving 4-address format via use_4addr) This patch addresses the above Rx requirement (ii) for backhaul STA to receive unicast (DA==RA) 3-address frames in addition to 4-address frames. The current design doesn't accept 3-address frames when configured in 4-address mode (use_4addr). Hence add a check to allow 3-address frames when DA==RA of backhaul STA (adhering to Table 9-26 of IEEE Std 802.11™-2016). This case was tested with a bridged station interface when associated with a non-mac80211 based vendor AP implementation using 3-address frames for WDS. STA was able to support the Multi-AP Rx requirement when DA==RA. No issues, no loops seen when tested with mac80211 based AP as well. Verified and confirmed all other Tx and Rx requirements of AP and STA for Multi-AP respectively. They all work using the current mac80211-WDS design. Signed-off-by: Sathishkumar Muruganandam Signed-off-by: Johannes Berg Change-Id: Iea5367f7664399c178b5749f7f9f46d7730ec665 Git-commit: 1ecef20cf12865729c86b0e428584635c77159ba Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git Signed-off-by: Balaji Pothunoori --- net/mac80211/rx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 31000622376d..45226c6aa45b 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -2206,7 +2206,7 @@ __ieee80211_data_to_8023(struct ieee80211_rx_data *rx, bool *port_control) if (!sdata->u.mgd.use_4addr) return -1; - else + else if (!ether_addr_equal(hdr->addr1, sdata->vif.addr)) check_port_control = true; } From a22ad35573a77ac72c6c68e0a89ef8d6ffa39ffa Mon Sep 17 00:00:00 2001 From: Nisha Menon Date: Mon, 28 Oct 2019 16:24:21 -0700 Subject: [PATCH 165/592] qcacld-3.0: CPU mask not set for affine cores on init Set cpu_mask for affine cores on init before sending a request to PM QoS interface to insert a element into the list for DMA latency in the QoS framework. Change-Id: I81f17077c6ddce69c99047c46cef008b6b195d77 CRs-Fixed: 2551349 --- core/hdd/src/wlan_hdd_main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 8e879c493c70..947bea40b93b 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -8708,6 +8708,8 @@ static inline void hdd_pm_qos_update_request(struct hdd_context *hdd_ctx, static inline void hdd_update_pm_qos_affine_cores(struct hdd_context *hdd_ctx) { hdd_ctx->pm_qos_req.type = PM_QOS_REQ_AFFINE_CORES; + qdf_cpumask_clear(&hdd_ctx->pm_qos_req.cpus_affine); + hdd_pm_qos_update_cpu_mask(&hdd_ctx->pm_qos_req.cpus_affine, false); } #else static inline void hdd_update_pm_qos_affine_cores(struct hdd_context *hdd_ctx) @@ -8719,6 +8721,8 @@ static inline void hdd_pm_qos_add_request(struct hdd_context *hdd_ctx) hdd_update_pm_qos_affine_cores(hdd_ctx); pm_qos_add_request(&hdd_ctx->pm_qos_req, PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE); + hdd_info("Set cpu_mask %*pb for affine_cores", + cpumask_pr_args(&hdd_ctx->pm_qos_req.cpus_affine)); } static inline void hdd_pm_qos_remove_request(struct hdd_context *hdd_ctx) From 65a37e7688deca774829a75172bca40d3377a139 Mon Sep 17 00:00:00 2001 From: Mahesh Kumar Kalikot Veetil Date: Thu, 10 Oct 2019 22:59:33 -0700 Subject: [PATCH 166/592] qcacld-3.0: Fix pm_qos update logic If the CPU latency requirement is not there, set the pm qos vote to default value. The target values of resume latency and active state latency tolerance are the minimum of the request values held in the parameter list elements. Change-Id: Ia5a68c024c08043da840490b6207803523f5a34a CRs-Fixed: 2554446 --- core/hdd/src/wlan_hdd_main.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 947bea40b93b..962435a69c84 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -8694,8 +8694,13 @@ static inline void hdd_pm_qos_update_request(struct hdd_context *hdd_ctx, cpumask_t *pm_qos_cpu_mask) { cpumask_copy(&hdd_ctx->pm_qos_req.cpus_affine, pm_qos_cpu_mask); + /* Latency value to be read from INI */ - pm_qos_update_request(&hdd_ctx->pm_qos_req, 1); + if (cpumask_empty(pm_qos_cpu_mask)) + pm_qos_update_request(&hdd_ctx->pm_qos_req, + PM_QOS_DEFAULT_VALUE); + else + pm_qos_update_request(&hdd_ctx->pm_qos_req, 1); } #ifdef CONFIG_SMP From b5685ff77acb8990a21c2c780bdfb6cf2b3b2d6a Mon Sep 17 00:00:00 2001 From: nshrivas Date: Mon, 13 Jul 2020 23:53:29 -0700 Subject: [PATCH 167/592] Release 5.2.03.29F Release 5.2.03.29F Change-Id: I24170bf59fcbad98a8a53646c44aab9b8663f760 CRs-Fixed: 774533 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index 2b0b60cdcf6b..064fb4cf5a6e 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -32,9 +32,9 @@ #define QWLAN_VERSION_MAJOR 5 #define QWLAN_VERSION_MINOR 2 #define QWLAN_VERSION_PATCH 03 -#define QWLAN_VERSION_EXTRA "E" +#define QWLAN_VERSION_EXTRA "F" #define QWLAN_VERSION_BUILD 29 -#define QWLAN_VERSIONSTR "5.2.03.29E" +#define QWLAN_VERSIONSTR "5.2.03.29F" #endif /* QWLAN_VERSION_H */ From f0a4a745133cc4650c673e08bdb3fc46c78884be Mon Sep 17 00:00:00 2001 From: Surabhi Vishnoi Date: Wed, 17 Apr 2019 14:01:45 +0530 Subject: [PATCH 168/592] UPSTREAM: ath10k: Add wmi tlv vdev subtype for mesh in WCN3990 There is a disparity in wmi and wmi tlv vdev subtype enum for WMI_VDEV_SUBTYPE_MESH_11S. Add different enum for wmi tlv vdev subtype to support vdev of subtype mesh 11s for WCN3990. Tested HW: WCN3990 Signed-off-by: Surabhi Vishnoi Signed-off-by: Kalle Valo Change-Id: Iea5367f7664399c178b5749f7f9f46d7730ee781 Git-commit: a7368c395fc3ebd544cf6ceaca715adb4e85eff1 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git Signed-off-by: Balaji Pothunoori --- drivers/net/wireless/ath/ath10k/wmi-tlv.c | 24 ++++++++++++++++++++++- drivers/net/wireless/ath/ath10k/wmi-tlv.h | 10 ++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index 6ab44add9f51..520a813477fc 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -1704,6 +1704,28 @@ ath10k_wmi_tlv_op_gen_stop_scan(struct ath10k *ar, return skb; } +static int ath10k_wmi_tlv_op_get_vdev_subtype(struct ath10k *ar, + enum wmi_vdev_subtype subtype) +{ + switch (subtype) { + case WMI_VDEV_SUBTYPE_NONE: + return WMI_TLV_VDEV_SUBTYPE_NONE; + case WMI_VDEV_SUBTYPE_P2P_DEVICE: + return WMI_TLV_VDEV_SUBTYPE_P2P_DEV; + case WMI_VDEV_SUBTYPE_P2P_CLIENT: + return WMI_TLV_VDEV_SUBTYPE_P2P_CLI; + case WMI_VDEV_SUBTYPE_P2P_GO: + return WMI_TLV_VDEV_SUBTYPE_P2P_GO; + case WMI_VDEV_SUBTYPE_PROXY_STA: + return WMI_TLV_VDEV_SUBTYPE_PROXY_STA; + case WMI_VDEV_SUBTYPE_MESH_11S: + return WMI_TLV_VDEV_SUBTYPE_MESH_11S; + case WMI_VDEV_SUBTYPE_MESH_NON_11S: + return -ENOTSUPP; + } + return -ENOTSUPP; +} + static struct sk_buff * ath10k_wmi_tlv_op_gen_vdev_create(struct ath10k *ar, u32 vdev_id, @@ -3826,7 +3848,7 @@ static const struct wmi_ops wmi_tlv_ops = { .gen_tdls_peer_update = ath10k_wmi_tlv_op_gen_tdls_peer_update, .gen_adaptive_qcs = ath10k_wmi_tlv_op_gen_adaptive_qcs, .fw_stats_fill = ath10k_wmi_main_op_fw_stats_fill, - .get_vdev_subtype = ath10k_wmi_op_get_vdev_subtype, + .get_vdev_subtype = ath10k_wmi_tlv_op_get_vdev_subtype, .gen_echo = ath10k_wmi_tlv_op_gen_echo, .gen_vdev_spectral_conf = ath10k_wmi_tlv_op_gen_vdev_spectral_conf, .gen_vdev_spectral_enable = ath10k_wmi_tlv_op_gen_vdev_spectral_enable, diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.h b/drivers/net/wireless/ath/ath10k/wmi-tlv.h index eac0a5364a57..8631a34c31f9 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.h +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.h @@ -1721,6 +1721,16 @@ struct wmi_tlv_start_scan_cmd { struct wmi_mac_addr mac_mask; } __packed; +enum wmi_tlv_vdev_subtype { + WMI_TLV_VDEV_SUBTYPE_NONE = 0, + WMI_TLV_VDEV_SUBTYPE_P2P_DEV = 1, + WMI_TLV_VDEV_SUBTYPE_P2P_CLI = 2, + WMI_TLV_VDEV_SUBTYPE_P2P_GO = 3, + WMI_TLV_VDEV_SUBTYPE_PROXY_STA = 4, + WMI_TLV_VDEV_SUBTYPE_MESH = 5, + WMI_TLV_VDEV_SUBTYPE_MESH_11S = 6, +}; + struct wmi_tlv_vdev_start_cmd { __le32 vdev_id; __le32 requestor_id; From 9d3885467752dbabf7cdbce3c664cd6dfd64b6db Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 2 Nov 2018 10:17:47 -0700 Subject: [PATCH 169/592] UPSTREAM: ath10k: assign 'n_cipher_suites' for WCN3990 Commit 2ea9f12cefe4 ("ath10k: add new cipher suite support") added a new n_cipher_suites HW param with a fallback value and a warning log. Commit 03a72288c546 ("ath10k: wmi: add hw params entry for wcn3990") later added WCN3990 HW entries, but it missed the n_cipher_suites. Rather than seeing this warning every boot ath10k_snoc 18800000.wifi: invalid hw_params.n_cipher_suites 0 let's provide the appropriate value. Cc: Rakesh Pillai Cc: Govind Singh Signed-off-by: Brian Norris Signed-off-by: Kalle Valo Change-Id: Iea5367f7664399c178b5749f7f9f46d7730ee782 Git-commit: 2bd345cd2bfc0bd44528896313c0b45f087bdf67 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git Signed-off-by: Balaji Pothunoori --- drivers/net/wireless/ath/ath10k/core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 81e9b36c056a..d543b3ebe8bf 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -538,6 +538,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .hw_ops = &wcn3990_ops, .decap_align_bytes = 1, .num_peers = TARGET_HL_10_TLV_NUM_PEERS, + .n_cipher_suites = 8, .ast_skid_limit = TARGET_HL_10_TLV_AST_SKID_LIMIT, .num_wds_entries = TARGET_HL_10_TLV_NUM_WDS_ENTRIES, .target_64bit = true, From 7167f9e338c182b0435e9c61a67999c52b0bd0f9 Mon Sep 17 00:00:00 2001 From: Abhishek Ambure Date: Fri, 8 Feb 2019 14:55:23 +0200 Subject: [PATCH 170/592] UPSTREAM: ath10k: assign 'n_cipher_suites = 11' for WCN3990 to enable WPA3 Hostapd uses CCMP, GCMP & GCMP-256 as 'wpa_pairwise' option to run WPA3. In WCN3990 firmware cipher suite numbers 9 to 11 are for CCMP, GCMP & GCMP-256. To enable CCMP, GCMP & GCMP-256 cipher suites in WCN3990 firmware, host sets 'n_cipher_suites = 11' while initializing hardware parameters. Tested HW: WCN3990 Tested FW: WLAN.HL.2.0-01188-QCAHLSWMTPLZ-1 Signed-off-by: Abhishek Ambure Signed-off-by: Kalle Valo Change-Id: Iea5367f7664399c178b5749f7f9f46d7730ee783 Git-commit: 7ba31e6e0cdc0cc2e60e1fcbf467f3c95aea948e Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git Signed-off-by: Balaji Pothunoori --- drivers/net/wireless/ath/ath10k/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index d543b3ebe8bf..452297924255 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -538,7 +538,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .hw_ops = &wcn3990_ops, .decap_align_bytes = 1, .num_peers = TARGET_HL_10_TLV_NUM_PEERS, - .n_cipher_suites = 8, + .n_cipher_suites = 11, .ast_skid_limit = TARGET_HL_10_TLV_AST_SKID_LIMIT, .num_wds_entries = TARGET_HL_10_TLV_NUM_WDS_ENTRIES, .target_64bit = true, From 88eb6b4211ac02d307457c1f43fda935f49167c0 Mon Sep 17 00:00:00 2001 From: Abhishek Ambure Date: Fri, 8 Feb 2019 14:55:26 +0200 Subject: [PATCH 171/592] UPSTREAM: ath10k: update GCMP & GCMP-256 cipher suite number for WCN3990 TLV based firmware ex. QCA6174, WCN3990 expects key cipher value set to 9 while non-TLV firmware expects key cipher value set to 8 for enabling GCMP and GCMP-256 cipher suites. To fix this problem, attach the key cipher suite values based on wmi version. Tested HW: WCN3990 Tested FW: WLAN.HL.2.0-01188-QCAHLSWMTPLZ-1 Signed-off-by: Abhishek Ambure Signed-off-by: Kalle Valo Change-Id: Iea5367f7664399c178b5749f7f9f46d7730ee784 Git-commit: 7d94f862d6482e1159ccca669cbf21c724d159e1 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git [bpothuno@codeaurora.org: fix trivial merge conflicts] Signed-off-by: Balaji Pothunoori --- drivers/net/wireless/ath/ath10k/core.h | 1 + drivers/net/wireless/ath/ath10k/mac.c | 12 ++++----- drivers/net/wireless/ath/ath10k/wmi-tlv.c | 6 +++-- drivers/net/wireless/ath/ath10k/wmi.c | 30 +++++++++++++++++++++ drivers/net/wireless/ath/ath10k/wmi.h | 33 ++++++++++++++++------- 5 files changed, 65 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 04dab735de7f..b8279e1ab69a 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -1037,6 +1037,7 @@ struct ath10k { u32 ampdu_reference; + const u8 *wmi_key_cipher; void *ce_priv; /* must be last */ diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index e55524749f8f..254caedfc1e2 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -231,24 +231,24 @@ static int ath10k_send_key(struct ath10k_vif *arvif, switch (key->cipher) { case WLAN_CIPHER_SUITE_CCMP: - arg.key_cipher = WMI_CIPHER_AES_CCM; + arg.key_cipher = ar->wmi_key_cipher[WMI_CIPHER_AES_CCM]; key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV_MGMT; break; case WLAN_CIPHER_SUITE_TKIP: - arg.key_cipher = WMI_CIPHER_TKIP; + arg.key_cipher = ar->wmi_key_cipher[WMI_CIPHER_TKIP]; arg.key_txmic_len = 8; arg.key_rxmic_len = 8; break; case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP104: - arg.key_cipher = WMI_CIPHER_WEP; + arg.key_cipher = ar->wmi_key_cipher[WMI_CIPHER_WEP]; break; case WLAN_CIPHER_SUITE_CCMP_256: - arg.key_cipher = WMI_CIPHER_AES_CCM; + arg.key_cipher = ar->wmi_key_cipher[WMI_CIPHER_AES_CCM]; break; case WLAN_CIPHER_SUITE_GCMP: case WLAN_CIPHER_SUITE_GCMP_256: - arg.key_cipher = WMI_CIPHER_AES_GCM; + arg.key_cipher = ar->wmi_key_cipher[WMI_CIPHER_AES_GCM]; break; case WLAN_CIPHER_SUITE_BIP_GMAC_128: case WLAN_CIPHER_SUITE_BIP_GMAC_256: @@ -265,7 +265,7 @@ static int ath10k_send_key(struct ath10k_vif *arvif, key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; if (cmd == DISABLE_KEY) { - arg.key_cipher = WMI_CIPHER_NONE; + arg.key_cipher = ar->wmi_key_cipher[WMI_CIPHER_NONE]; arg.key_data = NULL; } diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index 520a813477fc..06b7362e51e4 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -1954,9 +1954,11 @@ ath10k_wmi_tlv_op_gen_vdev_install_key(struct ath10k *ar, size_t len; void *ptr; - if (arg->key_cipher == WMI_CIPHER_NONE && arg->key_data != NULL) + if (arg->key_cipher == ar->wmi_key_cipher[WMI_CIPHER_NONE] && + arg->key_data) return ERR_PTR(-EINVAL); - if (arg->key_cipher != WMI_CIPHER_NONE && arg->key_data == NULL) + if (arg->key_cipher != ar->wmi_key_cipher[WMI_CIPHER_NONE] && + !arg->key_data) return ERR_PTR(-EINVAL); len = sizeof(*tlv) + sizeof(*cmd) + diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index be3bade3d101..1d0b8f26afa1 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -1588,6 +1588,30 @@ static struct wmi_pdev_param_map wmi_10_4_pdev_param_map = { .enable_btcoex = WMI_10_4_PDEV_PARAM_ENABLE_BTCOEX, }; +static const u8 wmi_key_cipher_suites[] = { + [WMI_CIPHER_NONE] = WMI_CIPHER_NONE, + [WMI_CIPHER_WEP] = WMI_CIPHER_WEP, + [WMI_CIPHER_TKIP] = WMI_CIPHER_TKIP, + [WMI_CIPHER_AES_OCB] = WMI_CIPHER_AES_OCB, + [WMI_CIPHER_AES_CCM] = WMI_CIPHER_AES_CCM, + [WMI_CIPHER_WAPI] = WMI_CIPHER_WAPI, + [WMI_CIPHER_CKIP] = WMI_CIPHER_CKIP, + [WMI_CIPHER_AES_CMAC] = WMI_CIPHER_AES_CMAC, + [WMI_CIPHER_AES_GCM] = WMI_CIPHER_AES_GCM, +}; + +static const u8 wmi_tlv_key_cipher_suites[] = { + [WMI_CIPHER_NONE] = WMI_TLV_CIPHER_NONE, + [WMI_CIPHER_WEP] = WMI_TLV_CIPHER_WEP, + [WMI_CIPHER_TKIP] = WMI_TLV_CIPHER_TKIP, + [WMI_CIPHER_AES_OCB] = WMI_TLV_CIPHER_AES_OCB, + [WMI_CIPHER_AES_CCM] = WMI_TLV_CIPHER_AES_CCM, + [WMI_CIPHER_WAPI] = WMI_TLV_CIPHER_WAPI, + [WMI_CIPHER_CKIP] = WMI_TLV_CIPHER_CKIP, + [WMI_CIPHER_AES_CMAC] = WMI_TLV_CIPHER_AES_CMAC, + [WMI_CIPHER_AES_GCM] = WMI_TLV_CIPHER_AES_GCM, +}; + static const struct wmi_peer_flags_map wmi_peer_flags_map = { .auth = WMI_PEER_AUTH, .qos = WMI_PEER_QOS, @@ -8421,6 +8445,7 @@ int ath10k_wmi_attach(struct ath10k *ar) ar->wmi.vdev_param = &wmi_10_4_vdev_param_map; ar->wmi.pdev_param = &wmi_10_4_pdev_param_map; ar->wmi.peer_flags = &wmi_10_2_peer_flags_map; + ar->wmi_key_cipher = wmi_key_cipher_suites; break; case ATH10K_FW_WMI_OP_VERSION_10_2_4: ar->wmi.cmd = &wmi_10_2_4_cmd_map; @@ -8428,6 +8453,7 @@ int ath10k_wmi_attach(struct ath10k *ar) ar->wmi.vdev_param = &wmi_10_2_4_vdev_param_map; ar->wmi.pdev_param = &wmi_10_2_4_pdev_param_map; ar->wmi.peer_flags = &wmi_10_2_peer_flags_map; + ar->wmi_key_cipher = wmi_key_cipher_suites; break; case ATH10K_FW_WMI_OP_VERSION_10_2: ar->wmi.cmd = &wmi_10_2_cmd_map; @@ -8435,6 +8461,7 @@ int ath10k_wmi_attach(struct ath10k *ar) ar->wmi.vdev_param = &wmi_10x_vdev_param_map; ar->wmi.pdev_param = &wmi_10x_pdev_param_map; ar->wmi.peer_flags = &wmi_10_2_peer_flags_map; + ar->wmi_key_cipher = wmi_key_cipher_suites; break; case ATH10K_FW_WMI_OP_VERSION_10_1: ar->wmi.cmd = &wmi_10x_cmd_map; @@ -8442,6 +8469,7 @@ int ath10k_wmi_attach(struct ath10k *ar) ar->wmi.vdev_param = &wmi_10x_vdev_param_map; ar->wmi.pdev_param = &wmi_10x_pdev_param_map; ar->wmi.peer_flags = &wmi_10x_peer_flags_map; + ar->wmi_key_cipher = wmi_key_cipher_suites; break; case ATH10K_FW_WMI_OP_VERSION_MAIN: ar->wmi.cmd = &wmi_cmd_map; @@ -8449,9 +8477,11 @@ int ath10k_wmi_attach(struct ath10k *ar) ar->wmi.vdev_param = &wmi_vdev_param_map; ar->wmi.pdev_param = &wmi_pdev_param_map; ar->wmi.peer_flags = &wmi_peer_flags_map; + ar->wmi_key_cipher = wmi_key_cipher_suites; break; case ATH10K_FW_WMI_OP_VERSION_TLV: ath10k_wmi_tlv_attach(ar); + ar->wmi_key_cipher = wmi_tlv_key_cipher_suites; break; case ATH10K_FW_WMI_OP_VERSION_UNSET: case ATH10K_FW_WMI_OP_VERSION_MAX: diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 9ca3cea79fce..88ca6e576cbd 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -4765,15 +4765,30 @@ struct wmi_key_seq_counter { __le32 key_seq_counter_h; } __packed; -#define WMI_CIPHER_NONE 0x0 /* clear key */ -#define WMI_CIPHER_WEP 0x1 -#define WMI_CIPHER_TKIP 0x2 -#define WMI_CIPHER_AES_OCB 0x3 -#define WMI_CIPHER_AES_CCM 0x4 -#define WMI_CIPHER_WAPI 0x5 -#define WMI_CIPHER_CKIP 0x6 -#define WMI_CIPHER_AES_CMAC 0x7 -#define WMI_CIPHER_AES_GCM 0x8 +enum wmi_cipher_suites { + WMI_CIPHER_NONE, + WMI_CIPHER_WEP, + WMI_CIPHER_TKIP, + WMI_CIPHER_AES_OCB, + WMI_CIPHER_AES_CCM, + WMI_CIPHER_WAPI, + WMI_CIPHER_CKIP, + WMI_CIPHER_AES_CMAC, + WMI_CIPHER_AES_GCM, +}; + +enum wmi_tlv_cipher_suites { + WMI_TLV_CIPHER_NONE, + WMI_TLV_CIPHER_WEP, + WMI_TLV_CIPHER_TKIP, + WMI_TLV_CIPHER_AES_OCB, + WMI_TLV_CIPHER_AES_CCM, + WMI_TLV_CIPHER_WAPI, + WMI_TLV_CIPHER_CKIP, + WMI_TLV_CIPHER_AES_CMAC, + WMI_TLV_CIPHER_ANY, + WMI_TLV_CIPHER_AES_GCM, +}; struct wmi_vdev_install_key_cmd { __le32 vdev_id; From 8572d72cf5bd81654050ad6e56a28eab8cb2cfd7 Mon Sep 17 00:00:00 2001 From: Surabhi Vishnoi Date: Wed, 17 Apr 2019 14:01:47 +0530 Subject: [PATCH 172/592] UPSTREAM: ath10k: Add wmi tlv service map for mesh 11s WCN3990 firmware advertises the service WMI_TLV_SERVICE_MESH_11S for mesh 11s. Map this wmi tlv service to enable mesh 11s for WCN3990. Tested HW: WCN3990 Signed-off-by: Surabhi Vishnoi Signed-off-by: Kalle Valo Change-Id: Iea5367f7664399c178b5749f7f9f46d7730ee785 Git-commit: 7835d8f8792dab0e3704951d5009c2b832d4513d Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git Signed-off-by: Balaji Pothunoori --- drivers/net/wireless/ath/ath10k/wmi-tlv.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.h b/drivers/net/wireless/ath/ath10k/wmi-tlv.h index 8631a34c31f9..1717835d532d 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.h +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.h @@ -1554,6 +1554,8 @@ wmi_tlv_svc_map(const __le32 *in, unsigned long *out, size_t len) WMI_SERVICE_SAP_AUTH_OFFLOAD, len); SVCMAP(WMI_TLV_SERVICE_MGMT_TX_WMI, WMI_SERVICE_MGMT_TX_WMI, len); + SVCMAP(WMI_TLV_SERVICE_MESH_11S, + WMI_SERVICE_MESH_11S, len); } static inline void From e34c6400786b36d3e184da93ec459cca69b9c905 Mon Sep 17 00:00:00 2001 From: Rakesh Pillai Date: Mon, 3 Jun 2019 17:41:33 +0300 Subject: [PATCH 173/592] UPSTREAM: ath10k: wait for vdev delete response from firmware When we add an interface immediately after removing the interface the vdev deletion in firmware might not have been completed. We need to synchronize the vdev creation with the firmware. Wait for vdev delete response from firmware when we remove an interface. Tested HW: WCN3990 Tested FW: WLAN.HL.2.0-01188-QCAHLSWMTPLZ-1 Signed-off-by: Rakesh Pillai Signed-off-by: Kalle Valo Change-Id: Iea5367f7664399c178b5749f7f9f46d7730ee786 Git-commit: fe36e70f766ed99c5a140f8e265e81dd39897bb6 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git [bpothuno@codeaurora.org: fix trivial merge conflicts] Signed-off-by: Balaji Pothunoori --- drivers/net/wireless/ath/ath10k/core.c | 3 +++ drivers/net/wireless/ath/ath10k/core.h | 5 ++++- drivers/net/wireless/ath/ath10k/mac.c | 15 +++++++++++++++ drivers/net/wireless/ath/ath10k/wmi-tlv.c | 11 +++++++++++ drivers/net/wireless/ath/ath10k/wmi-tlv.h | 5 +++++ drivers/net/wireless/ath/ath10k/wmi.h | 2 ++ 6 files changed, 40 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 452297924255..7c9dc64f223c 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -1,6 +1,7 @@ /* * Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. + * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -2101,6 +2102,7 @@ static void ath10k_core_restart(struct work_struct *work) complete(&ar->offchan_tx_completed); complete(&ar->install_key_done); complete(&ar->vdev_setup_done); + complete(&ar->vdev_delete_done); complete(&ar->thermal.wmi_sync); complete(&ar->bss_survey_done); wake_up(&ar->htt.empty_tx_wq); @@ -3003,6 +3005,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, init_completion(&ar->install_key_done); init_completion(&ar->vdev_setup_done); + init_completion(&ar->vdev_delete_done); init_completion(&ar->thermal.wmi_sync); init_completion(&ar->bss_survey_done); diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index b8279e1ab69a..6919435ee591 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -1,6 +1,7 @@ /* * Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. + * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -374,7 +375,8 @@ struct ath10k_sta { #endif }; -#define ATH10K_VDEV_SETUP_TIMEOUT_HZ (5 * HZ) +#define ATH10K_VDEV_SETUP_TIMEOUT_HZ (5 * HZ) +#define ATH10K_VDEV_DELETE_TIMEOUT_HZ (5 * HZ) enum ath10k_beacon_state { ATH10K_BEACON_SCHEDULED = 0, @@ -913,6 +915,7 @@ struct ath10k { int last_wmi_vdev_start_status; struct completion vdev_setup_done; + struct completion vdev_delete_done; struct workqueue_struct *workqueue; /* Auxiliary workqueue */ diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 254caedfc1e2..4deeef1f7f8d 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -1003,6 +1003,7 @@ static int ath10k_monitor_vdev_start(struct ath10k *ar, int vdev_id) arg.channel.max_antenna_gain = channel->max_antenna_gain * 2; reinit_completion(&ar->vdev_setup_done); + reinit_completion(&ar->vdev_delete_done); ret = ath10k_wmi_vdev_start(ar, &arg); if (ret) { @@ -1052,6 +1053,7 @@ static int ath10k_monitor_vdev_stop(struct ath10k *ar) ar->monitor_vdev_id, ret); reinit_completion(&ar->vdev_setup_done); + reinit_completion(&ar->vdev_delete_done); ret = ath10k_wmi_vdev_stop(ar, ar->monitor_vdev_id); if (ret) @@ -1393,6 +1395,7 @@ static int ath10k_vdev_stop(struct ath10k_vif *arvif) lockdep_assert_held(&ar->conf_mutex); reinit_completion(&ar->vdev_setup_done); + reinit_completion(&ar->vdev_delete_done); ret = ath10k_wmi_vdev_stop(ar, arvif->vdev_id); if (ret) { @@ -1429,6 +1432,7 @@ static int ath10k_vdev_start_restart(struct ath10k_vif *arvif, lockdep_assert_held(&ar->conf_mutex); reinit_completion(&ar->vdev_setup_done); + reinit_completion(&ar->vdev_delete_done); arg.vdev_id = arvif->vdev_id; arg.dtim_period = arvif->dtim_period; @@ -5280,6 +5284,7 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw, struct ath10k *ar = hw->priv; struct ath10k_vif *arvif = (void *)vif->drv_priv; struct ath10k_peer *peer; + unsigned long time_left; int ret; int i; @@ -5321,6 +5326,15 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw, ath10k_warn(ar, "failed to delete WMI vdev %i: %d\n", arvif->vdev_id, ret); + if (test_bit(WMI_SERVICE_SYNC_DELETE_CMDS, ar->wmi.svc_map)) { + time_left = wait_for_completion_timeout(&ar->vdev_delete_done, + ATH10K_VDEV_DELETE_TIMEOUT_HZ); + if (time_left == 0) { + ath10k_warn(ar, "Timeout in receiving vdev delete response\n"); + goto out; + } + } + /* Some firmware revisions don't notify host about self-peer removal * until after associated vdev is deleted. */ @@ -5371,6 +5385,7 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw, ath10k_mac_txq_unref(ar, vif->txq); +out: mutex_unlock(&ar->conf_mutex); } diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index 06b7362e51e4..5085533d4241 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -1,6 +1,7 @@ /* * Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. + * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -222,6 +223,13 @@ static int ath10k_wmi_tlv_event_bcn_tx_status(struct ath10k *ar, return 0; } +static void ath10k_wmi_tlv_event_vdev_delete_resp(struct ath10k *ar, + struct sk_buff *skb) +{ + ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_VDEV_DELETE_RESP_EVENTID\n"); + complete(&ar->vdev_delete_done); +} + static int ath10k_wmi_tlv_event_diag_data(struct ath10k *ar, struct sk_buff *skb) { @@ -468,6 +476,9 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb) case WMI_TLV_VDEV_STOPPED_EVENTID: ath10k_wmi_event_vdev_stopped(ar, skb); break; + case WMI_TLV_VDEV_DELETE_RESP_EVENTID: + ath10k_wmi_tlv_event_vdev_delete_resp(ar, skb); + break; case WMI_TLV_PEER_STA_KICKOUT_EVENTID: ath10k_wmi_event_peer_sta_kickout(ar, skb); break; diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.h b/drivers/net/wireless/ath/ath10k/wmi-tlv.h index 1717835d532d..ebc7c1cd16dc 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.h +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.h @@ -1,6 +1,7 @@ /* * Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. + * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -309,6 +310,8 @@ enum wmi_tlv_event_id { WMI_TLV_VDEV_STOPPED_EVENTID, WMI_TLV_VDEV_INSTALL_KEY_COMPLETE_EVENTID, WMI_TLV_VDEV_MCC_BCN_INTERVAL_CHANGE_REQ_EVENTID, + WMI_TLV_VDEV_TSF_REPORT_EVENTID, + WMI_TLV_VDEV_DELETE_RESP_EVENTID, WMI_TLV_PEER_STA_KICKOUT_EVENTID = WMI_TLV_EV(WMI_TLV_GRP_PEER), WMI_TLV_PEER_INFO_EVENTID, WMI_TLV_PEER_TX_FAIL_CNT_THR_EVENTID, @@ -1556,6 +1559,8 @@ wmi_tlv_svc_map(const __le32 *in, unsigned long *out, size_t len) WMI_SERVICE_MGMT_TX_WMI, len); SVCMAP(WMI_TLV_SERVICE_MESH_11S, WMI_SERVICE_MESH_11S, len); + SVCMAP(WMI_TLV_SERVICE_SYNC_DELETE_CMDS, + WMI_SERVICE_SYNC_DELETE_CMDS, len); } static inline void diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 88ca6e576cbd..ffe6c166c7b6 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -202,6 +202,7 @@ enum wmi_service { WMI_SERVICE_TPC_STATS_FINAL, WMI_SERVICE_RESET_CHIP, WMI_SERVICE_SPOOF_MAC_SUPPORT, + WMI_SERVICE_SYNC_DELETE_CMDS, /* keep last */ WMI_SERVICE_MAX, @@ -453,6 +454,7 @@ static inline char *wmi_service_name(int service_id) SVCSTR(WMI_SERVICE_TDLS_CONN_TRACKER_IN_HOST_MODE); SVCSTR(WMI_SERVICE_TDLS_EXPLICIT_MODE_ONLY); SVCSTR(WMI_SERVICE_TDLS_WIDER_BANDWIDTH); + SVCSTR(WMI_SERVICE_SYNC_DELETE_CMDS); default: return NULL; } From 69490b23dd8d1ed9a680935bdada982e5db6eb65 Mon Sep 17 00:00:00 2001 From: Dundi Raviteja Date: Mon, 3 Jun 2019 17:41:51 +0300 Subject: [PATCH 174/592] UPSTREAM: ath10k: Add peer delete response event Peer creation in firmware fails if last peer deletion is still in progress. The firmware sends a peer delete response event if it advertises the service WMI_SERVICE_SYNC_DELETE_CMDS. This peer delete response event is used to synchronize the peer deletion. Add peer delete response event and wait for the event after deleting every peer from host driver to synchronize with firmware. Tested HW: WCN3990 Tested FW: WLAN.HL.2.0-01188-QCAHLSWMTPLZ-1 Signed-off-by: Dundi Raviteja Signed-off-by: Rakesh Pillai Signed-off-by: Kalle Valo Change-Id: Iea5367f7664399c178b5749f7f9f46d7730ee787 Git-commit: c6f537a11b812c50decb8d5fa470e5e2a0ce354f Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git [bpothuno@codeaurora.org: fix trivial merge conflicts] Signed-off-by: Balaji Pothunoori --- drivers/net/wireless/ath/ath10k/core.c | 1 + drivers/net/wireless/ath/ath10k/core.h | 2 ++ drivers/net/wireless/ath/ath10k/mac.c | 41 +++++++++++++++++++++-- drivers/net/wireless/ath/ath10k/wmi-tlv.c | 21 ++++++++++++ drivers/net/wireless/ath/ath10k/wmi-tlv.h | 2 ++ drivers/net/wireless/ath/ath10k/wmi.h | 5 +++ 6 files changed, 70 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 7c9dc64f223c..54637f36013b 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -3008,6 +3008,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, init_completion(&ar->vdev_delete_done); init_completion(&ar->thermal.wmi_sync); init_completion(&ar->bss_survey_done); + init_completion(&ar->peer_delete_done); INIT_DELAYED_WORK(&ar->scan.timeout, ath10k_scan_timeout_work); diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 6919435ee591..4136a8e8d190 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -1043,6 +1043,8 @@ struct ath10k { const u8 *wmi_key_cipher; void *ce_priv; + struct completion peer_delete_done; + /* must be last */ u8 drv_priv[0] __aligned(sizeof(void *)); }; diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 4deeef1f7f8d..a920660a114a 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -685,6 +685,26 @@ ath10k_mac_get_any_chandef_iter(struct ieee80211_hw *hw, *def = &conf->def; } +static void ath10k_wait_for_peer_delete_done(struct ath10k *ar, u32 vdev_id, + const u8 *addr) +{ + unsigned long time_left; + int ret; + + if (test_bit(WMI_SERVICE_SYNC_DELETE_CMDS, ar->wmi.svc_map)) { + ret = ath10k_wait_for_peer_deleted(ar, vdev_id, addr); + if (ret) { + ath10k_warn(ar, "failed wait for peer deleted"); + return; + } + + time_left = wait_for_completion_timeout(&ar->peer_delete_done, + 5 * HZ); + if (!time_left) + ath10k_warn(ar, "Timeout in receiving peer delete response\n"); + } +} + static int ath10k_peer_create(struct ath10k *ar, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -729,7 +749,7 @@ static int ath10k_peer_create(struct ath10k *ar, spin_unlock_bh(&ar->data_lock); ath10k_warn(ar, "failed to find peer %pM on vdev %i after creation\n", addr, vdev_id); - ath10k_wmi_peer_delete(ar, vdev_id, addr); + ath10k_wait_for_peer_delete_done(ar, vdev_id, addr); return -ENOENT; } @@ -811,6 +831,18 @@ static int ath10k_peer_delete(struct ath10k *ar, u32 vdev_id, const u8 *addr) if (ret) return ret; + if (test_bit(WMI_SERVICE_SYNC_DELETE_CMDS, ar->wmi.svc_map)) { + unsigned long time_left; + + time_left = wait_for_completion_timeout + (&ar->peer_delete_done, 5 * HZ); + + if (!time_left) { + ath10k_warn(ar, "Timeout in receiving peer delete response\n"); + return -ETIMEDOUT; + } + } + ar->num_peers--; return 0; @@ -5248,8 +5280,11 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, err_peer_delete: if (arvif->vdev_type == WMI_VDEV_TYPE_AP || - arvif->vdev_type == WMI_VDEV_TYPE_IBSS) + arvif->vdev_type == WMI_VDEV_TYPE_IBSS) { ath10k_wmi_peer_delete(ar, arvif->vdev_id, vif->addr); + ath10k_wait_for_peer_delete_done(ar, arvif->vdev_id, + vif->addr); + } err_vdev_delete: ath10k_wmi_vdev_delete(ar, arvif->vdev_id); @@ -5315,6 +5350,8 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw, ath10k_warn(ar, "failed to submit AP/IBSS self-peer removal on vdev %i: %d\n", arvif->vdev_id, ret); + ath10k_wait_for_peer_delete_done(ar, arvif->vdev_id, + vif->addr); kfree(arvif->u.ap.noa_data); } diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index 5085533d4241..39cd88fa293f 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -420,6 +420,24 @@ static int ath10k_wmi_tlv_event_tx_pause(struct ath10k *ar, return 0; } +static int ath10k_wmi_tlv_event_peer_delete_resp(struct ath10k *ar, + struct sk_buff *skb) +{ + struct wmi_peer_delete_resp_ev_arg *arg; + struct wmi_tlv *tlv_hdr; + + tlv_hdr = (struct wmi_tlv *)skb->data; + arg = (struct wmi_peer_delete_resp_ev_arg *)tlv_hdr->value; + + ath10k_dbg(ar, ATH10K_DBG_WMI, "vdev id %d", arg->vdev_id); + ath10k_dbg(ar, ATH10K_DBG_WMI, "peer mac addr %pM", &arg->peer_addr); + ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv peer delete response\n"); + + complete(&ar->peer_delete_done); + + return 0; +} + /***********/ /* TLV ops */ /***********/ @@ -566,6 +584,9 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb) case WMI_TLV_TX_PAUSE_EVENTID: ath10k_wmi_tlv_event_tx_pause(ar, skb); break; + case WMI_TLV_PEER_DELETE_RESP_EVENTID: + ath10k_wmi_tlv_event_peer_delete_resp(ar, skb); + break; default: ath10k_warn(ar, "Unknown eventid: %d\n", id); break; diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.h b/drivers/net/wireless/ath/ath10k/wmi-tlv.h index ebc7c1cd16dc..f9249a50e52b 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.h +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.h @@ -317,6 +317,8 @@ enum wmi_tlv_event_id { WMI_TLV_PEER_TX_FAIL_CNT_THR_EVENTID, WMI_TLV_PEER_ESTIMATED_LINKSPEED_EVENTID, WMI_TLV_PEER_STATE_EVENTID, + WMI_TLV_PEER_ASSOC_CONF_EVENTID, + WMI_TLV_PEER_DELETE_RESP_EVENTID, WMI_TLV_MGMT_RX_EVENTID = WMI_TLV_EV(WMI_TLV_GRP_MGMT), WMI_TLV_HOST_SWBA_EVENTID, WMI_TLV_TBTTOFFSET_UPDATE_EVENTID, diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index ffe6c166c7b6..661f23ffe59f 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -6498,6 +6498,11 @@ struct wmi_scan_ev_arg { __le32 vdev_id; }; +struct wmi_peer_delete_resp_ev_arg { + __le32 vdev_id; + struct wmi_mac_addr peer_addr; +}; + struct wmi_mgmt_rx_ev_arg { __le32 channel; __le32 snr; From f882fc70bc4beba64a59495ddafb4cf99c337ec6 Mon Sep 17 00:00:00 2001 From: Surabhi Vishnoi Date: Fri, 15 Feb 2019 20:49:37 +0530 Subject: [PATCH 175/592] UPSTREAM: ath10k: Fix length of wmi tlv command for protected mgmt frames The length of wmi tlv command for management tx send is calculated incorrectly in case of protected management frames as there is addition of IEEE80211_CCMP_MIC_LEN twice. This leads to improper behaviour of firmware as the wmi tlv mgmt tx send command for protected mgmt frames is formed wrongly. Fix the length calculation of wmi tlv command for mgmt tx send in case of protected management frames by adding the IEEE80211_CCMP_MIC_LEN only once. Tested HW: WCN3990 Tested FW: WLAN.HL.3.1-00784-QCAHLSWMTPLZ-1 Fixes: 1807da49733e "ath10k: wmi: add management tx by reference support over wmi" Signed-off-by: Surabhi Vishnoi Signed-off-by: Kalle Valo Change-Id: Iea5367f7664399c178b5749f7f9f46d7730ee788 Git-commit: 761156ff573d1002983416e4fd1fe8d3489c4bd8 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git Signed-off-by: Balaji Pothunoori --- drivers/net/wireless/ath/ath10k/wmi-tlv.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index 39cd88fa293f..fe991e99f9eb 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -2666,10 +2666,8 @@ ath10k_wmi_tlv_op_gen_mgmt_tx(struct ath10k *ar, struct sk_buff *msdu) if ((ieee80211_is_action(hdr->frame_control) || ieee80211_is_deauth(hdr->frame_control) || ieee80211_is_disassoc(hdr->frame_control)) && - ieee80211_has_protected(hdr->frame_control)) { - len += IEEE80211_CCMP_MIC_LEN; + ieee80211_has_protected(hdr->frame_control)) buf_len += IEEE80211_CCMP_MIC_LEN; - } buf_len = min_t(u32, buf_len, WMI_TLV_MGMT_TX_FRAME_MAX_LEN); buf_len = round_up(buf_len, 4); From 56ae9bd240a01e3fc540c1724d19c8bb6473b482 Mon Sep 17 00:00:00 2001 From: Rakesh Pillai Date: Tue, 2 Apr 2019 18:12:50 +0530 Subject: [PATCH 176/592] UPSTREAM: ath10k: Fix encoding for protected management frames Currently the protected management frames are not appended with the MIC_LEN which results in the protected management frames being encoded incorrectly. Add the extra space at the end of the protected management frames to fix this encoding error for the protected management frames. Tested HW: WCN3990 Tested FW: WLAN.HL.3.1-00784-QCAHLSWMTPLZ-1 Fixes: 1807da49733e ("ath10k: wmi: add management tx by reference support over wmi") Signed-off-by: Rakesh Pillai Signed-off-by: Kalle Valo Change-Id: Iea5367f7664399c178b5749f7f9f46d7730ee789 Git-commit: 42f1bc43e6a97b9ddbe976eba9bd05306c990c75 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git Signed-off-by: Balaji Pothunoori --- drivers/net/wireless/ath/ath10k/wmi-tlv.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index fe991e99f9eb..c4dfc61fc164 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -2666,8 +2666,10 @@ ath10k_wmi_tlv_op_gen_mgmt_tx(struct ath10k *ar, struct sk_buff *msdu) if ((ieee80211_is_action(hdr->frame_control) || ieee80211_is_deauth(hdr->frame_control) || ieee80211_is_disassoc(hdr->frame_control)) && - ieee80211_has_protected(hdr->frame_control)) + ieee80211_has_protected(hdr->frame_control)) { + skb_put(msdu, IEEE80211_CCMP_MIC_LEN); buf_len += IEEE80211_CCMP_MIC_LEN; + } buf_len = min_t(u32, buf_len, WMI_TLV_MGMT_TX_FRAME_MAX_LEN); buf_len = round_up(buf_len, 4); From 0d3931ee885bdbebe15c472774410fa38c3e05fe Mon Sep 17 00:00:00 2001 From: Abhishek Singh Date: Wed, 20 Mar 2019 16:29:33 +0530 Subject: [PATCH 177/592] qcacld-3.0: Fix Mlme info updating in connected BSS in scan Mlme info is not updated for the new AP to which driver roamed and also not updated for the old AP after driver roamed to new AP. Also in some case when deauth is from peer the Mlme info is not reset by driver for the disconnected AP. As mlme info of the AP is not updated and it remain in associated state The AGE out logic skip the AP and thus it never ageout. Fix this by properly updating the MLME info of the AP during roaming And disconnection. Change-Id: Ib17499c8ab0c4725d146d7c09077c92661adbdd5 CRs-Fixed: 2419853 --- core/sme/src/csr/csr_api_roam.c | 79 ++++++++++++++++++++++----------- 1 file changed, 52 insertions(+), 27 deletions(-) diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 73c2c6f862d0..ac17c55867d7 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -7573,16 +7573,37 @@ bool csr_roam_is_fast_roam_enabled(tpAniSirGlobal pMac, uint32_t sessionId) } } -static void csr_update_scan_entry_associnfo(tpAniSirGlobal mac_ctx, - struct bss_info *bss, enum scan_entry_connection_state state) +static +void csr_update_scan_entry_associnfo(tpAniSirGlobal mac_ctx, + struct csr_roam_session *session, + enum scan_entry_connection_state state) { QDF_STATUS status; struct mlme_info mlme; + struct bss_info bss; + tCsrRoamConnectedProfile *conn_profile; - sme_debug("Update MLME info in scan database. bssid %pM state: %d", - bss->bssid.bytes, state); + if (!session) { + sme_debug("session is NULL"); + return; + } + conn_profile = &session->connectedProfile; + if (!CSR_IS_INFRASTRUCTURE(conn_profile)) { + sme_debug("not infra return"); + return; + } + + qdf_copy_macaddr(&bss.bssid, &conn_profile->bssid); + bss.chan = conn_profile->operationChannel; + bss.ssid.length = conn_profile->SSID.length; + qdf_mem_copy(&bss.ssid.ssid, &conn_profile->SSID.ssId, + bss.ssid.length); + + sme_debug("Update MLME info in scan database. bssid %pM ssid:%.*s chan %d state: %d", + bss.bssid.bytes, bss.ssid.length, bss.ssid.ssid, bss.chan, + state); mlme.assoc_state = state; - status = ucfg_scan_update_mlme_by_bssinfo(mac_ctx->pdev, bss, &mlme); + status = ucfg_scan_update_mlme_by_bssinfo(mac_ctx->pdev, &bss, &mlme); if (QDF_IS_STATUS_ERROR(status)) sme_debug("Failed to update the MLME info in scan entry"); } @@ -7736,7 +7757,6 @@ static void csr_roam_process_results_default(tpAniSirGlobal mac_ctx, struct csr_roam_session *session; struct csr_roam_info *roam_info; QDF_STATUS status; - struct bss_info bss_info; struct csr_roam_connectedinfo *prev_connect_info = NULL; if (!CSR_IS_SESSION_VALID(mac_ctx, session_id)) { @@ -7752,14 +7772,17 @@ static void csr_roam_process_results_default(tpAniSirGlobal mac_ctx, sme_debug("Assoc ref count: %d", session->bRefAssocStartCnt); - if (CSR_IS_INFRASTRUCTURE(&session->connectedProfile)) { - qdf_copy_macaddr(&bss_info.bssid, - &session->connectedProfile.bssid); - bss_info.chan = session->connectedProfile.operationChannel; - bss_info.ssid.length = session->connectedProfile.SSID.length; - qdf_mem_copy(&bss_info.ssid.ssid, - &session->connectedProfile.SSID.ssId, - bss_info.ssid.length); + /* Update AP's assoc info in scan before removing connectedProfile */ + switch (cmd->u.roamCmd.roamReason) { + case eCsrSmeIssuedDisassocForHandoff: + case eCsrForcedDisassoc: + case eCsrForcedDeauth: + case eCsrForcedDisassocMICFailure: + csr_update_scan_entry_associnfo(mac_ctx, session, + SCAN_ENTRY_CON_STATE_NONE); + break; + default: + break; } if (CSR_IS_INFRASTRUCTURE(&session->connectedProfile) || CSR_IS_ROAM_SUBSTATE_STOP_BSS_REQ(mac_ctx, session_id)) { @@ -7878,8 +7901,6 @@ static void csr_roam_process_results_default(tpAniSirGlobal mac_ctx, SME_QOS_CSR_DISCONNECT_IND, NULL); #endif - csr_update_scan_entry_associnfo(mac_ctx, &bss_info, - SCAN_ENTRY_CON_STATE_NONE); csr_roam_link_down(mac_ctx, session_id); if (mac_ctx->roam.deauthRspStatus == eSIR_SME_DEAUTH_STATUS) { @@ -8349,7 +8370,6 @@ static void csr_roam_process_join_res(tpAniSirGlobal mac_ctx, struct ps_global_info *ps_global_info = &mac_ctx->sme.ps_global_info; tSirSmeJoinRsp *join_rsp = (tSirSmeJoinRsp *) context; uint32_t len; - struct bss_info bss_info; if (!join_rsp) { sme_err("join_rsp is NULL"); @@ -8701,15 +8721,8 @@ static void csr_roam_process_join_res(tpAniSirGlobal mac_ctx, eCSR_ROAM_RESULT_ASSOCIATED); } - qdf_copy_macaddr(&bss_info.bssid, &conn_profile->bssid); - bss_info.chan = conn_profile->operationChannel; - bss_info.ssid.length = - conn_profile->SSID.length; - qdf_mem_copy(&bss_info.ssid.ssid, - &conn_profile->SSID.ssId, - bss_info.ssid.length); - csr_update_scan_entry_associnfo(mac_ctx, - &bss_info, SCAN_ENTRY_CON_STATE_ASSOC); + csr_update_scan_entry_associnfo(mac_ctx, session, + SCAN_ENTRY_CON_STATE_ASSOC); csr_roam_completion(mac_ctx, session_id, NULL, cmd, eCSR_ROAM_RESULT_NONE, true); csr_reset_pmkid_candidate_list(mac_ctx, session_id); @@ -12936,7 +12949,10 @@ csr_roam_chk_lnk_disassoc_ind(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr) return; } - /* Update the disconnect stats */ + csr_update_scan_entry_associnfo(mac_ctx, + session, SCAN_ENTRY_CON_STATE_NONE); + + /* Update the disconnect stats */ session->disconnect_stats.disconnection_cnt++; session->disconnect_stats.disassoc_by_peer++; @@ -13011,6 +13027,8 @@ csr_roam_chk_lnk_deauth_ind(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr) return; } + csr_update_scan_entry_associnfo(mac_ctx, + session, SCAN_ENTRY_CON_STATE_NONE); /* Update the disconnect stats */ switch (pDeauthInd->reasonCode) { case eSIR_MAC_DISASSOC_DUE_TO_INACTIVITY_REASON: @@ -24200,6 +24218,10 @@ static QDF_STATUS csr_process_roam_sync_callback(tpAniSirGlobal mac_ctx, bss_desc, ies_local); ps_global_info->remain_in_power_active_till_dhcp = false; session->connectState = eCSR_ASSOC_STATE_TYPE_INFRA_ASSOCIATED; + + /* Remove old BSSID mlme info from scan cache */ + csr_update_scan_entry_associnfo(mac_ctx, session, + SCAN_ENTRY_CON_STATE_NONE); roam_info = qdf_mem_malloc(sizeof(struct csr_roam_info)); if (NULL == roam_info) { QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, @@ -24220,6 +24242,9 @@ static QDF_STATUS csr_process_roam_sync_callback(tpAniSirGlobal mac_ctx, session->pCurRoamProfile, bss_desc, ies_local); + /* Add new mlme info to new BSSID after upting connectedProfile */ + csr_update_scan_entry_associnfo(mac_ctx, session, + SCAN_ENTRY_CON_STATE_ASSOC); csr_roam_save_security_rsp_ie(mac_ctx, session_id, session->pCurRoamProfile->negotiatedAuthType, bss_desc, ies_local); From c9e3704cb048087e9a2638d6e9f004c345586400 Mon Sep 17 00:00:00 2001 From: nshrivas Date: Tue, 14 Jul 2020 01:48:43 -0700 Subject: [PATCH 178/592] Release 5.2.03.29G Release 5.2.03.29G Change-Id: I4f737d3aa87e50e2e10e650fc50b1cef8158973d CRs-Fixed: 774533 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index 064fb4cf5a6e..43f4de922466 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -32,9 +32,9 @@ #define QWLAN_VERSION_MAJOR 5 #define QWLAN_VERSION_MINOR 2 #define QWLAN_VERSION_PATCH 03 -#define QWLAN_VERSION_EXTRA "F" +#define QWLAN_VERSION_EXTRA "G" #define QWLAN_VERSION_BUILD 29 -#define QWLAN_VERSIONSTR "5.2.03.29F" +#define QWLAN_VERSIONSTR "5.2.03.29G" #endif /* QWLAN_VERSION_H */ From 2154791df833d2cae85d70cc17749092ebeb3a29 Mon Sep 17 00:00:00 2001 From: Bapiraju Alla Date: Wed, 15 Jul 2020 00:14:24 +0530 Subject: [PATCH 179/592] qcacld-3.0: Limit the number of times get_tx_power can come Currently in the driver, there is no limit on how many number of times get_tx_power can be requested by the userspace. This can lead to potential issues where the firmware crashes due to excessive stats request. Add a time based rate limiting logic wherein the function call only sends request to the firmware once in three seconds. In other cases, it returns the cached value present in the adapter. Change-Id: I65f23135d88c66e6438484715dafce3def14ddb3 CRs-Fixed: 2717633 --- core/hdd/inc/wlan_hdd_cfg.h | 23 +++++++++++++++++++++++ core/hdd/inc/wlan_hdd_main.h | 23 +++++++++++++++++++++++ core/hdd/src/wlan_hdd_cfg.c | 8 ++++++++ core/hdd/src/wlan_hdd_power.c | 9 +++++++-- 4 files changed, 61 insertions(+), 2 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index 602e385ecd60..ab04758cfe25 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -17624,6 +17624,28 @@ enum hdd_external_acs_policy { #define CFG_DISABLE_4WAY_HS_OFFLOAD_MAX (1) #define CFG_DISABLE_4WAY_HS_OFFLOAD_DEFAULT (0) +/* + * + * nb_commands_interval - Used to rate limit nb commands from userspace + * + * @Min: 0 + * @Max: 10 + * Default: 3 + * + * This ini is used to specify the duration in which any supp. nb command from + * userspace will not be processed completely in driver. For ex, the default + * value of 3 seconds signifies that consecutive commands within that + * time will not be processed fully. + * + * Usage: Internal + * + * + */ +#define CFG_NB_COMMANDS_RATE_LIMIT "nb_commands_interval" +#define CFG_NB_COMMANDS_RATE_LIMIT_MIN (0) +#define CFG_NB_COMMANDS_RATE_LIMIT_MAX (10) +#define CFG_NB_COMMANDS_RATE_LIMIT_DEFAULT (3) + /* * * enable_time_sync_ftm - Time Sync FTM feature support @@ -18835,6 +18857,7 @@ struct hdd_config { bool ShortGI160MhzEnable; uint32_t vendor_roam_score_algorithm; uint32_t dp_proto_event_bitmap; + uint8_t nb_commands_interval; #ifdef SAR_SAFETY_FEATURE uint32_t sar_safety_timeout; diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index ea84f343c9af..0555cd95f93b 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -138,6 +138,29 @@ struct hdd_apf_context { #define NUM_TX_QUEUES 4 #endif +/* HDD_IS_RATE_LIMIT_REQ: Macro helper to implement rate limiting + * @flag: The flag to determine if limiting is required or not + * @rate: The number of seconds within which if multiple commands come, the + * flag will be set to true + * + * If the function in which this macro is used is called multiple times within + * "rate" number of seconds, the "flag" will be set to true which can be used + * to reject/take appropriate action. + */ +#define HDD_IS_RATE_LIMIT_REQ(flag, rate)\ + do {\ + static ulong __last_ticks;\ + ulong __ticks = jiffies;\ + flag = false; \ + if (!time_after(__ticks,\ + __last_ticks + rate * HZ)) {\ + flag = true; \ + } \ + else { \ + __last_ticks = __ticks;\ + } \ + } while (0) + /* * API in_compat_syscall() is introduced in 4.6 kernel to check whether we're * in a compat syscall or not. It is a new way to query the syscall type, which diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c index 01ae60d8f241..243d0af233b8 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/core/hdd/src/wlan_hdd_cfg.c @@ -6366,6 +6366,14 @@ struct reg_table_entry g_registry_table[] = { CFG_DISABLE_4WAY_HS_OFFLOAD_DEFAULT, CFG_DISABLE_4WAY_HS_OFFLOAD_MIN, CFG_DISABLE_4WAY_HS_OFFLOAD_MAX), + + REG_VARIABLE(CFG_NB_COMMANDS_RATE_LIMIT, WLAN_PARAM_Integer, + struct hdd_config, nb_commands_interval, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_NB_COMMANDS_RATE_LIMIT_DEFAULT, + CFG_NB_COMMANDS_RATE_LIMIT_MIN, + CFG_NB_COMMANDS_RATE_LIMIT_MAX), + #ifdef FEATURE_WLAN_TIME_SYNC_FTM REG_VARIABLE(CFG_ENABLE_TIME_SYNC_FTM, WLAN_PARAM_Integer, struct hdd_config, time_sync_ftm_enable, diff --git a/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c index b37f833cd698..da7ac413f1f5 100644 --- a/core/hdd/src/wlan_hdd_power.c +++ b/core/hdd/src/wlan_hdd_power.c @@ -2332,6 +2332,7 @@ static int __wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev); int status; struct hdd_station_ctx *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); + static bool is_rate_limited; hdd_enter_dev(ndev); @@ -2356,10 +2357,14 @@ static int __wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, return -EINVAL; } + HDD_IS_RATE_LIMIT_REQ(is_rate_limited, + hdd_ctx->config->nb_commands_interval); + mutex_lock(&hdd_ctx->iface_change_lock); - if (hdd_ctx->driver_status != DRIVER_MODULES_ENABLED) { + if (hdd_ctx->driver_status != DRIVER_MODULES_ENABLED || + is_rate_limited) { mutex_unlock(&hdd_ctx->iface_change_lock); - hdd_debug("Driver Module not enabled return success"); + hdd_debug("Modules not enabled/rate limited, use cached stats"); /* Send cached data to upperlayer*/ *dbm = adapter->hdd_stats.class_a_stat.max_pwr; return 0; From 8e4b3413e697c85783350a178de0116b00e78f73 Mon Sep 17 00:00:00 2001 From: snandini Date: Tue, 14 Jul 2020 23:48:46 -0700 Subject: [PATCH 180/592] Release 5.2.03.29H Release 5.2.03.29H Change-Id: Ie147d42b62170fff226152b09512e3ba4a347389 CRs-Fixed: 774533 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index 43f4de922466..926ddaa93f28 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -32,9 +32,9 @@ #define QWLAN_VERSION_MAJOR 5 #define QWLAN_VERSION_MINOR 2 #define QWLAN_VERSION_PATCH 03 -#define QWLAN_VERSION_EXTRA "G" +#define QWLAN_VERSION_EXTRA "H" #define QWLAN_VERSION_BUILD 29 -#define QWLAN_VERSIONSTR "5.2.03.29G" +#define QWLAN_VERSIONSTR "5.2.03.29H" #endif /* QWLAN_VERSION_H */ From 85e28b13bfd44ef72e6843e220680963d3ca86ac Mon Sep 17 00:00:00 2001 From: Prasadarao Durvasula Date: Wed, 15 Jul 2020 21:07:35 +0530 Subject: [PATCH 181/592] usb: gadget: handle bam setup and cleanup for mbim in u_bam_dmux When usb composition contains RMNET and MBIM functions, then handle bam setup for mbim. As RMNET and MBIM use same bam channel 8, In multi-function usb compositions, RMNET binding happens before MBIM binding. bam setup happens in binding operation. So if binding operation happens for RMNET, then binding operation for MBIM is not required. Depends on host selection of RMNET/MBIM function, same bam setup will be used by one of functions RMNET/MBIM. In non multi-function usb compositions where only RMNET or MBIM present, RMNET or MBIM works as usual. Change-Id: I5200d1a26726ee27e87a51404456232b09751b50 Signed-off-by: Prasadarao Durvasula Signed-off-by: Sivasri Kumar Vanka --- drivers/usb/gadget/function/u_bam_dmux.c | 14 +++++++++----- drivers/usb/gadget/function/u_rmnet.h | 2 +- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/usb/gadget/function/u_bam_dmux.c b/drivers/usb/gadget/function/u_bam_dmux.c index f40b8e7ecb7f..57aaebfcfd64 100644 --- a/drivers/usb/gadget/function/u_bam_dmux.c +++ b/drivers/usb/gadget/function/u_bam_dmux.c @@ -35,7 +35,6 @@ static struct workqueue_struct *gbam_wq; static unsigned int n_tx_req_queued; static unsigned int bam_ch_ids[BAM_DMUX_NUM_FUNCS] = { - BAM_DMUX_USB_RMNET_0, BAM_DMUX_USB_RMNET_0, BAM_DMUX_USB_DPL }; @@ -1026,11 +1025,12 @@ static void gbam_port_free(enum bam_dmux_func_type func) struct gbam_port *port = bam_ports[func].port; struct platform_driver *pdrv = &bam_ports[func].pdrv; - if (port) + if (port) { platform_driver_unregister(pdrv); - kfree(port); - bam_ports[func].port = NULL; + kfree(port); + bam_ports[func].port = NULL; + } } static int gbam_port_alloc(enum bam_dmux_func_type func) @@ -1217,6 +1217,9 @@ static void gbam_debugfs_init(void) } static void gbam_debugfs_remove(void) { + if (!gbam_dent) + return; + debugfs_remove_recursive(gbam_dent); debugfs_remove(gbam_dent); gbam_dent = NULL; @@ -1451,7 +1454,8 @@ int gbam_mbim_setup(void) { int ret = 0; - ret = gbam_setup(BAM_DMUX_FUNC_MBIM); + if (!bam_ports[BAM_DMUX_FUNC_RMNET].port) + ret = gbam_setup(BAM_DMUX_FUNC_MBIM); return ret; } diff --git a/drivers/usb/gadget/function/u_rmnet.h b/drivers/usb/gadget/function/u_rmnet.h index dbc3002bb99e..2e963f813a7f 100644 --- a/drivers/usb/gadget/function/u_rmnet.h +++ b/drivers/usb/gadget/function/u_rmnet.h @@ -22,7 +22,7 @@ enum bam_dmux_func_type { BAM_DMUX_FUNC_RMNET, - BAM_DMUX_FUNC_MBIM, + BAM_DMUX_FUNC_MBIM = 0, BAM_DMUX_FUNC_DPL, BAM_DMUX_NUM_FUNCS, }; From e80c855c8e62d43b50a0e0a3bc6ad57cc38a93f7 Mon Sep 17 00:00:00 2001 From: Srinivas Dasari Date: Wed, 15 Jul 2020 20:46:50 +0530 Subject: [PATCH 182/592] qcacld-3.0: Send vdev param NAN_CONFIG_FEATURES after creating vdev Currently, the ini value is cached in nan component and it's sent to firmware from target_if as part of vdev obj create handler. But vdev create might be incomplete in firmware by the time vdev obj mgr create handler gets called. So send the vdev param NAN_CONFIG_FEATURES after creating vdev through sme_cli_set_command. So revert the changes to cache the ini in NAN component and sending vdev param through target_if. Change-Id: I3a5b0d99f12cfecd3faaedc31814f466f83c56cf CRs-Fixed: 2732662 --- core/hdd/inc/wlan_hdd_main.h | 1 - core/hdd/src/wlan_hdd_main.c | 44 ++++++++++++++++++------------------ 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 0555cd95f93b..1648509df32d 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -2122,7 +2122,6 @@ struct hdd_context { struct wlan_mlme_chain_cfg fw_chain_cfg; struct sar_limit_cmd_params *sar_cmd_params; bool nan_seperate_vdev_supported; - uint32_t nan_feature_config; #ifdef SAR_SAFETY_FEATURE qdf_mc_timer_t sar_safety_timer; diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 962435a69c84..87ba68553d0c 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -4772,11 +4772,32 @@ static void hdd_configure_nan_support_mp0_discovery(struct hdd_adapter *adapter) VDEV_CMD); } } + +static void hdd_set_nan_feature_config(struct hdd_adapter *adapter) +{ + struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + + if (!wlan_hdd_nan_is_supported(hdd_ctx)) + return; + + if (QDF_NAN_DISC_MODE == adapter->device_mode || + (QDF_STA_MODE == adapter->device_mode && + (!hdd_ctx->nan_seperate_vdev_supported || + !wlan_hdd_nan_separate_iface_supported(hdd_ctx)))) + sme_cli_set_command(adapter->session_id, + WMI_VDEV_PARAM_ENABLE_DISABLE_NAN_CONFIG_FEATURES, + hdd_ctx->config->nan_feature_config, + VDEV_CMD); +} #else static inline void hdd_configure_nan_support_mp0_discovery( struct hdd_adapter *adapter) { } + +static inline void hdd_set_nan_feature_config(struct hdd_adapter *adapter) +{ +} #endif int hdd_vdev_create(struct hdd_adapter *adapter, @@ -4881,6 +4902,7 @@ int hdd_vdev_create(struct hdd_adapter *adapter, hdd_nofl_debug("vdev %d created successfully", adapter->session_id); hdd_configure_nan_support_mp0_discovery(adapter); + hdd_set_nan_feature_config(adapter); return 0; @@ -15282,24 +15304,6 @@ static int hdd_update_pkt_capture_config(struct hdd_context *hdd_ctx) return qdf_status_to_os_return(status); } -/** - * hdd_update_nan_config - Update nan config - * @hdd_ctx: HDD context - * - * Return: 0 on success / error on failure - */ -static int hdd_update_nan_config(struct hdd_context *hdd_ctx) -{ - QDF_STATUS status; - uint32_t nan_feature_config = hdd_ctx->config->nan_feature_config; - - status = ucfg_set_nan_feature_config(hdd_ctx->psoc, nan_feature_config); - if (QDF_IS_STATUS_ERROR(status)) - hdd_err("nan config failed"); - - return qdf_status_to_os_return(status); -} - #ifdef FEATURE_WLAN_TIME_SYNC_FTM /** * hdd_update_time_sync_ftm_config - Update time sync ftm config parameters @@ -15668,10 +15672,6 @@ int hdd_update_components_config(struct hdd_context *hdd_ctx) if (ret) return ret; - ret = hdd_update_nan_config(hdd_ctx); - if (ret) - return ret; - ret = hdd_update_time_sync_ftm_config(hdd_ctx); return ret; From 7eaa600a6fb17044aa39ddb52b6d777ff0154d93 Mon Sep 17 00:00:00 2001 From: Srinivas Dasari Date: Wed, 15 Jul 2020 20:28:15 +0530 Subject: [PATCH 183/592] qcacmn: Send vdev param NAN_CONFIG_FEATURES after creating vdev Currently, the ini value is cached in nan component and it's sent to firmware as vdev param from target_if as part of vdev obj create handler. But vdev create might be incomplete in firmware by the time vdev obj mgr create handler gets called. So send the vdev param NAN_CONFIG_FEATURES after creating vdev through sme_cli_set_command. So revert the changes to cache the ini in NAN component and sending vdev param through target_if. Change-Id: I165c0fb7bf3f5b02650a90e41a39e4d4c4033be7 CRs-Fixed: 2733054 --- target_if/nan/inc/target_if_nan.h | 11 ------- target_if/nan/src/target_if_nan.c | 42 -------------------------- umac/nan/core/src/nan_api.c | 10 ------ umac/nan/core/src/nan_main_i.h | 4 --- umac/nan/dispatcher/inc/nan_ucfg_api.h | 20 ------------ umac/nan/dispatcher/src/nan_ucfg_api.c | 30 ------------------ 6 files changed, 117 deletions(-) diff --git a/target_if/nan/inc/target_if_nan.h b/target_if/nan/inc/target_if_nan.h index 7333b3cc731e..1ddc2676b158 100644 --- a/target_if/nan/inc/target_if_nan.h +++ b/target_if/nan/inc/target_if_nan.h @@ -94,15 +94,4 @@ QDF_STATUS target_if_nan_register_events(struct wlan_objmgr_psoc *psoc); */ QDF_STATUS target_if_nan_deregister_events(struct wlan_objmgr_psoc *psoc); -/** - * target_if_nan_set_vdev_feature_config() - Init NAN feature config params - * @psoc: Pointer to PSOC Object - * @vdev_id: vdev_id of the current vdev - * @mode: Opmode of the vdev - * - * This function updates NAN feature config bitmap to firmware - */ -void target_if_nan_set_vdev_feature_config(struct wlan_objmgr_psoc *psoc, - uint8_t vdev_id, - enum QDF_OPMODE mode); #endif /* _WIFI_POS_TGT_IF_H_ */ diff --git a/target_if/nan/src/target_if_nan.c b/target_if/nan/src/target_if_nan.c index 827aad997a84..9522169827d0 100644 --- a/target_if/nan/src/target_if_nan.c +++ b/target_if/nan/src/target_if_nan.c @@ -26,7 +26,6 @@ #include "target_if_nan.h" #include "wmi_unified_api.h" #include "scheduler_api.h" -#include static QDF_STATUS target_if_nan_event_flush_cb(struct scheduler_msg *msg) { @@ -886,44 +885,3 @@ QDF_STATUS target_if_nan_deregister_events(struct wlan_objmgr_psoc *psoc) else return QDF_STATUS_SUCCESS; } - -void target_if_nan_set_vdev_feature_config(struct wlan_objmgr_psoc *psoc, - uint8_t vdev_id, - enum QDF_OPMODE mode) -{ - QDF_STATUS status; - uint32_t nan_features = 0; - struct vdev_set_params param; - wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); - struct target_psoc_info *tgt_hdl; - target_resource_config *wlan_res_cfg; - - if (!wmi_handle) { - target_if_err("Invalid wmi handle"); - return; - } - - tgt_hdl = wlan_psoc_get_tgt_if_handle(psoc); - if (!tgt_hdl) { - target_if_err("target psoc info is NULL"); - return; - } - wlan_res_cfg = target_psoc_get_wlan_res_cfg(tgt_hdl); - - if (!(mode == QDF_NAN_DISC_MODE || - (!wlan_res_cfg->nan_separate_iface_support && - mode == QDF_STA_MODE))) - return; - - ucfg_get_nan_feature_config(psoc, &nan_features); - target_if_debug("vdev_id:%d NAN features:0x%x", vdev_id, nan_features); - - param.if_id = vdev_id; - param.param_id = WMI_VDEV_PARAM_ENABLE_DISABLE_NAN_CONFIG_FEATURES; - param.param_value = nan_features; - - status = wmi_unified_vdev_set_param_send(wmi_handle, ¶m); - if (QDF_IS_STATUS_ERROR(status)) - target_if_err("failed to set NAN_CONFIG_FEATURES(status = %d)", - status); -} diff --git a/umac/nan/core/src/nan_api.c b/umac/nan/core/src/nan_api.c index d66cc53d7b3b..592dadbb2f96 100644 --- a/umac/nan/core/src/nan_api.c +++ b/umac/nan/core/src/nan_api.c @@ -125,18 +125,8 @@ static QDF_STATUS nan_vdev_obj_created_notification( { struct nan_vdev_priv_obj *nan_obj; QDF_STATUS status = QDF_STATUS_SUCCESS; - struct wlan_objmgr_psoc *psoc; nan_debug("nan_vdev_create_notif called"); - - psoc = wlan_vdev_get_psoc(vdev); - if (!psoc) { - nan_err("psoc is NULL"); - return QDF_STATUS_E_INVAL; - } - target_if_nan_set_vdev_feature_config(psoc, - wlan_vdev_get_id(vdev), - wlan_vdev_mlme_get_opmode(vdev)); if (wlan_vdev_mlme_get_opmode(vdev) != QDF_NDI_MODE) { nan_debug("not a ndi vdev. do nothing"); return QDF_STATUS_SUCCESS; diff --git a/umac/nan/core/src/nan_main_i.h b/umac/nan/core/src/nan_main_i.h index 0c9494fcc7bc..e1d4323968f7 100644 --- a/umac/nan/core/src/nan_main_i.h +++ b/umac/nan/core/src/nan_main_i.h @@ -61,16 +61,12 @@ struct scheduler_msg; * @cb_obj: struct contaning callback pointers * @request_context: NAN context to carry cookie for wait_for_complete * @ndp_active_sessions: active ndp sessions - * @nan_feature_config: Bitmap to enable/disable a particular NAN feature - * configuration in firmware. It's sent to firmware through - * WMI_VDEV_PARAM_ENABLE_DISABLE_NAN_CONFIG_FEATURES */ struct nan_psoc_priv_obj { qdf_spinlock_t lock; struct nan_callbacks cb_obj; void *request_context; uint8_t ndp_active_sessions; - uint32_t nan_feature_config; }; /** diff --git a/umac/nan/dispatcher/inc/nan_ucfg_api.h b/umac/nan/dispatcher/inc/nan_ucfg_api.h index 520766dd3245..13f9af872c74 100644 --- a/umac/nan/dispatcher/inc/nan_ucfg_api.h +++ b/umac/nan/dispatcher/inc/nan_ucfg_api.h @@ -278,24 +278,4 @@ int ucfg_nan_register_lim_callbacks(struct wlan_objmgr_psoc *psoc, QDF_STATUS ucfg_nan_get_callbacks(struct wlan_objmgr_psoc *psoc, struct nan_callbacks *cb_obj); -/** - * ucfg_set_nan_feature_config() - Set NAN feature bitmap - * @psoc: pointer to psoc object - * @nan_feature_config: NAN feature config bitmap configured by user - * - * Return: QDF_STATUS - */ -QDF_STATUS ucfg_set_nan_feature_config(struct wlan_objmgr_psoc *psoc, - uint32_t nan_feature_config); - -/** - * ucfg_get_nan_feature_config() - Get NAN feature bitmap - * @psoc: pointer to psoc object - * @nan_feature_config: NAN feature config bitmap to be enabled in firmware - * - * Return: QDF_STATUS - */ -QDF_STATUS ucfg_get_nan_feature_config(struct wlan_objmgr_psoc *psoc, - uint32_t *nan_feature_config); - #endif /* _NAN_UCFG_API_H_ */ diff --git a/umac/nan/dispatcher/src/nan_ucfg_api.c b/umac/nan/dispatcher/src/nan_ucfg_api.c index 5119c8d85b7a..3f0d37d3a36e 100644 --- a/umac/nan/dispatcher/src/nan_ucfg_api.c +++ b/umac/nan/dispatcher/src/nan_ucfg_api.c @@ -485,33 +485,3 @@ int ucfg_nan_register_lim_callbacks(struct wlan_objmgr_psoc *psoc, return 0; } - -QDF_STATUS ucfg_set_nan_feature_config(struct wlan_objmgr_psoc *psoc, - uint32_t nan_feature_config) -{ - struct nan_psoc_priv_obj *psoc_nan_obj; - - psoc_nan_obj = nan_get_psoc_priv_obj(psoc); - if (!psoc_nan_obj) { - nan_err("psoc_nan_obj is null"); - return QDF_STATUS_E_INVAL; - } - - psoc_nan_obj->nan_feature_config = nan_feature_config; - return QDF_STATUS_SUCCESS; -} - -QDF_STATUS ucfg_get_nan_feature_config(struct wlan_objmgr_psoc *psoc, - uint32_t *nan_feature_config) -{ - struct nan_psoc_priv_obj *psoc_nan_obj; - - psoc_nan_obj = nan_get_psoc_priv_obj(psoc); - if (!psoc_nan_obj) { - nan_err("psoc_nan_obj is null"); - return QDF_STATUS_E_INVAL; - } - - *nan_feature_config = psoc_nan_obj->nan_feature_config; - return QDF_STATUS_SUCCESS; -} From 8c692fde6b87d8f1086a22ba5dc16f3daa1a8e4b Mon Sep 17 00:00:00 2001 From: spuligil Date: Wed, 15 Jul 2020 12:00:59 -0700 Subject: [PATCH 184/592] fw-api: CL 10966184 - update fw common interface files Change-Id: I911250768ae9484e89bcbf789012dfd12bdc09d8 WMI: add WLAN_DISCONNECT_REASON_MOVE_TO_CELLULAR def CRs-Fixed: 2262693 --- fw/wmi_unified.h | 4 ++++ fw/wmi_version.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/fw/wmi_unified.h b/fw/wmi_unified.h index 703c1e4f73b5..f76431cf48cb 100644 --- a/fw/wmi_unified.h +++ b/fw/wmi_unified.h @@ -16128,6 +16128,10 @@ typedef enum { * due to CSA in OCV enabled case. */ WLAN_DISCONNECT_REASON_CSA_SA_QUERY_TIMEOUT = 1, + /* MOVE_TO_CELLULAR: + * Disconnect from WiFi to move to cellular + */ + WLAN_DISCONNECT_REASON_MOVE_TO_CELLULAR, } WMI_VDEV_DISCONNECT_REASON_ID; typedef struct { diff --git a/fw/wmi_version.h b/fw/wmi_version.h index bb8e0016414b..77e46a82e4a0 100644 --- a/fw/wmi_version.h +++ b/fw/wmi_version.h @@ -36,7 +36,7 @@ #define __WMI_VER_MINOR_ 0 /** WMI revision number has to be incremented when there is a * change that may or may not break compatibility. */ -#define __WMI_REVISION_ 860 +#define __WMI_REVISION_ 861 /** The Version Namespace should not be normally changed. Only * host and firmware of the same WMI namespace will work From 4ff9344778bf0b725ae5e2e5e3467113d16fd24a Mon Sep 17 00:00:00 2001 From: spuligil Date: Wed, 15 Jul 2020 12:01:16 -0700 Subject: [PATCH 185/592] fw-api: CL 10972934 - update fw common interface files Change-Id: Ia6eafe7e87d13ac05baf77ebb9237a2e1bbb8754 WMI: TWT: add PROTECTION, FRAME_DISABLED flags, SP TSF field CRs-Fixed: 2262693 --- fw/wmi_unified.h | 9 +++++++++ fw/wmi_version.h | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/fw/wmi_unified.h b/fw/wmi_unified.h index f76431cf48cb..0c6bdcca8a44 100644 --- a/fw/wmi_unified.h +++ b/fw/wmi_unified.h @@ -31310,6 +31310,12 @@ typedef struct { #define WMI_TWT_SESSION_FLAG_ANNOUN_TWT_GET(_var) WMI_GET_BITS(_var, 18, 1) #define WMI_TWT_SESSION_FLAG_ANNOUN_TWT_SET(_var, _val) WMI_SET_BITS(_var, 18, 1, _val) +#define WMI_TWT_SESSION_FLAG_TWT_PROTECTION_GET(_var) WMI_GET_BITS(_var, 19, 1) +#define WMI_TWT_SESSION_FLAG_TWT_PROTECTION_SET(_var, _val) WMI_SET_BITS(_var, 19, 1, _val) + +#define WMI_TWT_SESSION_FLAG_TWT_INFO_FRAME_DISABLED_GET(_var) WMI_GET_BITS(_var, 20, 1) +#define WMI_TWT_SESSION_FLAG_TWT_INFO_FRAME_DISABLED_SET(_var, _val) WMI_SET_BITS(_var, 20, 1, _val) + typedef struct { /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_twt_session_stats_info */ A_UINT32 tlv_hdr; @@ -31328,6 +31334,9 @@ typedef struct { A_UINT32 wake_intvl_us; /* this long time after TWT resumed the 1st Service Period will start */ A_UINT32 sp_offset_us; + /* service period start TSF */ + A_UINT32 sp_tsf_us_lo; /* bits 31:0 */ + A_UINT32 sp_tsf_us_hi; /* bits 63:32 */ } wmi_twt_session_stats_info; enum wmi_twt_session_stats_type { diff --git a/fw/wmi_version.h b/fw/wmi_version.h index 77e46a82e4a0..0f5c9b56cab3 100644 --- a/fw/wmi_version.h +++ b/fw/wmi_version.h @@ -36,7 +36,7 @@ #define __WMI_VER_MINOR_ 0 /** WMI revision number has to be incremented when there is a * change that may or may not break compatibility. */ -#define __WMI_REVISION_ 861 +#define __WMI_REVISION_ 862 /** The Version Namespace should not be normally changed. Only * host and firmware of the same WMI namespace will work From 55e6d04583c2e2c286c3af1c993e4a339123d741 Mon Sep 17 00:00:00 2001 From: spuligil Date: Wed, 15 Jul 2020 12:01:28 -0700 Subject: [PATCH 186/592] fw-api: CL 10992505 - update fw common interface files Change-Id: Iedb5a1fc4f7f8bc34fdd829f9f299dfd9bffba05 WMI: add vdev extd stats CRs-Fixed: 2262693 --- fw/wmi_tlv_defs.h | 7 ++++-- fw/wmi_unified.h | 56 +++++++++++++++++++++++++++++++++-------------- fw/wmi_version.h | 2 +- 3 files changed, 46 insertions(+), 19 deletions(-) diff --git a/fw/wmi_tlv_defs.h b/fw/wmi_tlv_defs.h index c4f271960d39..4cfc55642a3d 100644 --- a/fw/wmi_tlv_defs.h +++ b/fw/wmi_tlv_defs.h @@ -1098,6 +1098,7 @@ typedef enum { WMITLV_TAG_STRUC_wmi_pdev_twt_session_stats_event_fixed_param, WMITLV_TAG_STRUC_wmi_twt_session_stats_info, WMITLV_TAG_STRUC_wmi_configure_roam_trigger_parameters, + WMITLV_TAG_STRUC_wmi_vdev_extd_stats, } WMITLV_TAG_ID; /* @@ -4979,7 +4980,8 @@ WMITLV_CREATE_PARAM_STRUC(WMI_HOST_SWFDA_EVENTID); WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_rssi_stats, rssi_stats, WMITLV_SIZE_VAR) \ WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_congestion_stats, congestion_stats, WMITLV_SIZE_VAR) \ WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_peer_extd2_stats, peer_extd2_stats, WMITLV_SIZE_VAR) \ - WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_pmf_bcn_protect_stats, pmf_bcn_protect_stats, WMITLV_SIZE_VAR) + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_pmf_bcn_protect_stats, pmf_bcn_protect_stats, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_vdev_extd_stats, vdev_extd_stats, WMITLV_SIZE_VAR) WMITLV_CREATE_PARAM_STRUC(WMI_UPDATE_STATS_EVENTID); /* Update PN response Event */ @@ -5787,7 +5789,8 @@ WMITLV_CREATE_PARAM_STRUC(WMI_PEER_STATS_INFO_EVENTID); /* Update Control Path stats event */ #define WMITLV_TABLE_WMI_CTRL_PATH_STATS_EVENTID(id, op, buf, len) \ WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_ctrl_path_stats_event_fixed_param, wmi_ctrl_path_stats_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ - WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_ctrl_path_pdev_stats_struct, ctrl_path_pdev_stats, WMITLV_SIZE_VAR) + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_ctrl_path_pdev_stats_struct, ctrl_path_pdev_stats, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_vdev_extd_stats, vdev_extd_stats, WMITLV_SIZE_VAR) WMITLV_CREATE_PARAM_STRUC(WMI_CTRL_PATH_STATS_EVENTID); #define WMITLV_TABLE_WMI_RADIO_CHAN_STATS_EVENTID(id, op, buf, len) \ diff --git a/fw/wmi_unified.h b/fw/wmi_unified.h index 0c6bdcca8a44..5c974b59b502 100644 --- a/fw/wmi_unified.h +++ b/fw/wmi_unified.h @@ -7774,22 +7774,23 @@ typedef struct { } wmi_pdev_set_wmm_params_cmd_fixed_param; typedef enum { - WMI_REQUEST_PEER_STAT = 0x0001, - WMI_REQUEST_AP_STAT = 0x0002, - WMI_REQUEST_PDEV_STAT = 0x0004, - WMI_REQUEST_VDEV_STAT = 0x0008, - WMI_REQUEST_BCNFLT_STAT = 0x0010, - WMI_REQUEST_VDEV_RATE_STAT = 0x0020, - WMI_REQUEST_INST_STAT = 0x0040, - WMI_REQUEST_MIB_STAT = 0x0080, - WMI_REQUEST_RSSI_PER_CHAIN_STAT = 0x0100, - WMI_REQUEST_CONGESTION_STAT = 0x0200, - WMI_REQUEST_PEER_EXTD_STAT = 0x0400, - WMI_REQUEST_BCN_STAT = 0x0800, - WMI_REQUEST_BCN_STAT_RESET = 0x1000, - WMI_REQUEST_PEER_EXTD2_STAT = 0x2000, - WMI_REQUEST_MIB_EXTD_STAT = 0x4000, - WMI_REQUEST_PMF_BCN_PROTECT_STAT = 0x8000, + WMI_REQUEST_PEER_STAT = 0x00001, + WMI_REQUEST_AP_STAT = 0x00002, + WMI_REQUEST_PDEV_STAT = 0x00004, + WMI_REQUEST_VDEV_STAT = 0x00008, + WMI_REQUEST_BCNFLT_STAT = 0x00010, + WMI_REQUEST_VDEV_RATE_STAT = 0x00020, + WMI_REQUEST_INST_STAT = 0x00040, + WMI_REQUEST_MIB_STAT = 0x00080, + WMI_REQUEST_RSSI_PER_CHAIN_STAT = 0x00100, + WMI_REQUEST_CONGESTION_STAT = 0x00200, + WMI_REQUEST_PEER_EXTD_STAT = 0x00400, + WMI_REQUEST_BCN_STAT = 0x00800, + WMI_REQUEST_BCN_STAT_RESET = 0x01000, + WMI_REQUEST_PEER_EXTD2_STAT = 0x02000, + WMI_REQUEST_MIB_EXTD_STAT = 0x04000, + WMI_REQUEST_PMF_BCN_PROTECT_STAT = 0x08000, + WMI_REQUEST_VDEV_EXTD_STAT = 0x10000, } wmi_stats_id; /* @@ -8514,6 +8515,10 @@ typedef struct { * wmi_pmf_bcn_protect_stats pmf_bcn_protect_stats[] * follows the other TLVs */ +/* If WMI_REQUEST_VDEV_EXTD_STAT is set in stats_id, then TLV + * wmi_vdev_extd_stats wmi_vdev_extd_stats[] + * follows the other TLVs + */ } wmi_stats_event_fixed_param; /* WLAN channel CCA stats bitmap */ @@ -9138,6 +9143,8 @@ typedef struct { * different types of stats: * 1. wmi_ctrl_path_pdev_stats_struct ctrl_path_pdev_stats[]; * This TLV array contains zero or more pdev stats instances. + * 2. wmi_vdev_extd_stats vdev_extd_stats[]; + * This TLV array contains zero or more vdev_extd_stats instances. */ } wmi_ctrl_path_stats_event_fixed_param; @@ -9287,6 +9294,23 @@ typedef struct { A_UINT32 tx_bcn_outage_cnt; /* Total number of failed beacons */ } wmi_bcn_stats; +/** + * vdev extension statistics + */ +typedef struct { + A_UINT32 tlv_header; + /* vdev id */ + A_UINT32 vdev_id; + /* Total number of Fils Discovery frames transmitted successfully */ + A_UINT32 fd_succ_cnt; + /* Total number of Fils Discovery frames failed */ + A_UINT32 fd_fail_cnt; + /* Total number of unsolicited probe response frames transmitted successfully */ + A_UINT32 unsolicited_prb_succ_cnt; + /* Total number of unsolicited probe response frames failed */ + A_UINT32 unsolicited_prb_fail_cnt; +} wmi_vdev_extd_stats; + /** * peer statistics. */ diff --git a/fw/wmi_version.h b/fw/wmi_version.h index 0f5c9b56cab3..136752caba37 100644 --- a/fw/wmi_version.h +++ b/fw/wmi_version.h @@ -36,7 +36,7 @@ #define __WMI_VER_MINOR_ 0 /** WMI revision number has to be incremented when there is a * change that may or may not break compatibility. */ -#define __WMI_REVISION_ 862 +#define __WMI_REVISION_ 863 /** The Version Namespace should not be normally changed. Only * host and firmware of the same WMI namespace will work From 9973ecba047e6d99b178dcd009d03458ef8918e2 Mon Sep 17 00:00:00 2001 From: spuligil Date: Wed, 15 Jul 2020 12:01:44 -0700 Subject: [PATCH 187/592] fw-api: CL 11006718 - update fw common interface files Change-Id: I36df38c84730aa158feee4897cbf0e28731663e9 WMI: add additional params TLV in TWT_ADD_DIALOG_COMPLETE_EVENT msg CRs-Fixed: 2262693 --- fw/wmi_tlv_defs.h | 4 +++- fw/wmi_unified.h | 19 +++++++++++++++++++ fw/wmi_version.h | 2 +- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/fw/wmi_tlv_defs.h b/fw/wmi_tlv_defs.h index 4cfc55642a3d..1a8ea2273fa0 100644 --- a/fw/wmi_tlv_defs.h +++ b/fw/wmi_tlv_defs.h @@ -1099,6 +1099,7 @@ typedef enum { WMITLV_TAG_STRUC_wmi_twt_session_stats_info, WMITLV_TAG_STRUC_wmi_configure_roam_trigger_parameters, WMITLV_TAG_STRUC_wmi_vdev_extd_stats, + WMITLV_TAG_STRUC_wmi_twt_add_dialog_additional_params, } WMITLV_TAG_ID; /* @@ -5874,7 +5875,8 @@ WMITLV_CREATE_PARAM_STRUC(WMI_TWT_DISABLE_COMPLETE_EVENTID); /* adding TWT dialog complete Event */ #define WMITLV_TABLE_WMI_TWT_ADD_DIALOG_COMPLETE_EVENTID(id,op,buf,len) \ - WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_twt_add_dialog_complete_event_fixed_param, wmi_twt_add_dialog_complete_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_twt_add_dialog_complete_event_fixed_param, wmi_twt_add_dialog_complete_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_twt_add_dialog_additional_params, twt_params, WMITLV_SIZE_VAR) WMITLV_CREATE_PARAM_STRUC(WMI_TWT_ADD_DIALOG_COMPLETE_EVENTID); /* deleting TWT dialog complete Event */ diff --git a/fw/wmi_unified.h b/fw/wmi_unified.h index 5c974b59b502..ae578177b294 100644 --- a/fw/wmi_unified.h +++ b/fw/wmi_unified.h @@ -27479,6 +27479,10 @@ typedef enum _WMI_TWT_COMMAND_T { #define TWT_FLAGS_GET_BTWT_ID0(flag) WMI_GET_BITS(flag, 12, 1) #define TWT_FLAGS_SET_BTWT_ID0(flag, val) WMI_SET_BITS(flag, 12, 1, val) +/* 0 means TWT Information frame is enabled, 1 means TWT Information frame is disabled */ +#define TWT_FLAGS_GET_TWT_INFO_FRAME_DISABLED(flag) WMI_GET_BITS(flag, 13, 1) +#define TWT_FLAGS_SET_TWT_INFO_FRAME_DISABLED(flag, val) WMI_SET_BITS(flag, 13, 1, val) + typedef struct { A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_twt_add_dialog_cmd_fixed_param */ A_UINT32 vdev_id; /* VDEV identifier */ @@ -27527,12 +27531,27 @@ typedef enum _WMI_ADD_TWT_STATUS_T { WMI_ADD_TWT_STATUS_UNKNOWN_ERROR, /* adding TWT dialog failed with an unknown reason */ } WMI_ADD_TWT_STATUS_T; +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_twt_add_dialog_additional_params */ + A_UINT32 flags; /* TWT flags, refer to MACROs TWT_FLAGS_*(TWT_FLAGS_GET_CMD etc) */ + A_UINT32 wake_dur_us; /* Wake duration in uS */ + A_UINT32 wake_intvl_us; /* Wake Interval in uS */ + A_UINT32 sp_offset_us; /* SP Starting Offset */ + A_UINT32 sp_tsf_us_lo; /* SP start TSF bits 31:0 */ + A_UINT32 sp_tsf_us_hi; /* SP start TSF bits 63:32 */ +} wmi_twt_add_dialog_additional_params; + typedef struct { A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_twt_add_dialog_complete_event_fixed_param */ A_UINT32 vdev_id; /* VDEV identifier */ wmi_mac_addr peer_macaddr; /* peer MAC address */ A_UINT32 dialog_id; /* TWT dialog ID */ A_UINT32 status; /* refer to WMI_ADD_TWT_STATUS_T */ +/* + * This fixed_param TLV is followed by the below TLVs: + * wmi_twt_add_dialog_additional_params twt_params[]; // TWT params received + * // from peer + */ } wmi_twt_add_dialog_complete_event_fixed_param; typedef struct { diff --git a/fw/wmi_version.h b/fw/wmi_version.h index 136752caba37..d00d9b4498bc 100644 --- a/fw/wmi_version.h +++ b/fw/wmi_version.h @@ -36,7 +36,7 @@ #define __WMI_VER_MINOR_ 0 /** WMI revision number has to be incremented when there is a * change that may or may not break compatibility. */ -#define __WMI_REVISION_ 863 +#define __WMI_REVISION_ 864 /** The Version Namespace should not be normally changed. Only * host and firmware of the same WMI namespace will work From 31e546aee7ad26a155348ae197e06b9518007817 Mon Sep 17 00:00:00 2001 From: spuligil Date: Wed, 15 Jul 2020 12:01:57 -0700 Subject: [PATCH 188/592] fw-api: CL 11019489 - update fw common interface files Change-Id: If3a36d90a89c5236c21aa67fb43f3eafe6c2f78b WMI: add sta_type bitfield in PEER_ASSOC_COMPLETE_CMD msg CRs-Fixed: 2262693 --- fw/wmi_unified.h | 23 +++++++++++++++++++++++ fw/wmi_version.h | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/fw/wmi_unified.h b/fw/wmi_unified.h index ae578177b294..3c932d9b320f 100644 --- a/fw/wmi_unified.h +++ b/fw/wmi_unified.h @@ -13231,6 +13231,22 @@ typedef struct { #define WMI_RC_TS_FLAG 0x200 /* Three stream flag */ #define WMI_RC_UAPSD_FLAG 0x400 /* UAPSD Rate Control */ +enum WMI_PEER_STA_TYPE { + WMI_PEER_STA_TYPE_INVALID = 0, /* Invalid type*/ + WMI_PEER_STA_TYPE_ONLY_STAVDEV = 1, /* AP has only STAVDEV and APVDEV is not present on any radio */ + WMI_PEER_STA_TYPE_APVDEV_ON_OTHER_RADIO = 2, /* AP has STAVDEV on one radio and APVDEV on other radios */ + WMI_PEER_STA_TYPE_FH_APVDEV_ON_SAME_RADIO = 3, /* AP has STAVDEV and APVDEV on same radio. During STAVDEV connection, + * no repeater client is connected with this repeater APVDEV + */ + WMI_PEER_STA_TYPE_BH_APVDEV_ON_SAME_RADIO = 4, /* AP has STAVDEV and APVDEV on same radio. During STAVDEV connection, + * at least one repeater client is connected with this repeater APVDEV + * (daisy chain config) + */ +}; + +#define WMI_PEER_STA_TYPE_GET(dword) WMI_GET_BITS(dword, 0, 8) +#define WMI_PEER_STA_TYPE_SET(dword, value) WMI_SET_BITS(dword, 0, 8, value) + typedef struct { A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_peer_assoc_complete_cmd_fixed_param */ /** peer MAC address */ @@ -13321,6 +13337,13 @@ typedef struct { */ A_UINT32 peer_he_caps_6ghz; + /* bit[0-7] : sta_type + * bit[8-31]: reserved + * Refer to enum WMI_PEER_STA_TYPE for sta_type values. + * Refer to WMI_PEER_STA_TYPE_GET/SET macros. + */ + A_UINT32 sta_type; + /* Following this struct are the TLV's: * A_UINT8 peer_legacy_rates[]; * A_UINT8 peer_ht_rates[]; diff --git a/fw/wmi_version.h b/fw/wmi_version.h index d00d9b4498bc..2d24e22fc2f0 100644 --- a/fw/wmi_version.h +++ b/fw/wmi_version.h @@ -36,7 +36,7 @@ #define __WMI_VER_MINOR_ 0 /** WMI revision number has to be incremented when there is a * change that may or may not break compatibility. */ -#define __WMI_REVISION_ 864 +#define __WMI_REVISION_ 865 /** The Version Namespace should not be normally changed. Only * host and firmware of the same WMI namespace will work From 3d39782da6a890597e2685d05332a70133986fa5 Mon Sep 17 00:00:00 2001 From: spuligil Date: Wed, 15 Jul 2020 12:02:10 -0700 Subject: [PATCH 189/592] fw-api: CL 11024688 - update fw common interface files Change-Id: I1df3da64260483d04148a1f821aa4fe3b6e9f86e WMI: add capture_count field, FILTER_IN_AS_FP_TA_RA_TYPE flag to CFR msg CRs-Fixed: 2262693 --- fw/wmi_services.h | 3 +++ fw/wmi_unified.h | 54 ++++++++++++++++++++++++++++++++++++++++++++--- fw/wmi_version.h | 2 +- 3 files changed, 55 insertions(+), 4 deletions(-) diff --git a/fw/wmi_services.h b/fw/wmi_services.h index 322e25c6de25..b6094be01e3c 100644 --- a/fw/wmi_services.h +++ b/fw/wmi_services.h @@ -447,6 +447,7 @@ typedef enum { WMI_SERVICE_NO_INTERBAND_MCC_SUPPORT = 252, /* Indicates FW doesn't support interband MCC */ WMI_SERVICE_MBSS_PARAM_IN_VDEV_START_SUPPORT = 253, /* FW supports VDEV's MBSS param exchange in VDEV start command */ WMI_SERVICE_CONFIGURE_ROAM_TRIGGER_PARAM_SUPPORT = 254, /* FW supports ROAM trigger configuration param TLV */ + WMI_SERVICE_CFR_TA_RA_AS_FP_SUPPORT = 255, /* indicates FW support to program CFR TA/RA filtered packets as Filter pass */ /******* ADD NEW SERVICES UP TO 256 HERE *******/ @@ -472,6 +473,8 @@ typedef enum { /******* ADD NEW SERVICES 256 AND BEYOND HERE *******/ + WMI_SERVICE_CFR_CAPTURE_COUNT_SUPPORT = 256, /* indicates FW support to program CFR capture mode and capture count */ + WMI_MAX_EXT2_SERVICE diff --git a/fw/wmi_unified.h b/fw/wmi_unified.h index 3c932d9b320f..a551e6b82872 100644 --- a/fw/wmi_unified.h +++ b/fw/wmi_unified.h @@ -30739,6 +30739,7 @@ typedef struct { #define WMI_CFR_NDPA_NDP_ALL_EN_BIT_POS 3 #define WMI_CFR_TA_RA_TYPE_FILTER_EN_BIT_POS 4 #define WMI_CFR_ALL_PACKET_EN_BIT_POS 5 +#define WMI_CFR_FILTER_IN_AS_FP_TA_RA_TYPE_BIT_POS 6 #define WMI_CFR_CAPTURE_INTERVAL_NUM_BITS 24 #define WMI_CFR_CAPTURE_INTERVAL_BIT_POS 0 @@ -30758,6 +30759,14 @@ typedef struct { #define WMI_CFR_FREEZE_DELAY_CNT_THR_NUM_BITS 8 #define WMI_CFR_FREEZE_DELAY_CNT_THR_BIT_POS 1 + +#define WMI_CFR_CAPTURE_COUNT_NUM_BITS 16 +#define WMI_CFR_CAPTURE_COUNT_BIT_POS 0 + +#define WMI_CFR_CAPTURE_INTERVAL_MODE_SEL_NUM_BITS 1 +#define WMI_CFR_CAPTURE_INTERVAL_MODE_SEL_BIT_POS 16 + + #define WMI_CFR_DIRECTED_FTM_ACK_EN_SET(param, value) \ WMI_SET_BITS(param, WMI_CFR_DIRECTED_FTM_ACK_EN_BIT_POS, 1, value) @@ -30796,6 +30805,12 @@ typedef struct { #define WMI_CFR_ALL_PACKET_EN_GET(param) \ WMI_GET_BITS(param, WMI_CFR_ALL_PACKET_EN_BIT_POS, 1) +#define WMI_CFR_FILTER_IN_AS_FP_TA_RA_TYPE_SET(param, value) \ + WMI_SET_BITS(param, WMI_CFR_FILTER_IN_AS_FP_TA_RA_TYPE_BIT_POS, 1, value) + +#define WMI_CFR_FILTER_IN_AS_FP_TA_RA_TYPE_GET(param) \ + WMI_GET_BITS(param, WMI_CFR_FILTER_IN_AS_FP_TA_RA_TYPE_BIT_POS, 1) + #define WMI_CFR_CAPTURE_INTERVAL_SET(param, value) \ WMI_SET_BITS(param, WMI_CFR_CAPTURE_INTERVAL_BIT_POS, WMI_CFR_CAPTURE_INTERVAL_NUM_BITS, value) @@ -30832,6 +30847,18 @@ typedef struct { #define WMI_CFR_FREEZE_DELAY_CNT_THR_GET(param) \ WMI_GET_BITS(param, WMI_CFR_FREEZE_DELAY_CNT_THR_BIT_POS, WMI_CFR_FREEZE_DELAY_CNT_THR_NUM_BITS) +#define WMI_CFR_CAPTURE_COUNT_SET(param, value) \ + WMI_SET_BITS(param, WMI_CFR_CAPTURE_COUNT_BIT_POS, WMI_CFR_CAPTURE_COUNT_NUM_BITS, value) + +#define WMI_CFR_CAPTURE_COUNT_GET(param) \ + WMI_GET_BITS(param, WMI_CFR_CAPTURE_COUNT_BIT_POS, WMI_CFR_CAPTURE_COUNT_NUM_BITS) + +#define WMI_CFR_CAPTURE_INTERVAL_MODE_SEL_SET(param, value) \ + WMI_SET_BITS(param, WMI_CFR_CAPTURE_INTERVAL_MODE_SEL_BIT_POS, WMI_CFR_CAPTURE_INTERVAL_MODE_SEL_NUM_BITS, value) + +#define WMI_CFR_CAPTURE_INTERVAL_MODE_SEL_GET(param) \ + WMI_GET_BITS(param, WMI_CFR_CAPTURE_INTERVAL_MODE_SEL_BIT_POS, WMI_CFR_CAPTURE_INTERVAL_MODE_SEL_NUM_BITS) + typedef struct { /** TLV tag and len; tag equals * WMITLV_TAG_STRUC_wmi_peer_cfr_capture_filter_cmd_fixed_param */ @@ -30846,10 +30873,12 @@ typedef struct { * Bit 0: Filter Directed FTM ACK frames for CFR capture * Bit 1: Filter All FTM ACK frames for CFR capture * Bit 2: Filter NDPA NDP Directed Frames for CFR capture - * Bit 3: Filter Frames based on TA/RA/Subtype as provided + * Bit 3: Filter NDPA NDP All Frames for CFR capture + * Bit 4: Filter Frames based on TA/RA/Subtype as provided * in CFR Group config - * Bit 4: Filter in All packets for CFR Capture - * Bits 31:5 Reserved for future use + * Bit 5: Filter in All packets for CFR Capture + * Bit 6: Filter in TA/RA frames as FP if this bit is set else as MO + * Bits 31:7 Reserved for future use */ A_UINT32 filter_type; /* capture_interval: @@ -30897,6 +30926,25 @@ typedef struct { * Bits 31:9 Reserved for future use */ A_UINT32 freeze_tlv_delay_cnt; + + /* capture_count: + * Indicates the number of consecutive packets for which CFR capture + * is to be enabled. + * Interpretation of capture_interval_mode_select (bit 16): + * Value 0: capture_interval + capture_duration fields are used + * to capture CFR for capture_duration after every + * capture_interval. + * Value 1: capture_interval + capture_count fields are used to + * capture CFR for capture_count+1 number of packets + * after every capture interval + * Bit 15:0 : capture_count + * Refer to WMI_CFR_CAPTURE_COUNT_GET/SET macros. + * Bit 16 : capture_interval_mode_select + * Refer to WMI_CFR_CAPTURE_INTERVAL_MODE_SEL_GET/SET macros. + * Bits 31:17 : Reserved + */ + A_UINT32 capture_count; + /* * A variable-length TLV array of wmi_cfr_filter_group_config will * follow this fixed_param TLV diff --git a/fw/wmi_version.h b/fw/wmi_version.h index 2d24e22fc2f0..1b5c3d46477a 100644 --- a/fw/wmi_version.h +++ b/fw/wmi_version.h @@ -36,7 +36,7 @@ #define __WMI_VER_MINOR_ 0 /** WMI revision number has to be incremented when there is a * change that may or may not break compatibility. */ -#define __WMI_REVISION_ 865 +#define __WMI_REVISION_ 866 /** The Version Namespace should not be normally changed. Only * host and firmware of the same WMI namespace will work From 14dc6399a5a92b5a3feaf9dcbbc8cf857c25d7a3 Mon Sep 17 00:00:00 2001 From: spuligil Date: Wed, 15 Jul 2020 12:02:25 -0700 Subject: [PATCH 190/592] fw-api: CL 11025894 - update fw common interface files HTT stats: add DBG_EXT_PKTLOG_AND_HTT_RING_STATS Change-Id: I7eff3217540ea7ec0b638e3ff18ecd26e06730f9 CRs-Fixed: 2262693 --- fw/htt_stats.h | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/fw/htt_stats.h b/fw/htt_stats.h index d0cb8ccc836a..68945063ec52 100644 --- a/fw/htt_stats.h +++ b/fw/htt_stats.h @@ -367,6 +367,14 @@ enum htt_dbg_ext_stats_type { */ HTT_DBG_EXT_VDEV_RTT_RESP_STATS = 34, + /* HTT_DBG_EXT_PKTLOG_AND_HTT_RING_STATS + * PARAMS: + * - No Params + * RESP MSG: + * - htt_pktlog_and_htt_ring_stats_t + */ + HTT_DBG_EXT_PKTLOG_AND_HTT_RING_STATS = 35, + /* keep this last */ HTT_DBG_NUM_EXT_STATS = 256, @@ -511,6 +519,7 @@ typedef enum { HTT_STATS_TXBF_OFDMA_STEER_STATS_TAG = 116, /* htt_txbf_ofdma_steer_stats_tlv */ HTT_STATS_STA_UL_OFDMA_STATS_TAG = 117, /* htt_sta_ul_ofdma_stats_tlv */ HTT_STATS_VDEV_RTT_RESP_STATS_TAG = 118, /* htt_vdev_rtt_resp_stats_tlv */ + HTT_STATS_PKTLOG_AND_HTT_RING_STATS_TAG = 119, /* htt_pktlog_and_htt_ring_stats_tlv */ HTT_STATS_MAX_TAG, } htt_tlv_tag_t; @@ -5113,5 +5122,28 @@ typedef struct { htt_vdev_rtt_resp_stats_tlv vdev_rtt_resp_stats; } htt_vdev_rtt_resp_stats_t; +/* STATS_TYPE : HTT_DBG_EXT_PKTLOG_AND_HTT_RING_STATS + * TLV_TAGS: + * - HTT_STATS_PKTLOG_AND_HTT_RING_STATS_TAG + */ +/* NOTE: + * This structure is for documentation, and cannot be safely used directly. + * Instead, use the constituent TLV structures to fill/parse. + */ +typedef struct { + htt_tlv_hdr_t tlv_hdr; + + /* No of pktlog payloads that were dropped in htt_ppdu_stats path */ + A_UINT32 pktlog_lite_drop_cnt; + /* No of pktlog payloads that were dropped in TQM path */ + A_UINT32 pktlog_tqm_drop_cnt; + /* No of pktlog ppdu stats payloads that were dropped */ + A_UINT32 pktlog_ppdu_stats_drop_cnt; + /* No of pktlog ppdu ctrl payloads that were dropped */ + A_UINT32 pktlog_ppdu_ctrl_drop_cnt; + /* No of pktlog sw events payloads that were dropped */ + A_UINT32 pktlog_sw_events_drop_cnt; +} htt_pktlog_and_htt_ring_stats_tlv; + #endif /* __HTT_STATS_H__ */ From 9b098432784fec09628fba8c99df727205f8f99a Mon Sep 17 00:00:00 2001 From: spuligil Date: Wed, 15 Jul 2020 12:02:38 -0700 Subject: [PATCH 191/592] fw-api: CL 11034593 - update fw common interface files Change-Id: I72c49865dc33afbae56c94da82f54a75543fa55f WMI: add WMI_SERVICE_OCV_SUPPORT def CRs-Fixed: 2262693 --- fw/wmi_services.h | 1 + fw/wmi_version.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/fw/wmi_services.h b/fw/wmi_services.h index b6094be01e3c..9b6d51c7f688 100644 --- a/fw/wmi_services.h +++ b/fw/wmi_services.h @@ -474,6 +474,7 @@ typedef enum { /******* ADD NEW SERVICES 256 AND BEYOND HERE *******/ WMI_SERVICE_CFR_CAPTURE_COUNT_SUPPORT = 256, /* indicates FW support to program CFR capture mode and capture count */ + WMI_SERVICE_OCV_SUPPORT = 257, /* FW supports OCV (Operating Channel Validation) */ WMI_MAX_EXT2_SERVICE diff --git a/fw/wmi_version.h b/fw/wmi_version.h index 1b5c3d46477a..a934d35826b1 100644 --- a/fw/wmi_version.h +++ b/fw/wmi_version.h @@ -36,7 +36,7 @@ #define __WMI_VER_MINOR_ 0 /** WMI revision number has to be incremented when there is a * change that may or may not break compatibility. */ -#define __WMI_REVISION_ 866 +#define __WMI_REVISION_ 867 /** The Version Namespace should not be normally changed. Only * host and firmware of the same WMI namespace will work From 4a048ec5e8873c35b29013566c7766a64a6b941f Mon Sep 17 00:00:00 2001 From: spuligil Date: Wed, 15 Jul 2020 12:02:54 -0700 Subject: [PATCH 192/592] fw-api: CL 11039524 - update fw common interface files Change-Id: I5497c849f5703e50df0ccf9838fdcda528ebf3fb WMI: add timestamp field to roam_btm_response, add ROAM_TRIGGER_SUB_REASONs CRs-Fixed: 2262693 --- fw/wmi_unified.h | 19 +++++++++++++++++++ fw/wmi_version.h | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/fw/wmi_unified.h b/fw/wmi_unified.h index a551e6b82872..072374fcefad 100644 --- a/fw/wmi_unified.h +++ b/fw/wmi_unified.h @@ -28276,6 +28276,9 @@ typedef struct { typedef enum { WMI_ROAM_TRIGGER_SUB_REASON_PERIODIC_TIMER = 1, /* Roam scan triggered due to periodic timer expiry */ WMI_ROAM_TRIGGER_SUB_REASON_INACTIVITY_TIMER, /* Roam scan triggered due to inactivity detection */ + /* INACTIVITY_TIMER_LOW_RSSI - alias for INACTIVITY_TIMER */ + WMI_ROAM_TRIGGER_SUB_REASON_INACTIVITY_TIMER_LOW_RSSI = + WMI_ROAM_TRIGGER_SUB_REASON_INACTIVITY_TIMER, WMI_ROAM_TRIGGER_SUB_REASON_BTM_DI_TIMER, /* Roam scan triggered due to BTM Disassoc Imminent timeout */ WMI_ROAM_TRIGGER_SUB_REASON_FULL_SCAN, /* Roam scan triggered due to partial scan failure */ WMI_ROAM_TRIGGER_SUB_REASON_LOW_RSSI_PERIODIC, /* Roam scan triggered due to Low rssi periodic timer */ @@ -28286,6 +28289,16 @@ typedef enum { * This timer is enabled/used for roaming in a vendor-specific manner. */ WMI_ROAM_TRIGGER_SUB_REASCON_PERIODIC_TIMER_AFTER_INACTIVITY, + WMI_ROAM_TRIGGER_SUB_REASON_PERIODIC_TIMER_AFTER_INACTIVITY = + WMI_ROAM_TRIGGER_SUB_REASCON_PERIODIC_TIMER_AFTER_INACTIVITY, + /* + * PERIODIC_TIMER_AFTER_INACTIVITY_LOW_RSSI - alias for + * PERIODIC_TIMER_AFTER_INACTIVITY + */ + WMI_ROAM_TRIGGER_SUB_REASON_PERIODIC_TIMER_AFTER_INACTIVITY_LOW_RSSI = + WMI_ROAM_TRIGGER_SUB_REASON_PERIODIC_TIMER_AFTER_INACTIVITY, + WMI_ROAM_TRIGGER_SUB_REASON_PERIODIC_TIMER_AFTER_INACTIVITY_CU, + WMI_ROAM_TRIGGER_SUB_REASON_INACTIVITY_TIMER_CU, } WMI_ROAM_TRIGGER_SUB_REASON_ID; typedef enum wmi_roam_invoke_status_error { @@ -28518,6 +28531,12 @@ typedef struct { * 0x08-0xFF TBD */ A_UINT32 vsie_reason; + /* + * timestamp is the absolute time w.r.t host timer which is synchronized + * between the host and target. + * This timestamp indicates the time when btm response is sent. + */ + A_UINT32 timestamp; /* milli second units */ } wmi_roam_btm_response_info; typedef struct { diff --git a/fw/wmi_version.h b/fw/wmi_version.h index a934d35826b1..363be9ec28b3 100644 --- a/fw/wmi_version.h +++ b/fw/wmi_version.h @@ -36,7 +36,7 @@ #define __WMI_VER_MINOR_ 0 /** WMI revision number has to be incremented when there is a * change that may or may not break compatibility. */ -#define __WMI_REVISION_ 867 +#define __WMI_REVISION_ 868 /** The Version Namespace should not be normally changed. Only * host and firmware of the same WMI namespace will work From 087d7a03239539b3cb9fc82ab328ceabcd454a7d Mon Sep 17 00:00:00 2001 From: snandini Date: Wed, 15 Jul 2020 13:50:03 -0700 Subject: [PATCH 193/592] Release 5.2.03.29I Release 5.2.03.29I Change-Id: I07267dccf843b38a513d942e3c2c357bf8825238 CRs-Fixed: 774533 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index 926ddaa93f28..cf9473de94f2 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -32,9 +32,9 @@ #define QWLAN_VERSION_MAJOR 5 #define QWLAN_VERSION_MINOR 2 #define QWLAN_VERSION_PATCH 03 -#define QWLAN_VERSION_EXTRA "H" +#define QWLAN_VERSION_EXTRA "I" #define QWLAN_VERSION_BUILD 29 -#define QWLAN_VERSIONSTR "5.2.03.29H" +#define QWLAN_VERSIONSTR "5.2.03.29I" #endif /* QWLAN_VERSION_H */ From 2e19136d177a027aee315949d92711a2f1f6612d Mon Sep 17 00:00:00 2001 From: spuligil Date: Wed, 15 Jul 2020 18:00:38 -0700 Subject: [PATCH 194/592] fw-api: CL 11046353 - update fw common interface files add WMI_SCAN_FLAG_EXT_6GHZ_EXTEND_MEASURE_TIME def Change-Id: I95b1fc587a5947f2bae1ae53478cf26f54919818 CRs-Fixed: 2262693 --- fw/wmi_unified.h | 3 +++ fw/wmi_version.h | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/fw/wmi_unified.h b/fw/wmi_unified.h index 072374fcefad..d7f1ec7b3946 100644 --- a/fw/wmi_unified.h +++ b/fw/wmi_unified.h @@ -4351,6 +4351,9 @@ typedef enum { /* Force broadcast address in RA even though specified bssid */ #define WMI_SCAN_FLAG_EXT_FORCE_BRCAST_RA 0x00000200 +/* Extend 6ghz channel measure time */ +#define WMI_SCAN_FLAG_EXT_6GHZ_EXTEND_MEASURE_TIME 0x00000400 + /** * new 6 GHz flags per chan (short ssid or bssid) in struct * wmi_hint_freq_short_ssid or wmi_hint_freq_bssid diff --git a/fw/wmi_version.h b/fw/wmi_version.h index 363be9ec28b3..6be23827697f 100644 --- a/fw/wmi_version.h +++ b/fw/wmi_version.h @@ -36,7 +36,7 @@ #define __WMI_VER_MINOR_ 0 /** WMI revision number has to be incremented when there is a * change that may or may not break compatibility. */ -#define __WMI_REVISION_ 868 +#define __WMI_REVISION_ 869 /** The Version Namespace should not be normally changed. Only * host and firmware of the same WMI namespace will work From 7b7ff50dd1b54c8cb020f710d5496f0734c550fd Mon Sep 17 00:00:00 2001 From: Ajay Agarwal Date: Wed, 22 Apr 2020 23:39:06 +0530 Subject: [PATCH 195/592] usb: gadget: f_gsi: Increase num of buffers to 50 for ECM Currently the ECM interface has 15 data buffers allocated by the driver which can be used by IPA. In some telematics platform concurrency scenarios like Ethernet and USB together, this number is not enough for IPA to keep packets in its stack and service the Ethernet pipe. Hence the packets get dropped leading to lower throughput on both the pipes. Fix this by increasing the number of buffers to 50 for relevant interfaces. Change-Id: I65e0282143d489ab9f6b9fcc640cad7808adb68d Signed-off-by: Ajay Agarwal --- drivers/usb/gadget/function/f_gsi.c | 6 +++--- drivers/usb/gadget/function/f_gsi.h | 3 +-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/usb/gadget/function/f_gsi.c b/drivers/usb/gadget/function/f_gsi.c index 5a2b8ab2b95c..709052bf9e53 100644 --- a/drivers/usb/gadget/function/f_gsi.c +++ b/drivers/usb/gadget/function/f_gsi.c @@ -2968,7 +2968,7 @@ static int gsi_bind(struct usb_configuration *c, struct usb_function *f) info.out_epname = "gsi-epout"; info.in_req_buf_len = GSI_IN_RNDIS_BUFF_SIZE; gsi->d_port.in_aggr_size = GSI_IN_RNDIS_AGGR_SIZE; - info.in_req_num_buf = GSI_NUM_IN_RNDIS_BUFFERS; + info.in_req_num_buf = GSI_NUM_IN_RNDIS_RMNET_ECM_BUFFERS; gsi->d_port.out_aggr_size = GSI_OUT_AGGR_SIZE; info.out_req_buf_len = GSI_OUT_AGGR_SIZE; info.out_req_num_buf = GSI_NUM_OUT_BUFFERS; @@ -3167,7 +3167,7 @@ static int gsi_bind(struct usb_configuration *c, struct usb_function *f) info.out_epname = "gsi-epout"; gsi->d_port.in_aggr_size = GSI_IN_RMNET_AGGR_SIZE; info.in_req_buf_len = GSI_IN_RMNET_BUFF_SIZE; - info.in_req_num_buf = GSI_NUM_IN_RMNET_BUFFERS; + info.in_req_num_buf = GSI_NUM_IN_RNDIS_RMNET_ECM_BUFFERS; gsi->d_port.out_aggr_size = GSI_OUT_AGGR_SIZE; info.out_req_buf_len = GSI_OUT_RMNET_BUF_LEN; info.out_req_num_buf = GSI_NUM_OUT_BUFFERS; @@ -3200,7 +3200,7 @@ static int gsi_bind(struct usb_configuration *c, struct usb_function *f) info.out_epname = "gsi-epout"; gsi->d_port.in_aggr_size = GSI_ECM_AGGR_SIZE; info.in_req_buf_len = GSI_IN_BUFF_SIZE; - info.in_req_num_buf = GSI_NUM_IN_BUFFERS; + info.in_req_num_buf = GSI_NUM_IN_RNDIS_RMNET_ECM_BUFFERS; gsi->d_port.out_aggr_size = GSI_ECM_AGGR_SIZE; info.out_req_buf_len = GSI_OUT_ECM_BUF_LEN; info.out_req_num_buf = GSI_NUM_OUT_BUFFERS; diff --git a/drivers/usb/gadget/function/f_gsi.h b/drivers/usb/gadget/function/f_gsi.h index 43fba6d61179..0db1f0ac381d 100644 --- a/drivers/usb/gadget/function/f_gsi.h +++ b/drivers/usb/gadget/function/f_gsi.h @@ -44,8 +44,7 @@ #define GSI_MAX_CTRL_PKT_SIZE 8192 #define GSI_CTRL_DTR (1 << 0) -#define GSI_NUM_IN_RNDIS_BUFFERS 50 -#define GSI_NUM_IN_RMNET_BUFFERS 50 +#define GSI_NUM_IN_RNDIS_RMNET_ECM_BUFFERS 50 #define GSI_NUM_IN_BUFFERS 15 #define GSI_IN_BUFF_SIZE 2048 #define GSI_IN_RMNET_BUFF_SIZE 31744 From d5388a5072cab6c712d314b2860311ee163de198 Mon Sep 17 00:00:00 2001 From: Manaf Meethalavalappu Pallikunhi Date: Tue, 14 Jul 2020 14:06:31 +0530 Subject: [PATCH 196/592] ARM: dts: msm: update modem Tj thermal zone trips for SA515 Update modem Tj thermal zone trips for sa515 variants based on latest recommendation. Change-Id: Ibd14e17ba466eb11095a4a87a45d2c556d0cb7b7 Signed-off-by: Manaf Meethalavalappu Pallikunhi --- arch/arm64/boot/dts/qcom/sa515m-ccard.dtsi | 20 +++++++++++++++++ .../arm64/boot/dts/qcom/sa515m-flashless.dtsi | 22 +++++++++++++++++++ arch/arm64/boot/dts/qcom/sa515m-v2-ttp.dtsi | 20 +++++++++++++++++ .../boot/dts/qcom/sdxprairie-v2-dsda-cdp.dts | 20 +++++++++++++++++ 4 files changed, 82 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sa515m-ccard.dtsi b/arch/arm64/boot/dts/qcom/sa515m-ccard.dtsi index 69f4da650cec..6430b1a47797 100644 --- a/arch/arm64/boot/dts/qcom/sa515m-ccard.dtsi +++ b/arch/arm64/boot/dts/qcom/sa515m-ccard.dtsi @@ -97,6 +97,26 @@ /delete-node/ pm8150b-bcl-lvl1; /delete-node/ pm8150b-bcl-lvl2; /delete-node/ soc; + + /* update Tj thresholds */ + mdm-core-0-step { + trips { + active-config0 { + temperature = <95000>; + hysteresis = <5000>; + }; + + active-config1 { + temperature = <100000>; + hysteresis = <5000>; + }; + + active-config2 { + temperature = <105000>; + hysteresis = <5000>; + }; + }; + }; }; &usb { diff --git a/arch/arm64/boot/dts/qcom/sa515m-flashless.dtsi b/arch/arm64/boot/dts/qcom/sa515m-flashless.dtsi index 9b3b3cf860d5..1c1a676c0413 100644 --- a/arch/arm64/boot/dts/qcom/sa515m-flashless.dtsi +++ b/arch/arm64/boot/dts/qcom/sa515m-flashless.dtsi @@ -19,3 +19,25 @@ &pil_modem { qcom,auto-boot; }; + +&thermal_zones { + /* update Tj thresholds */ + mdm-core-0-step { + trips { + active-config0 { + temperature = <95000>; + hysteresis = <5000>; + }; + + active-config1 { + temperature = <100000>; + hysteresis = <5000>; + }; + + active-config2 { + temperature = <105000>; + hysteresis = <5000>; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sa515m-v2-ttp.dtsi b/arch/arm64/boot/dts/qcom/sa515m-v2-ttp.dtsi index cd13e45e4145..e35648a1520a 100644 --- a/arch/arm64/boot/dts/qcom/sa515m-v2-ttp.dtsi +++ b/arch/arm64/boot/dts/qcom/sa515m-v2-ttp.dtsi @@ -30,6 +30,26 @@ /delete-node/ pm8150b-bcl-lvl1; /delete-node/ pm8150b-bcl-lvl2; /delete-node/ soc; + + /* update Tj thresholds */ + mdm-core-0-step { + trips { + active-config0 { + temperature = <95000>; + hysteresis = <5000>; + }; + + active-config1 { + temperature = <100000>; + hysteresis = <5000>; + }; + + active-config2 { + temperature = <105000>; + hysteresis = <5000>; + }; + }; + }; }; &usb { diff --git a/arch/arm64/boot/dts/qcom/sdxprairie-v2-dsda-cdp.dts b/arch/arm64/boot/dts/qcom/sdxprairie-v2-dsda-cdp.dts index 165a3275f2af..99e9f86f5f14 100644 --- a/arch/arm64/boot/dts/qcom/sdxprairie-v2-dsda-cdp.dts +++ b/arch/arm64/boot/dts/qcom/sdxprairie-v2-dsda-cdp.dts @@ -35,6 +35,26 @@ /delete-node/ pm8150b-bcl-lvl1; /delete-node/ pm8150b-bcl-lvl2; /delete-node/ soc; + + /* update Tj thresholds */ + mdm-core-0-step { + trips { + active-config0 { + temperature = <95000>; + hysteresis = <5000>; + }; + + active-config1 { + temperature = <100000>; + hysteresis = <5000>; + }; + + active-config2 { + temperature = <105000>; + hysteresis = <5000>; + }; + }; + }; }; &usb { From 3df8fc99697afb143e92158b8182f652567055c7 Mon Sep 17 00:00:00 2001 From: Bojun Pan Date: Wed, 15 Jul 2020 15:42:43 -0700 Subject: [PATCH 197/592] msm: ipa: send the endp_desc QMI for low_lat only on non-auto mode There is no low_lat use case on auto mode, so the ep mapping is not defined. Add sanity check to not sent endp_desc QMI for ep which is not defined. Add check to make sure send endp_desc specific to low lat only for mhi non-auto case. Change-Id: I6fe72556433c0ac84772411cc5b1ac99bcadc30e Signed-off-by: Bojun Pan --- drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c index 8c2f12e6dc2c..d6cd1b856bea 100644 --- a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c @@ -1496,6 +1496,10 @@ static int ipa_send_mhi_endp_ind_to_modem(void) int ipa_mhi_cons_ep_idx = ipa3_get_ep_mapping(IPA_CLIENT_MHI_LOW_LAT_CONS); + if (ipa_mhi_prod_ep_idx == IPA_EP_NOT_ALLOCATED || + ipa_mhi_cons_ep_idx == IPA_EP_NOT_ALLOCATED) + return -EINVAL; + memset(&req, 0, sizeof(struct ipa_endp_desc_indication_msg_v01)); req.ep_info_len = 2; req.ep_info_valid = true; @@ -4165,7 +4169,12 @@ void ipa3_q6_handshake_complete(bool ssr_bootup) if (ipa3_ctx->ipa_mhi_proxy) imp_handle_modem_ready(); - if (ipa3_ctx->ipa_config_is_mhi) + /* + * currently the endp_desc indication only send + * on non-auto mode for low latency pipes + */ + if (ipa3_ctx->ipa_config_is_mhi && + !ipa3_ctx->ipa_config_is_auto) ipa_send_mhi_endp_ind_to_modem(); } From 4882f265ae949a01dce2ac7ce88f9c2419b4b895 Mon Sep 17 00:00:00 2001 From: Aniket Randive Date: Mon, 29 Jun 2020 11:25:10 +0530 Subject: [PATCH 198/592] usb: gadget: f_ipc: Add support of sideband notifier call chain Due to host is in suspend mode the write operation on usb endpoint is fail so register sideband signal to notify the GPIO driver with "EVT_WAKE_UP" event, so GPIO driver will wakeup the host as per event. due to the sideband signalling mechanism, peripheral is able to send important message after host is coming out from suspend. Change-Id: I1196f265464ab13e55c1a69fbeb22a1d85d19dcb Signed-off-by: Aniket Randive --- drivers/usb/gadget/function/f_ipc.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/function/f_ipc.c b/drivers/usb/gadget/function/f_ipc.c index 1e6a1b4ac822..f77991cd1f80 100644 --- a/drivers/usb/gadget/function/f_ipc.c +++ b/drivers/usb/gadget/function/f_ipc.c @@ -21,6 +21,7 @@ #include #include #include +#include #define MAX_INST_NAME_LEN 40 @@ -272,22 +273,34 @@ retry_write: reinit_completion(&ipc_dev->write_done); if (usb_ep_queue(in, req, GFP_KERNEL)) { + /* Notify GPIO driver to wakup the host if host + * is in suspend mode. + */ + sb_notifier_call_chain(EVT_WAKE_UP, NULL); wait_event_interruptible(ipc_dev->state_wq, ipc_dev->online || ipc_dev->current_state == IPC_DISCONNECTED); pr_debug("%s: Interface ready, Retry IN request\n", __func__); goto retry_write; } +retry_write_done: ret = wait_for_completion_interruptible_timeout(&ipc_dev->write_done, msecs_to_jiffies(IPC_WRITE_WAIT_TIMEOUT)); if (ret < 0) { pr_err("%s: Interruption triggered\n", __func__); ret = -EINTR; goto fail; - } else if (ret == 0) { + } else if (ret == 0 && ipc_dev->online) { pr_err("%s: Request timed out\n", __func__); ret = -ETIMEDOUT; goto fail; + /* Notify the GPIO driver to wakeup the host and reintialize the + * completion structure. + */ + } else if (!ipc_dev->online) { + sb_notifier_call_chain(EVT_WAKE_UP, NULL); + reinit_completion(&ipc_dev->write_done); + goto retry_write_done; } return !req->status ? req->actual : req->status; From 5d0b7069d1f2a5996391c2044c702ebb2fbc0726 Mon Sep 17 00:00:00 2001 From: Akshay Pandit Date: Fri, 10 Jul 2020 02:15:54 +0530 Subject: [PATCH 199/592] msm: ipa3: Support uc header proc ctx for DSCP insertion Add UC header proc ctx support for inserting DSCP in layer 3 header. Change-Id: I976b1f2bbbfda2acb3dd52fdebab09ac1ed90ecd Signed-off-by: Akshay Pandit --- drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c | 1 + drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c | 6 ++++++ drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h | 1 + include/uapi/linux/msm_ipa.h | 5 +++-- 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c index 09856c4403dd..4e87ede63057 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c @@ -110,6 +110,7 @@ const char *ipa3_hdr_proc_type_name[] = { __stringify(IPA_HDR_PROC_ETHII_TO_ETHII_EX), __stringify(IPA_HDR_PROC_L2TP_UDP_HEADER_ADD), __stringify(IPA_HDR_PROC_L2TP_UDP_HEADER_REMOVE), + __stringify(IPA_HDR_PROC_SET_DSCP), }; static struct dentry *dent; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c index e16003813a9c..4d261f862d97 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c @@ -1428,6 +1428,9 @@ static int ipahal_cp_proc_ctx_to_hw_buff_v3(enum ipa_hdr_proc_type type, case IPA_HDR_PROC_802_3_TO_802_3: ctx->cmd.value = IPA_HDR_UCP_802_3_TO_802_3; break; + case IPA_HDR_PROC_SET_DSCP: + ctx->cmd.value = IPA_HDR_UCP_SET_DSCP; + break; default: IPAHAL_ERR("unknown ipa_hdr_proc_type %d", type); WARN_ON(1); @@ -1480,6 +1483,9 @@ static int ipahal_get_proc_ctx_needed_len_v3(enum ipa_hdr_proc_type type) case IPA_HDR_PROC_ETHII_TO_ETHII_EX: ret = sizeof(struct ipa_hw_hdr_proc_ctx_add_hdr_cmd_seq_ex); break; + case IPA_HDR_PROC_SET_DSCP: + ret = sizeof(struct ipa_hw_hdr_proc_ctx_add_hdr_cmd_seq); + break; default: /* invalid value to make sure failure */ IPAHAL_ERR_RL("invalid ipa_hdr_proc_type %d\n", type); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h index 77524c4a5227..787da2a651ff 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h @@ -624,6 +624,7 @@ struct ipa_pkt_status_hw { #define IPA_HDR_UCP_L2TP_UDP_HEADER_ADD 12 #define IPA_HDR_UCP_L2TP_UDP_HEADER_REMOVE 13 #define IPA_HDR_UCP_ETHII_TO_ETHII_EX 14 +#define IPA_HDR_UCP_SET_DSCP 16 /* Processing context TLV type */ #define IPA_PROC_CTX_TLV_TYPE_END 0 diff --git a/include/uapi/linux/msm_ipa.h b/include/uapi/linux/msm_ipa.h index 497526feb0ca..00b293065977 100644 --- a/include/uapi/linux/msm_ipa.h +++ b/include/uapi/linux/msm_ipa.h @@ -1184,9 +1184,10 @@ enum ipa_hdr_proc_type { IPA_HDR_PROC_L2TP_HEADER_REMOVE, IPA_HDR_PROC_ETHII_TO_ETHII_EX, IPA_HDR_PROC_L2TP_UDP_HEADER_ADD, - IPA_HDR_PROC_L2TP_UDP_HEADER_REMOVE + IPA_HDR_PROC_L2TP_UDP_HEADER_REMOVE, + IPA_HDR_PROC_SET_DSCP, }; -#define IPA_HDR_PROC_MAX (IPA_HDR_PROC_L2TP_UDP_HEADER_REMOVE + 1) +#define IPA_HDR_PROC_MAX (IPA_HDR_PROC_SET_DSCP + 1) /** * struct ipa_rt_rule - attributes of a routing rule From 23c8927c98a12de6b09336a1c7ae41921a68e4ba Mon Sep 17 00:00:00 2001 From: Venkata Prahlad Valluru Date: Fri, 17 Jul 2020 20:59:42 +0530 Subject: [PATCH 200/592] video: fbdev: msm: add interface to send idle on/off command to panel This allows the use of different refresh rates during idle and active state of the panel. This helps in reducing panel power consumption in idle state. Change-Id: I83d2d71a210c1ac34dc52c11cab698b19a0089a6 Signed-off-by: Venkata Prahlad Valluru --- drivers/video/fbdev/msm/mdss_dsi.h | 3 + drivers/video/fbdev/msm/mdss_dsi_panel.c | 70 +++++++++++++++++++++++- drivers/video/fbdev/msm/mdss_panel.h | 12 ++++ 3 files changed, 83 insertions(+), 2 deletions(-) diff --git a/drivers/video/fbdev/msm/mdss_dsi.h b/drivers/video/fbdev/msm/mdss_dsi.h index 0a72aadca739..da704cbe9682 100644 --- a/drivers/video/fbdev/msm/mdss_dsi.h +++ b/drivers/video/fbdev/msm/mdss_dsi.h @@ -476,6 +476,7 @@ struct mdss_dsi_ctrl_pdata { bool dsi_irq_line; bool dcs_cmd_insert; atomic_t te_irq_ready; + bool idle; bool cmd_sync_wait_broadcast; bool cmd_sync_wait_trigger; @@ -507,6 +508,8 @@ struct mdss_dsi_ctrl_pdata { struct dsi_panel_cmds lp_on_cmds; struct dsi_panel_cmds lp_off_cmds; struct dsi_panel_cmds status_cmds; + struct dsi_panel_cmds idle_on_cmds; /* for lp mode */ + struct dsi_panel_cmds idle_off_cmds; u32 *status_valid_params; u32 *status_cmds_rlen; u32 *status_value; diff --git a/drivers/video/fbdev/msm/mdss_dsi_panel.c b/drivers/video/fbdev/msm/mdss_dsi_panel.c index f9f41f5aeb62..4929de1c56c5 100644 --- a/drivers/video/fbdev/msm/mdss_dsi_panel.c +++ b/drivers/video/fbdev/msm/mdss_dsi_panel.c @@ -251,6 +251,55 @@ static void mdss_dsi_panel_bklt_dcs(struct mdss_dsi_ctrl_pdata *ctrl, int level) mdss_dsi_cmdlist_put(ctrl, &cmdreq); } +static void mdss_dsi_panel_set_idle_mode(struct mdss_panel_data *pdata, + bool enable) +{ + struct mdss_dsi_ctrl_pdata *ctrl = NULL; + + if (pdata == NULL) { + pr_err("%s: Invalid input data\n", __func__); + return; + } + + ctrl = container_of(pdata, struct mdss_dsi_ctrl_pdata, + panel_data); + + pr_debug("%s: Idle (%d->%d)\n", __func__, ctrl->idle, enable); + + if (ctrl->idle == enable) + return; + + if (enable) { + if (ctrl->idle_on_cmds.cmd_cnt) { + mdss_dsi_panel_cmds_send(ctrl, &ctrl->idle_on_cmds, + CMD_REQ_COMMIT); + ctrl->idle = true; + pr_debug("Idle on\n"); + } + } else { + if (ctrl->idle_off_cmds.cmd_cnt) { + mdss_dsi_panel_cmds_send(ctrl, &ctrl->idle_off_cmds, + CMD_REQ_COMMIT); + ctrl->idle = false; + pr_debug("Idle off\n"); + } + } +} + +static bool mdss_dsi_panel_get_idle_mode(struct mdss_panel_data *pdata) + +{ + struct mdss_dsi_ctrl_pdata *ctrl = NULL; + + if (pdata == NULL) { + pr_err("%s: Invalid input data\n", __func__); + return 0; + } + ctrl = container_of(pdata, struct mdss_dsi_ctrl_pdata, + panel_data); + return ctrl->idle; +} + static int mdss_dsi_request_gpios(struct mdss_dsi_ctrl_pdata *ctrl_pdata) { int rc = 0; @@ -1009,6 +1058,8 @@ static int mdss_dsi_post_panel_on(struct mdss_panel_data *pdata) } end: + /* clear idle state */ + ctrl->idle = false; pr_debug("%s:-\n", __func__); return 0; } @@ -1066,7 +1117,11 @@ static int mdss_dsi_panel_low_power_config(struct mdss_panel_data *pdata, enable); /* Any panel specific low power commands/config */ - + /* Control idle mode for panel */ + if (enable) + mdss_dsi_panel_set_idle_mode(pdata, true); + else + mdss_dsi_panel_set_idle_mode(pdata, false); pr_debug("%s:-\n", __func__); return 0; } @@ -2984,6 +3039,17 @@ static int mdss_panel_parse_dt(struct device_node *np, mdss_dsi_parse_dcs_cmds(np, &ctrl_pdata->off_cmds, "qcom,mdss-dsi-off-command", "qcom,mdss-dsi-off-command-state"); + mdss_dsi_parse_dcs_cmds(np, &ctrl_pdata->idle_on_cmds, + "qcom,mdss-dsi-idle-on-command", + "qcom,mdss-dsi-idle-on-command-state"); + + mdss_dsi_parse_dcs_cmds(np, &ctrl_pdata->idle_off_cmds, + "qcom,mdss-dsi-idle-off-command", + "qcom,mdss-dsi-idle-off-command-state"); + + rc = of_property_read_u32(np, "qcom,mdss-dsi-idle-fps", &tmp); + pinfo->mipi.frame_rate_idle = (!rc ? tmp : 60); + rc = of_property_read_u32(np, "qcom,adjust-timer-wakeup-ms", &tmp); pinfo->adjust_timer_delay_ms = (!rc ? tmp : 0); @@ -3075,6 +3141,6 @@ int mdss_dsi_panel_init(struct device_node *node, ctrl_pdata->panel_data.apply_display_setting = mdss_dsi_panel_apply_display_setting; ctrl_pdata->switch_mode = mdss_dsi_panel_switch_mode; - + ctrl_pdata->panel_data.get_idle = mdss_dsi_panel_get_idle_mode; return 0; } diff --git a/drivers/video/fbdev/msm/mdss_panel.h b/drivers/video/fbdev/msm/mdss_panel.h index 55bf8c06ec90..27b5b845bda0 100644 --- a/drivers/video/fbdev/msm/mdss_panel.h +++ b/drivers/video/fbdev/msm/mdss_panel.h @@ -519,6 +519,7 @@ struct mipi_panel_info { char traffic_mode; char frame_rate; /* command mode */ + char frame_rate_idle; char interleave_max; char insert_dcs_cmd; char wr_mem_continue; @@ -1003,6 +1004,7 @@ struct mdss_panel_data { */ int (*event_handler)(struct mdss_panel_data *pdata, int e, void *arg); struct device_node *(*get_fb_node)(struct platform_device *pdev); + bool (*get_idle)(struct mdss_panel_data *pdata); struct list_head timings_list; struct mdss_panel_timing *current_timing; @@ -1038,6 +1040,10 @@ static inline u32 mdss_panel_get_framerate(struct mdss_panel_info *panel_info) { u32 frame_rate, pixel_total; u64 rate; + struct mdss_panel_data *panel_data = + container_of(panel_info, typeof(*panel_data), + panel_info); + bool idle = false; if (panel_info == NULL) return DEFAULT_FRAME_RATE; @@ -1046,6 +1052,12 @@ static inline u32 mdss_panel_get_framerate(struct mdss_panel_info *panel_info) case MIPI_VIDEO_PANEL: case MIPI_CMD_PANEL: frame_rate = panel_info->mipi.frame_rate; + if (panel_data->get_idle) + idle = panel_data->get_idle(panel_data); + if (idle) + frame_rate = panel_info->mipi.frame_rate_idle; + else + frame_rate = panel_info->mipi.frame_rate; break; case EDP_PANEL: frame_rate = panel_info->edp.frame_rate; From 7b523bbf409657da868f59402696e88e04af62d1 Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Mon, 23 Sep 2019 10:21:08 +0530 Subject: [PATCH 201/592] ARM: dts: msm: Add MHI and PCIe configuration Additional config added to LE CPE platform Depends-on: 2875186 Change-Id: I658568988e80f1c538d02b77cc8771951d4d585e Acked-by: Gajendra Singh Signed-off-by: Signed-off-by: Aman Gupta --- .../dts/qcom/sdxprairie-v2-mtp-le-cpe.dtsi | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sdxprairie-v2-mtp-le-cpe.dtsi b/arch/arm64/boot/dts/qcom/sdxprairie-v2-mtp-le-cpe.dtsi index 0150fb2eef74..b078b9d38ef0 100644 --- a/arch/arm64/boot/dts/qcom/sdxprairie-v2-mtp-le-cpe.dtsi +++ b/arch/arm64/boot/dts/qcom/sdxprairie-v2-mtp-le-cpe.dtsi @@ -37,3 +37,27 @@ status = "disabled"; }; }; + +&cnss_qca6390 { + status = "disabled"; +}; + +&ipa_hw { + qcom,use-ipa-in-mhi-mode; +}; + +&pcie0 { + status = "disabled"; +}; + +&pcie_ep { + status = "ok"; +}; + +&mhi_device { + status = "ok"; +}; + +&mhi_net_device { + status = "ok"; +}; From 1e32a780c153511a99020adac88d2eacf2057f3a Mon Sep 17 00:00:00 2001 From: Ajit Kumar Date: Mon, 20 Jul 2020 13:40:31 +0530 Subject: [PATCH 202/592] ARM: dts: msm: Add shared_ee property to bg spi node Add shared_ee property for bg spi node. It helps to have the spi as a shared resource with TZ. Change-Id: I2a2c36783b4222fe1fcff7dba7e5f80281ce1184 Signed-off-by: Ajit Kumar --- arch/arm64/boot/dts/qcom/sdm429-bg-soc.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/qcom/sdm429-bg-soc.dtsi b/arch/arm64/boot/dts/qcom/sdm429-bg-soc.dtsi index 6ac3d71f82f5..d35f17738438 100644 --- a/arch/arm64/boot/dts/qcom/sdm429-bg-soc.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm429-bg-soc.dtsi @@ -26,6 +26,7 @@ spi_3: spi@78b7000 { /* BLSP1 QUP3*/ status = "ok"; + qcom,shared_ee; qcom,bg-spi { compatible = "qcom,bg-spi"; reg = <0>; From 93f53db46badb35a49515bc7d340a82959c0af23 Mon Sep 17 00:00:00 2001 From: Ajit Kumar Date: Mon, 20 Jul 2020 13:52:56 +0530 Subject: [PATCH 203/592] soc: qcom: bgcom: Use shared_ee property for spi Use shared_ee property for bg spi. Call pm runtime APIs to suspend the spi driver. Change-Id: If670311cddae8fab70a5673b38ec5d5149c4d38b Signed-off-by: Ajit Kumar --- drivers/soc/qcom/bgcom_interface.c | 5 ----- drivers/soc/qcom/bgcom_spi.c | 3 +++ 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/soc/qcom/bgcom_interface.c b/drivers/soc/qcom/bgcom_interface.c index bcb51a249e54..0705bc7ad16d 100644 --- a/drivers/soc/qcom/bgcom_interface.c +++ b/drivers/soc/qcom/bgcom_interface.c @@ -45,7 +45,6 @@ #define MPPS_DOWN_EVENT_TO_BG_TIMEOUT 3000 #define ADSP_DOWN_EVENT_TO_BG_TIMEOUT 3000 -#define SLEEP_FOR_SPI_BUS 2000 enum { SSR_DOMAIN_BG, @@ -401,8 +400,6 @@ static long bg_com_ioctl(struct file *filp, break; case SET_SPI_BUSY: ret = bgcom_set_spi_state(BGCOM_SPI_BUSY); - /* Add sleep for SPI Bus to release*/ - msleep(SLEEP_FOR_SPI_BUS); break; case BG_SOFT_RESET: ret = bg_soft_reset(); @@ -619,8 +616,6 @@ static int ssr_bg_cb(struct notifier_block *this, send_uevent(&bge); break; case SUBSYS_AFTER_SHUTDOWN: - /* Add sleep for SPI Bus to release*/ - msleep(SLEEP_FOR_SPI_BUS); if (dev->pending_bg_twm_wear_load) { /* Load bg-twm-wear */ dev->pending_bg_twm_wear_load = false; diff --git a/drivers/soc/qcom/bgcom_spi.c b/drivers/soc/qcom/bgcom_spi.c index e7993251a4d8..3e77c0c2d95f 100644 --- a/drivers/soc/qcom/bgcom_spi.c +++ b/drivers/soc/qcom/bgcom_spi.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "bgcom.h" #include "bgrsb.h" #include "bgcom_interface.h" @@ -263,7 +264,9 @@ static int bgcom_transfer(void *handle, uint8_t *tx_buf, tx_xfer->rx_buf = rx_buf; tx_xfer->len = txn_len; + pm_runtime_get_sync(bg_spi->spi->controller->dev.parent); ret = spi_sync(spi, &bg_spi->msg1); + pm_runtime_put_sync_suspend(bg_spi->spi->controller->dev.parent); mutex_unlock(&bg_spi->xfer_mutex); if (ret) From b94fd840804caddb3791ab48de2b9a0e21d7f12d Mon Sep 17 00:00:00 2001 From: Anirudh Ghayal Date: Tue, 30 Jun 2020 15:14:17 +0530 Subject: [PATCH 204/592] power: smb5-lib: Report the CURRENT_MAX as 1A in CC-mode Userspace uses the CURRENT_MAX power-supply property to determine the strength of the charger. In CC-mode of operation the main-charger's ICL is configured low and hence the CURRENT_MAX reported is lower attributing it as a weak-charger. Fix this by reporting a fixed value of 1A during CC-mode. Change-Id: Id8745b54c3909d01df69376a823396ea4c94eeb1 Signed-off-by: Anirudh Ghayal --- drivers/power/supply/qcom/qpnp-smb5.c | 2 +- drivers/power/supply/qcom/smb5-lib.c | 19 +++++++++++++++++++ drivers/power/supply/qcom/smb5-lib.h | 2 ++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c index 3903c213c0d3..1446407578be 100644 --- a/drivers/power/supply/qcom/qpnp-smb5.c +++ b/drivers/power/supply/qcom/qpnp-smb5.c @@ -784,7 +784,7 @@ static int smb5_usb_get_prop(struct power_supply *psy, val->intval = get_client_vote(chg->usb_icl_votable, PD_VOTER); break; case POWER_SUPPLY_PROP_CURRENT_MAX: - rc = smblib_get_prop_input_current_settled(chg, val); + rc = smblib_get_prop_input_current_max(chg, val); break; case POWER_SUPPLY_PROP_TYPE: val->intval = POWER_SUPPLY_TYPE_USB_PD; diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c index ea3f74aa578b..1b9d586c2ecd 100644 --- a/drivers/power/supply/qcom/smb5-lib.c +++ b/drivers/power/supply/qcom/smb5-lib.c @@ -1337,6 +1337,7 @@ static int smblib_get_pulse_cnt(struct smb_charger *chg, int *count) #define USBIN_150MA 150000 #define USBIN_500MA 500000 #define USBIN_900MA 900000 +#define USBIN_1000MA 1000000 static int set_sdp_current(struct smb_charger *chg, int icl_ua) { int rc; @@ -3798,6 +3799,24 @@ int smblib_get_prop_input_current_settled(struct smb_charger *chg, return smblib_get_charge_param(chg, &chg->param.icl_stat, &val->intval); } +int smblib_get_prop_input_current_max(struct smb_charger *chg, + union power_supply_propval *val) +{ + int icl_ua = 0, rc; + + rc = smblib_get_charge_param(chg, &chg->param.usb_icl, &icl_ua); + if (rc < 0) + return rc; + + if (is_override_vote_enabled_locked(chg->usb_icl_votable) && + icl_ua < USBIN_1000MA) { + val->intval = USBIN_1000MA; + return 0; + } + + return smblib_get_charge_param(chg, &chg->param.icl_stat, &val->intval); +} + int smblib_get_prop_input_voltage_settled(struct smb_charger *chg, union power_supply_propval *val) { diff --git a/drivers/power/supply/qcom/smb5-lib.h b/drivers/power/supply/qcom/smb5-lib.h index de04a7ab4a06..0a06c4b95e65 100644 --- a/drivers/power/supply/qcom/smb5-lib.h +++ b/drivers/power/supply/qcom/smb5-lib.h @@ -755,6 +755,8 @@ int smblib_get_prop_charger_temp(struct smb_charger *chg, int smblib_get_prop_die_health(struct smb_charger *chg); int smblib_get_prop_smb_health(struct smb_charger *chg); int smblib_get_prop_connector_health(struct smb_charger *chg); +int smblib_get_prop_input_current_max(struct smb_charger *chg, + union power_supply_propval *val); int smblib_set_prop_thermal_overheat(struct smb_charger *chg, int therm_overheat); int smblib_get_skin_temp_status(struct smb_charger *chg); From ea4ce87883efa24f13505aa2eac224019591fa45 Mon Sep 17 00:00:00 2001 From: Venkata Prahlad Valluru Date: Fri, 20 Mar 2020 21:12:30 +0530 Subject: [PATCH 205/592] video: fbdev: msm: add skip-panel-reset dt property When set, will skip panel reset during panel ON and OFF. This is needed for panels with in-cell design, where panel reset will affect touch. Change-Id: I6525379cf18d179b8c820edf7301810b7fdc858d Signed-off-by: Venkata Prahlad Valluru --- Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt | 1 + drivers/video/fbdev/msm/mdss_dsi_panel.c | 8 ++++++++ drivers/video/fbdev/msm/mdss_panel.h | 6 ++++++ 3 files changed, 15 insertions(+) diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt index 2182ade92b46..0752f51238e1 100644 --- a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt +++ b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt @@ -510,6 +510,7 @@ the fps window. in floating state(not LP00 or LP11) to turn on this property. Software turns off PHY pmic power supply, phy ldo and DSI Lane ldo during idle screen (footswitch control off) when this property is enabled. +- qcom,skip-panel-reset: Boolean. when set, will skip panel reset during panel ON/OFF. [[Optional config sub-nodes]] These subnodes provide different configurations for a given same panel. Default configuration can be chosen by specifying phandle of the selected subnode in the qcom,config-select. diff --git a/drivers/video/fbdev/msm/mdss_dsi_panel.c b/drivers/video/fbdev/msm/mdss_dsi_panel.c index f9f41f5aeb62..f7c11f884835 100644 --- a/drivers/video/fbdev/msm/mdss_dsi_panel.c +++ b/drivers/video/fbdev/msm/mdss_dsi_panel.c @@ -411,6 +411,11 @@ int mdss_dsi_panel_reset(struct mdss_panel_data *pdata, int enable) return rc; } + if (pinfo->skip_panel_reset && !pinfo->cont_splash_enabled) { + pr_debug("%s: skip_panel_reset is set\n", __func__); + return 0; + } + pr_debug("%s: enable = %d\n", __func__, enable); if (enable) { @@ -2990,6 +2995,9 @@ static int mdss_panel_parse_dt(struct device_node *np, pinfo->mipi.force_clk_lane_hs = of_property_read_bool(np, "qcom,mdss-dsi-force-clock-lane-hs"); + pinfo->skip_panel_reset = + of_property_read_bool(np, "qcom,mdss-skip-panel-reset"); + rc = mdss_dsi_parse_panel_features(np, ctrl_pdata); if (rc) { pr_err("%s: failed to parse panel features\n", __func__); diff --git a/drivers/video/fbdev/msm/mdss_panel.h b/drivers/video/fbdev/msm/mdss_panel.h index 55bf8c06ec90..2ca1f1f0e632 100644 --- a/drivers/video/fbdev/msm/mdss_panel.h +++ b/drivers/video/fbdev/msm/mdss_panel.h @@ -942,6 +942,12 @@ struct mdss_panel_info { /* stores initial adaptive variable refresh vtotal value */ u32 saved_avr_vtotal; + /* + * Skip panel reset during panel on/off. + * Set for some in-cell panels + */ + bool skip_panel_reset; + /* HDR properties of display panel*/ struct mdss_panel_hdr_properties hdr_properties; From ebb5a21ebd01aba63f03f83c39bd880f49335c05 Mon Sep 17 00:00:00 2001 From: Venkata Prahlad Valluru Date: Mon, 20 Jul 2020 16:48:06 +0530 Subject: [PATCH 206/592] ARM: msm: dts: set skip-panel-reset for AUO 416p panel Panel reset needs to be skipped for this in-cell panel, since panel reset will cause unnecessary touch interrupt. Change-Id: I0e7ebc2894aafa383e07e28ea1c2bfc2fbf015da Signed-off-by: Venkata Prahlad Valluru --- arch/arm64/boot/dts/qcom/sdm429-mdss-panels.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/qcom/sdm429-mdss-panels.dtsi b/arch/arm64/boot/dts/qcom/sdm429-mdss-panels.dtsi index c564239c6988..fe112f060f7d 100644 --- a/arch/arm64/boot/dts/qcom/sdm429-mdss-panels.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm429-mdss-panels.dtsi @@ -45,6 +45,7 @@ qcom,mdss-dsi-panel-status-check-mode = "te_signal_check"; qcom,mdss-dsi-power-off-disable; qcom,mdss-dsi-tear-disable; + qcom,mdss-skip-panel-reset; }; From 9642351d6970c7679b054588d9998e30fbcf8af1 Mon Sep 17 00:00:00 2001 From: Terence Ho Date: Mon, 20 Jul 2020 11:46:56 -0400 Subject: [PATCH 207/592] msm: ais: add ais isp trace Add ais isp trace functions to assist in debugging and performance profiling of camera. Change-Id: If169b22d917e344603ce3c059c2253410ce9a27c Signed-off-by: Terence Ho --- .../media/platform/msm/ais/ais_isp/Makefile | 1 + .../platform/msm/ais/ais_isp/utils/Makefile | 9 + .../msm/ais/ais_isp/utils/ais_isp_trace.c | 16 ++ .../msm/ais/ais_isp/utils/ais_isp_trace.h | 229 ++++++++++++++++++ .../platform/msm/ais/ais_isp/vfe_hw/Makefile | 1 + .../msm/ais/ais_isp/vfe_hw/ais_vfe_core.c | 57 ++++- 6 files changed, 306 insertions(+), 7 deletions(-) create mode 100644 drivers/media/platform/msm/ais/ais_isp/utils/Makefile create mode 100644 drivers/media/platform/msm/ais/ais_isp/utils/ais_isp_trace.c create mode 100644 drivers/media/platform/msm/ais/ais_isp/utils/ais_isp_trace.h diff --git a/drivers/media/platform/msm/ais/ais_isp/Makefile b/drivers/media/platform/msm/ais/ais_isp/Makefile index 96ff9c02a624..277eb8275180 100644 --- a/drivers/media/platform/msm/ais/ais_isp/Makefile +++ b/drivers/media/platform/msm/ais/ais_isp/Makefile @@ -8,5 +8,6 @@ ccflags-y += -Idrivers/media/platform/msm/ais/cam_cdm/ obj-$(CONFIG_MSM_AIS) += csid_hw/ obj-$(CONFIG_MSM_AIS) += vfe_hw/ +obj-$(CONFIG_MSM_AIS) += utils/ obj-$(CONFIG_MSM_AIS) += ais_ife_dev.o diff --git a/drivers/media/platform/msm/ais/ais_isp/utils/Makefile b/drivers/media/platform/msm/ais/ais_isp/utils/Makefile new file mode 100644 index 000000000000..bada56e9bf98 --- /dev/null +++ b/drivers/media/platform/msm/ais/ais_isp/utils/Makefile @@ -0,0 +1,9 @@ +ccflags-y += -Idrivers/media/platform/msm/ais/cam_core +ccflags-y += -Idrivers/media/platform/msm/ais/ais_isp/include +ccflags-y += -Idrivers/media/platform/msm/ais/cam_req_mgr +ccflags-y += -Idrivers/media/platform/msm/ais/cam_smmu/ +ccflags-y += -Idrivers/media/platform/msm/ais/cam_sync +ccflags-y += -Idrivers/media/platform/msm/ais/cam_utils +ccflags-y += -Idrivers/media/platform/msm/ais/cam_cdm/ + +obj-$(CONFIG_MSM_AIS) += ais_isp_trace.o diff --git a/drivers/media/platform/msm/ais/ais_isp/utils/ais_isp_trace.c b/drivers/media/platform/msm/ais/ais_isp/utils/ais_isp_trace.c new file mode 100644 index 000000000000..659acf4b1186 --- /dev/null +++ b/drivers/media/platform/msm/ais/ais_isp/utils/ais_isp_trace.c @@ -0,0 +1,16 @@ +/* Copyright (c) 2020, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +/* Instantiate tracepoints */ +#define CREATE_TRACE_POINTS +#include "ais_isp_trace.h" diff --git a/drivers/media/platform/msm/ais/ais_isp/utils/ais_isp_trace.h b/drivers/media/platform/msm/ais/ais_isp/utils/ais_isp_trace.h new file mode 100644 index 000000000000..e2ff0184306e --- /dev/null +++ b/drivers/media/platform/msm/ais/ais_isp/utils/ais_isp_trace.h @@ -0,0 +1,229 @@ +/* Copyright (c) 2020, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#if !defined(_AIS_ISP_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) +#define _AIS_ISP_TRACE_H + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM camera +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE ais_isp_trace + +#include +#include +#include "ais_isp_hw.h" + +TRACE_EVENT(ais_isp_vfe_irq_activated, + TP_PROTO(uint8_t id, uint32_t status0, uint32_t status1), + TP_ARGS(id, status0, status1), + TP_STRUCT__entry( + __field(uint8_t, id) + __field(uint32_t, status0) + __field(uint32_t, status1) + ), + TP_fast_assign( + __entry->id = id; + __entry->status0 = status0; + __entry->status1 = status1; + ), + TP_printk( + "vfe%d: irq 0x%08x 0x%08x", + __entry->id, + __entry->status0, __entry->status1 + ) +); + +TRACE_EVENT(ais_isp_irq_process, + TP_PROTO(uint8_t id, uint8_t evt, uint8_t state), + TP_ARGS(id, evt, state), + TP_STRUCT__entry( + __field(uint8_t, id) + __field(uint8_t, evt) + __field(uint8_t, state) + ), + TP_fast_assign( + __entry->id = id; + __entry->evt = evt; + __entry->state = state; + ), + TP_printk( + "vfe%d: irq event %d (%d)", + __entry->id, __entry->evt, __entry->state + ) +); + +TRACE_EVENT(ais_isp_vfe_state, + TP_PROTO(uint8_t id, uint8_t path, uint8_t state), + TP_ARGS(id, path, state), + TP_STRUCT__entry( + __field(uint8_t, id) + __field(uint8_t, path) + __field(uint8_t, state) + ), + TP_fast_assign( + __entry->id = id; + __entry->path = path; + __entry->state = state; + ), + TP_printk( + "vfe%d:%d: state %d", + __entry->id, __entry->path, __entry->state + ) +); + +TRACE_EVENT(ais_isp_vfe_sof, + TP_PROTO(uint8_t id, uint8_t path, struct ais_ife_rdi_timestamps *ts, + uint32_t fifo, uint32_t miss), + TP_ARGS(id, path, ts, fifo, miss), + TP_STRUCT__entry( + __field(uint8_t, id) + __field(uint8_t, path) + __field(uint32_t, fifo) + __field(uint32_t, miss) + __field(uint64_t, ts_cur) + __field(uint64_t, ts_prev) + ), + TP_fast_assign( + __entry->id = id; + __entry->path = path; + __entry->fifo = fifo; + __entry->miss = miss; + __entry->ts_cur = ts->cur_sof_ts; + __entry->ts_prev = ts->prev_sof_ts; + ), + TP_printk( + "vfe%d:%d: sof %llu %llu fifo %u miss %u", + __entry->id, __entry->path, __entry->ts_cur, __entry->ts_prev, + __entry->fifo, __entry->miss + ) +); + +TRACE_EVENT(ais_isp_vfe_q_sof, + TP_PROTO(uint8_t id, uint8_t path, uint32_t frame, uint64_t ts), + TP_ARGS(id, path, frame, ts), + TP_STRUCT__entry( + __field(uint8_t, id) + __field(uint8_t, path) + __field(uint32_t, frame) + __field(uint64_t, ts) + ), + TP_fast_assign( + __entry->id = id; + __entry->path = path; + __entry->frame = frame; + __entry->ts = ts; + ), + TP_printk( + "vfe%d:%d: sof %d %llu", + __entry->id, __entry->path, __entry->frame, __entry->ts + ) +); + +TRACE_EVENT(ais_isp_vfe_buf_done, + TP_PROTO(uint8_t id, uint8_t path, uint8_t idx, uint32_t frame, + uint8_t fifo, uint8_t match), + TP_ARGS(id, path, idx, frame, fifo, match), + TP_STRUCT__entry( + __field(uint8_t, id) + __field(uint8_t, path) + __field(uint8_t, idx) + __field(uint32_t, frame) + __field(uint8_t, fifo) + __field(uint8_t, match) + ), + TP_fast_assign( + __entry->id = id; + __entry->path = path; + __entry->idx = idx; + __entry->frame = frame; + __entry->fifo = fifo; + __entry->match = match; + ), + TP_printk( + "vfe%d:%d: buf_done %d (%d fifo %d match %d)", + __entry->id, __entry->path, __entry->idx, __entry->frame, + __entry->fifo, __entry->match + ) +); + +TRACE_EVENT(ais_isp_vfe_enq_buf_hw, + TP_PROTO(uint8_t id, uint8_t path, uint8_t idx, + uint8_t fifo, uint8_t full), + TP_ARGS(id, path, idx, fifo, full), + TP_STRUCT__entry( + __field(uint8_t, id) + __field(uint8_t, path) + __field(uint8_t, idx) + __field(uint8_t, fifo) + __field(uint8_t, full) + ), + TP_fast_assign( + __entry->id = id; + __entry->path = path; + __entry->idx = idx; + __entry->fifo = fifo; + __entry->full = full; + ), + TP_printk( + "vfe%d:%d: enq buf hw %d fifo %d full %d", + __entry->id, __entry->path, __entry->idx, + __entry->fifo, __entry->full + ) +); + +TRACE_EVENT(ais_isp_vfe_enq_req, + TP_PROTO(uint8_t id, uint8_t path, uint8_t idx), + TP_ARGS(id, path, idx), + TP_STRUCT__entry( + __field(uint8_t, id) + __field(uint8_t, path) + __field(uint8_t, idx) + ), + TP_fast_assign( + __entry->id = id; + __entry->path = path; + __entry->idx = idx; + ), + TP_printk( + "vfe%d:%d: enq req %d", + __entry->id, __entry->path, __entry->idx + ) +); + +TRACE_EVENT(ais_isp_vfe_error, + TP_PROTO(uint8_t id, uint8_t path, uint8_t err, uint8_t payload), + TP_ARGS(id, path, err, payload), + TP_STRUCT__entry( + __field(uint8_t, id) + __field(uint8_t, path) + __field(uint8_t, err) + __field(uint8_t, payload) + ), + TP_fast_assign( + __entry->id = id; + __entry->path = path; + __entry->err = err; + __entry->payload = payload; + ), + TP_printk( + "vfe%d:%d: error %d %d", + __entry->id, __entry->path, __entry->err, __entry->payload + ) +); + +#endif /* _AIS_ISP_TRACE_H */ + +/* This part must be outside protection */ +#include diff --git a/drivers/media/platform/msm/ais/ais_isp/vfe_hw/Makefile b/drivers/media/platform/msm/ais/ais_isp/vfe_hw/Makefile index 45f022014a74..81e5b8b88dcd 100644 --- a/drivers/media/platform/msm/ais/ais_isp/vfe_hw/Makefile +++ b/drivers/media/platform/msm/ais/ais_isp/vfe_hw/Makefile @@ -5,6 +5,7 @@ ccflags-y += -Idrivers/media/platform/msm/ais/cam_smmu/ ccflags-y += -Idrivers/media/platform/msm/ais/cam_req_mgr/ ccflags-y += -Idrivers/media/platform/msm/ais/ais_isp ccflags-y += -Idrivers/media/platform/msm/ais/ais_isp/include +ccflags-y += -Idrivers/media/platform/msm/ais/ais_isp/utils ccflags-y += -Idrivers/media/platform/msm/ais/ais_isp/vfe_hw/include ccflags-y += -Idrivers/media/platform/msm/ais/ais_isp/vfe_hw/vfe_bus/include ccflags-y += -Idrivers/media/platform/msm/ais/ais_isp/vfe_hw/vfe_bus diff --git a/drivers/media/platform/msm/ais/ais_isp/vfe_hw/ais_vfe_core.c b/drivers/media/platform/msm/ais/ais_isp/vfe_hw/ais_vfe_core.c index 1321d7dddbd3..f55efb259565 100644 --- a/drivers/media/platform/msm/ais/ais_isp/vfe_hw/ais_vfe_core.c +++ b/drivers/media/platform/msm/ais/ais_isp/vfe_hw/ais_vfe_core.c @@ -20,6 +20,7 @@ #include "ais_vfe_soc.h" #include "ais_vfe_core.h" #include "cam_debug_util.h" +#include "ais_isp_trace.h" /*VFE TOP DEFINITIONS*/ #define AIS_VFE_HW_RESET_HW_AND_REG_VAL 0x00003F9F @@ -715,6 +716,9 @@ static void ais_vfe_q_bufs_to_hw(struct ais_vfe_hw_core_info *core_info, fifo_status = cam_io_r_mb(core_info->mem_base + bus_hw_info->common_reg.addr_fifo_status); is_full = fifo_status & (1 << path); + + trace_ais_isp_vfe_enq_buf_hw(core_info->vfe_idx, path, + vfe_buf->bufIdx, rdi_path->num_buffer_hw_q, is_full); } if (rdi_path->num_buffer_hw_q > MAX_NUM_BUF_SW_FIFOQ_ERR) @@ -791,6 +795,10 @@ static int ais_vfe_cmd_enq_buf(struct ais_vfe_hw_core_info *core_info, vfe_buf->iova_addr += enq_buf->buffer.offset; spin_lock(&rdi_path->buffer_lock); + + trace_ais_isp_vfe_enq_req(core_info->vfe_idx, enq_buf->path, + enq_buf->buffer.idx); + list_add_tail(&vfe_buf->list, &rdi_path->buffer_q); if (rdi_path->state < AIS_ISP_RESOURCE_STATE_STREAMING) @@ -884,15 +892,17 @@ static int ais_vfe_q_sof(struct ais_vfe_hw_core_info *core_info, list_add_tail(&p_sof_info->list, &p_rdi->sof_info_q); p_rdi->num_sof_info_q++; + trace_ais_isp_vfe_q_sof(core_info->vfe_idx, path, + p_sof->frame_cnt, p_sof->cur_sof_hw_ts); CAM_DBG(CAM_ISP, "I%d|R%d|F%llu: sof %llu", - core_info->vfe_idx, path, p_rdi->frame_cnt, + core_info->vfe_idx, path, p_sof->frame_cnt, p_sof_info->cur_sof_hw_ts); } else { rc = -1; CAM_ERR(CAM_ISP, "I%d|R%d|F%llu: free timestamp empty (%d)", - core_info->vfe_idx, path, p_rdi->frame_cnt, + core_info->vfe_idx, path, p_sof->frame_cnt, p_rdi->num_buffer_hw_q); } @@ -936,6 +946,10 @@ static void ais_vfe_handle_sof_rdi(struct ais_vfe_hw_core_info *core_info, } } + trace_ais_isp_vfe_sof(core_info->vfe_idx, path, + &work_data->ts_hw[path], + p_rdi->num_buffer_hw_q, miss_sof); + if (p_rdi->frame_cnt == 1 && prev_sof_hw_ts != 0) { //enq missed first frame sof.sof_ts = work_data->ts; @@ -977,6 +991,10 @@ static void ais_vfe_handle_sof_rdi(struct ais_vfe_hw_core_info *core_info, ais_vfe_q_sof(core_info, path, &sof); } else { + trace_ais_isp_vfe_sof(core_info->vfe_idx, path, + &work_data->ts_hw[path], + p_rdi->num_buffer_hw_q, 0); + CAM_DBG(CAM_ISP, "I%d R%d Flush SOF (%d) HW Q empty", core_info->vfe_idx, path, p_rdi->num_sof_info_q); @@ -995,6 +1013,8 @@ static void ais_vfe_handle_sof_rdi(struct ais_vfe_hw_core_info *core_info, p_rdi->num_sof_info_q = 0; } + trace_ais_isp_vfe_error(core_info->vfe_idx, + path, 1, 0); //send warning core_info->event.type = AIS_IFE_MSG_OUTPUT_WARNING; @@ -1065,6 +1085,9 @@ static int ais_vfe_handle_error( CAM_ERR(CAM_ISP, "IFE%d ERROR on RDIs 0x%x", core_info->vfe_idx, work_data->path); + trace_ais_isp_vfe_error(core_info->vfe_idx, + work_data->path, 0, 0); + top_hw_info = core_info->vfe_hw_info->top_hw_info; bus_hw_info = core_info->vfe_hw_info->bus_hw_info; bus_hw_irq_regs = bus_hw_info->common_reg.irq_reg_info.irq_reg_set; @@ -1146,6 +1169,12 @@ static void ais_vfe_bus_handle_client_frame_done( list_del_init(&vfe_buf->list); --rdi_path->num_buffer_hw_q; + if (last_addr == vfe_buf->iova_addr) + last_addr_match = true; + else + CAM_WARN(CAM_ISP, "IFE%d buf %d did not match addr", + core_info->vfe_idx, vfe_buf->bufIdx); + CAM_DBG(CAM_ISP, "I%d|R%d BUF DQ %d (0x%x) FIFO:%d|0x%x", core_info->vfe_idx, path, vfe_buf->bufIdx, vfe_buf->iova_addr, @@ -1175,6 +1204,12 @@ static void ais_vfe_bus_handle_client_frame_done( cur_sof_hw_ts); + trace_ais_isp_vfe_buf_done(core_info->vfe_idx, path, + vfe_buf->bufIdx, + frame_cnt, + rdi_path->num_buffer_hw_q, + last_addr_match); + core_info->event.u.frame_msg.frame_id = frame_cnt; core_info->event.u.frame_msg.buf_idx = vfe_buf->bufIdx; core_info->event.u.frame_msg.ts = sof_ts; @@ -1183,11 +1218,7 @@ static void ais_vfe_bus_handle_client_frame_done( core_info->event_cb(core_info->event_cb_priv, &core_info->event); - if (last_addr == vfe_buf->iova_addr) - last_addr_match = true; - else - CAM_WARN(CAM_ISP, "IFE%d buf %d did not match addr", - core_info->vfe_idx, vfe_buf->bufIdx); + list_add_tail(&vfe_buf->list, &rdi_path->free_buffer_list); } @@ -1195,6 +1226,8 @@ static void ais_vfe_bus_handle_client_frame_done( CAM_ERR(CAM_ISP, "IFE%d BUF| RDI%d NO MATCH addr 0x%x", core_info->vfe_idx, path, last_addr); + trace_ais_isp_vfe_error(core_info->vfe_idx, path, 1, 1); + //send warning core_info->event.type = AIS_IFE_MSG_OUTPUT_WARNING; core_info->event.path = path; @@ -1222,6 +1255,8 @@ static void ais_vfe_bus_handle_client_frame_done( rdi_path->num_sof_info_q = 0; + trace_ais_isp_vfe_error(core_info->vfe_idx, path, 1, 0); + //send warning core_info->event.type = AIS_IFE_MSG_OUTPUT_WARNING; core_info->event.path = path; @@ -1371,6 +1406,8 @@ static int ais_vfe_process_irq_bh(void *priv, void *data) } work_data = (struct ais_vfe_hw_work_data *)data; + + trace_ais_isp_irq_process(core_info->vfe_idx, work_data->evt_type, 1); CAM_DBG(CAM_ISP, "VFE[%d] event %d", core_info->vfe_idx, work_data->evt_type); @@ -1393,6 +1430,8 @@ static int ais_vfe_process_irq_bh(void *priv, void *data) break; } + trace_ais_isp_irq_process(core_info->vfe_idx, work_data->evt_type, 2); + return rc; } @@ -1417,6 +1456,8 @@ static int ais_vfe_dispatch_irq(struct cam_hw_info *vfe_hw, work_data = (struct ais_vfe_hw_work_data *)task->payload; *work_data = *p_work; + trace_ais_isp_irq_process(core_info->vfe_idx, p_work->evt_type, 0); + task->process_cb = ais_vfe_process_irq_bh; rc = cam_req_mgr_workq_enqueue_task(task, vfe_hw, CRM_TASK_PRIORITY_0); @@ -1444,6 +1485,8 @@ irqreturn_t ais_vfe_irq(int irq_num, void *data) cam_io_w_mb(ife_status[1], core_info->mem_base + AIS_VFE_IRQ_CLEAR1); cam_io_w_mb(0x1, core_info->mem_base + AIS_VFE_IRQ_CMD); + trace_ais_isp_vfe_irq_activated(core_info->vfe_idx, + ife_status[0], ife_status[1]); CAM_DBG(CAM_ISP, "VFE%d irq status 0x%x 0x%x", core_info->vfe_idx, ife_status[0], ife_status[1]); From 69b86fdf7b5139842c4b3fca2de784f1e443d553 Mon Sep 17 00:00:00 2001 From: Sunil Paidimarri Date: Thu, 9 Jul 2020 21:21:04 -0700 Subject: [PATCH 208/592] net: stmmac: Add check for HWTSTAMP_FILTER_ALL filter -HWTSTAMP_FILTER_ALL with ipa enabled not supported. -Add check for above condition to avoid crash. Change-Id: I443122489aa257be5208bdf6260b2b3a9c8096c1 Acked-by: Ning Cai Signed-off-by: Sunil Paidimarri --- drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 8 ++++++++ drivers/net/ethernet/stmicro/stmmac/stmmac.h | 1 + drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 7 +++++++ 3 files changed, 16 insertions(+) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index b54efdad26d5..da5c40c74ed2 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -1768,6 +1768,14 @@ static int ethqos_set_early_eth_param(struct stmmac_priv *priv, return ret; } +bool qcom_ethqos_ipa_enabled(void) +{ +#ifdef CONFIG_ETH_IPA_OFFLOAD + return pethqos->ipa_enabled; +#endif + return false; +} + static int qcom_ethqos_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index 58ccbf8386ea..1d6802ea1b50 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -194,5 +194,6 @@ int stmmac_dvr_probe(struct device *device, struct stmmac_resources *res); void stmmac_disable_eee_mode(struct stmmac_priv *priv); bool stmmac_eee_init(struct stmmac_priv *priv); +bool qcom_ethqos_ipa_enabled(void); #endif /* __STMMAC_H__ */ diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 828c0d62c43a..8a1a05b60e97 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -539,6 +539,13 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr) sizeof(struct hwtstamp_config))) return -EFAULT; + if (qcom_ethqos_ipa_enabled() && + config.rx_filter == HWTSTAMP_FILTER_ALL) { + netdev_alert(priv->dev, + "No hw timestamping since ipa is enabled\n"); + return -EOPNOTSUPP; + } + netdev_dbg(priv->dev, "%s config flags:0x%x, tx_type:0x%x, rx_filter:0x%x\n", __func__, config.flags, config.tx_type, config.rx_filter); From c5b4824b8839cf3e5ae0f545a61e1a004b82cebb Mon Sep 17 00:00:00 2001 From: Ajay Agarwal Date: Tue, 21 Jul 2020 12:02:43 +0530 Subject: [PATCH 209/592] usb: misc: mdm_data_bridge: Add missing check for single interface Add missing check to fail probe if 900E diag device is attached. Change-Id: I3f70b873c5bc0c835fe9dfbb5e1525ba23c1473b Signed-off-by: Ajay Agarwal --- drivers/usb/misc/mdm_data_bridge.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/usb/misc/mdm_data_bridge.c b/drivers/usb/misc/mdm_data_bridge.c index 9bd5a1f00d3f..3cc96fa06628 100644 --- a/drivers/usb/misc/mdm_data_bridge.c +++ b/drivers/usb/misc/mdm_data_bridge.c @@ -863,6 +863,12 @@ bridge_probe(struct usb_interface *iface, const struct usb_device_id *id) return -EINVAL; } + if (devid == USB_BRIDGE_DIAG && + udev->actconfig->desc.bNumInterfaces == 1) { + pr_err("Invalid configuration: Only one interface\n"); + return -EINVAL; + } + num_eps = iface->cur_altsetting->desc.bNumEndpoints; for (i = 0; i < num_eps; i++) { endpoint = iface->cur_altsetting->endpoint + i; From b14c619e79d1bfc076a2585bbda1395f288ec3f8 Mon Sep 17 00:00:00 2001 From: Ashish Kori Date: Wed, 17 Jun 2020 20:00:23 +0530 Subject: [PATCH 210/592] ARM: dts: msm: Add core/core2x clk for SSC QUP Add core/core2x clock and SSC QUP sub system name for SA6155, SA8155 and SA8195 to enable SSR feature and add status field to QUP node. Change-Id: I7b198c4eb7bcd7347a879b359a9290e4dc7f97b5 Signed-off-by: Ashish Kori --- arch/arm64/boot/dts/qcom/sa6155-adp-air.dtsi | 4 ++++ arch/arm64/boot/dts/qcom/sa6155-adp-star.dtsi | 4 ++++ arch/arm64/boot/dts/qcom/sa8155-adp-common.dtsi | 4 ++++ arch/arm64/boot/dts/qcom/sa8195p-adp-common.dtsi | 4 ++++ arch/arm64/boot/dts/qcom/sdmshrike-qupv3.dtsi | 10 +++++++++- arch/arm64/boot/dts/qcom/sm6150-qupv3.dtsi | 9 ++++++++- arch/arm64/boot/dts/qcom/sm8150-qupv3.dtsi | 8 ++++++++ 7 files changed, 41 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sa6155-adp-air.dtsi b/arch/arm64/boot/dts/qcom/sa6155-adp-air.dtsi index 4b73b902333b..3f9013f63bd8 100644 --- a/arch/arm64/boot/dts/qcom/sa6155-adp-air.dtsi +++ b/arch/arm64/boot/dts/qcom/sa6155-adp-air.dtsi @@ -13,6 +13,10 @@ #include #include "sa6155-cnss.dtsi" +&qupv3_2 { + status = "ok"; +}; + &bluetooth_ext { status = "ok"; }; diff --git a/arch/arm64/boot/dts/qcom/sa6155-adp-star.dtsi b/arch/arm64/boot/dts/qcom/sa6155-adp-star.dtsi index 1ecae102b065..ab3647ea3828 100644 --- a/arch/arm64/boot/dts/qcom/sa6155-adp-star.dtsi +++ b/arch/arm64/boot/dts/qcom/sa6155-adp-star.dtsi @@ -13,6 +13,10 @@ #include #include "sa6155-cnss.dtsi" +&qupv3_2 { + status = "ok"; +}; + &bluetooth_ext { status = "ok"; }; diff --git a/arch/arm64/boot/dts/qcom/sa8155-adp-common.dtsi b/arch/arm64/boot/dts/qcom/sa8155-adp-common.dtsi index 9f47fd1779ee..a51e041d6ac6 100644 --- a/arch/arm64/boot/dts/qcom/sa8155-adp-common.dtsi +++ b/arch/arm64/boot/dts/qcom/sa8155-adp-common.dtsi @@ -16,6 +16,10 @@ #include "sa8155-pmic-overlay.dtsi" #include "sa8155-cnss.dtsi" +&qupv3_3 { + status = "ok"; +}; + &qupv3_se0_spi { status = "ok"; diff --git a/arch/arm64/boot/dts/qcom/sa8195p-adp-common.dtsi b/arch/arm64/boot/dts/qcom/sa8195p-adp-common.dtsi index f4cb5d816cef..4ded57fd707b 100644 --- a/arch/arm64/boot/dts/qcom/sa8195p-adp-common.dtsi +++ b/arch/arm64/boot/dts/qcom/sa8195p-adp-common.dtsi @@ -14,6 +14,10 @@ #include #include "sa8195p-cnss.dtsi" +&qupv3_3 { + status = "ok"; +}; + &qupv3_se0_spi { status = "ok"; diff --git a/arch/arm64/boot/dts/qcom/sdmshrike-qupv3.dtsi b/arch/arm64/boot/dts/qcom/sdmshrike-qupv3.dtsi index f942b85415e7..d6eb08d068d1 100644 --- a/arch/arm64/boot/dts/qcom/sdmshrike-qupv3.dtsi +++ b/arch/arm64/boot/dts/qcom/sdmshrike-qupv3.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -29,6 +29,7 @@ qcom,bus-mas-id = ; qcom,bus-slv-id = ; qcom,iommu-s1-bypass; + status = "ok"; iommu_qupv3_0_geni_se_cb: qcom,iommu_qupv3_0_geni_se_cb { compatible = "qcom,qupv3-geni-se-cb"; @@ -348,6 +349,7 @@ qcom,bus-mas-id = ; qcom,bus-slv-id = ; qcom,iommu-s1-bypass; + status = "ok"; iommu_qupv3_1_geni_se_cb: qcom,iommu_qupv3_1_geni_se_cb { compatible = "qcom,qupv3-geni-se-cb"; @@ -616,6 +618,7 @@ qcom,bus-mas-id = ; qcom,bus-slv-id = ; qcom,iommu-s1-bypass; + status = "ok"; iommu_qupv3_2_geni_se_cb: qcom,iommu_qupv3_2_geni_se_cb { compatible = "qcom,qupv3-geni-se-cb"; @@ -871,6 +874,11 @@ qcom,bus-mas-id = ; qcom,bus-slv-id = ; qcom,iommu-s1-bypass; + qcom,subsys-name = "slpi"; + clock-names = "corex", "core2x"; + clocks = <&clock_scc SCC_QUPV3_CORE_CLK>, + <&clock_scc SCC_QUPV3_2XCORE_CLK>; + status = "disabled"; iommu_qupv3_3_geni_se_cb: qcom,iommu_qupv3_3_geni_se_cb { compatible = "qcom,qupv3-geni-se-cb"; diff --git a/arch/arm64/boot/dts/qcom/sm6150-qupv3.dtsi b/arch/arm64/boot/dts/qcom/sm6150-qupv3.dtsi index cc6dd19ab227..4a013abe62e3 100644 --- a/arch/arm64/boot/dts/qcom/sm6150-qupv3.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6150-qupv3.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -32,6 +32,7 @@ qcom,bus-mas-id = ; qcom,bus-slv-id = ; qcom,iommu-s1-bypass; + status = "ok"; iommu_qupv3_0_geni_se_cb: qcom,iommu_qupv3_0_geni_se_cb { compatible = "qcom,qupv3-geni-se-cb"; @@ -147,6 +148,7 @@ qcom,bus-mas-id = ; qcom,bus-slv-id = ; qcom,iommu-s1-bypass; + status = "ok"; iommu_qupv3_1_geni_se_cb: qcom,iommu_qupv3_1_geni_se_cb { compatible = "qcom,qupv3-geni-se-cb"; @@ -350,6 +352,11 @@ qcom,bus-mas-id = ; qcom,bus-slv-id = ; qcom,iommu-s1-bypass; + qcom,subsys-name = "adsp"; + clock-names = "corex", "core2x"; + clocks = <&clock_scc SCC_QUPV3_CORE_CLK>, + <&clock_scc SCC_QUPV3_2XCORE_CLK>; + status = "disabled"; iommu_qupv3_2_geni_se_cb: qcom,iommu_qupv3_2_geni_se_cb { compatible = "qcom,qupv3-geni-se-cb"; diff --git a/arch/arm64/boot/dts/qcom/sm8150-qupv3.dtsi b/arch/arm64/boot/dts/qcom/sm8150-qupv3.dtsi index 90d7d8d911ec..99045e871fd0 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-qupv3.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-qupv3.dtsi @@ -20,6 +20,7 @@ qcom,bus-mas-id = ; qcom,bus-slv-id = ; qcom,iommu-s1-bypass; + status = "ok"; iommu_qupv3_0_geni_se_cb: qcom,iommu_qupv3_0_geni_se_cb { compatible = "qcom,qupv3-geni-se-cb"; @@ -385,6 +386,7 @@ qcom,bus-mas-id = ; qcom,bus-slv-id = ; qcom,iommu-s1-bypass; + status = "ok"; iommu_qupv3_1_geni_se_cb: qcom,iommu_qupv3_1_geni_se_cb { compatible = "qcom,qupv3-geni-se-cb"; @@ -713,6 +715,7 @@ qcom,bus-mas-id = ; qcom,bus-slv-id = ; qcom,iommu-s1-bypass; + status = "ok"; iommu_qupv3_2_geni_se_cb: qcom,iommu_qupv3_2_geni_se_cb { compatible = "qcom,qupv3-geni-se-cb"; @@ -981,6 +984,11 @@ qcom,bus-mas-id = ; qcom,bus-slv-id = ; qcom,iommu-s1-bypass; + qcom,subsys-name = "slpi"; + clock-names = "corex", "core2x"; + clocks = <&clock_scc SCC_QUPV3_CORE_CLK>, + <&clock_scc SCC_QUPV3_2XCORE_CLK>; + status = "disabled"; iommu_qupv3_3_geni_se_cb: qcom,iommu_qupv3_3_geni_se_cb { compatible = "qcom,qupv3-geni-se-cb"; From f62b4c27d0dff964daf444e0b87eff8ccc50b40b Mon Sep 17 00:00:00 2001 From: Pratham Pratap Date: Thu, 2 Jul 2020 16:19:01 +0530 Subject: [PATCH 211/592] usb: phy: snps: Enable auto-resume during host mode bus suspend Currently driver is enabling auto-resume irrespective of whether peripheral is connected to the host or not. Adding PHY flags before enabling auto-resume ensures that some peripheral must have been connected before bus suspend. This change enables auto-resume only during host mode real bus suspend. Change-Id: Ifed2f0a773ace31738628a988062f96e92efad44 Signed-off-by: Pratham Pratap --- drivers/usb/phy/phy-msm-snps-hs.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/usb/phy/phy-msm-snps-hs.c b/drivers/usb/phy/phy-msm-snps-hs.c index 913c612c2abd..2bb473d2409b 100644 --- a/drivers/usb/phy/phy-msm-snps-hs.c +++ b/drivers/usb/phy/phy-msm-snps-hs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -515,9 +515,17 @@ static int msm_hsphy_set_suspend(struct usb_phy *uphy, int suspend) } if (suspend) { /* Bus suspend */ - if (phy->cable_connected) { - /* Enable auto-resume functionality by pulsing signal */ - if (phy->phy.flags & PHY_HOST_MODE) { + if (phy->cable_connected || + (phy->phy.flags & PHY_HOST_MODE)) { + /* Enable auto-resume functionality only when + * there is some peripheral connected and real + * bus suspend happened + */ + if ((phy->phy.flags & PHY_HSFS_MODE) || + (phy->phy.flags & PHY_LS_MODE)) { + /* Enable auto-resume functionality by pulsing + * signal + */ msm_usb_write_readback(phy->base, USB2_PHY_USB_PHY_HS_PHY_CTRL2, USB2_AUTO_RESUME, USB2_AUTO_RESUME); From aec4625ec11ad8675d8796fa13285fd83ccfd703 Mon Sep 17 00:00:00 2001 From: Rajeev Nandan Date: Fri, 5 Jun 2020 10:33:40 +0530 Subject: [PATCH 212/592] dt-bindings: add clock_pre extend enable panel property This change adds the documentation for a new panel property qcom,mdss-dsi-t-clk-pre-extend, that makes clock_pre extend enable configurable. Change-Id: I8daed96c9a31bfba0faeb63ca42c9221537fee80 Signed-off-by: Rajeev Nandan --- Documentation/devicetree/bindings/drm/msm/mdss-dsi-panel.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/drm/msm/mdss-dsi-panel.txt b/Documentation/devicetree/bindings/drm/msm/mdss-dsi-panel.txt index 8ee87ab2f31c..0a2acb56088d 100644 --- a/Documentation/devicetree/bindings/drm/msm/mdss-dsi-panel.txt +++ b/Documentation/devicetree/bindings/drm/msm/mdss-dsi-panel.txt @@ -265,6 +265,8 @@ Optional properties: 0x00 = default value. - qcom,mdss-dsi-t-clk-pre: Specifies the byte clock cycles before mode switch. 0x00 = default value. +- qcom,mdss-dsi-t-clk-pre-extend: Boolean that specifies whether to enable t_clk_pre counter + increment by 2 byteclk. - qcom,mdss-dsi-stream: Specifies the packet stream to be used. 0 = stream 0 (default) 1 = stream 1 @@ -660,6 +662,7 @@ Example: qcom,lanes-per-sublink = <2>; qcom,mdss-dsi-t-clk-post = <0x20>; qcom,mdss-dsi-t-clk-pre = <0x2c>; + qcom,mdss-dsi-t-clk-pre-extend; qcom,mdss-dsi-stream = <0>; qcom,mdss-dsi-mdp-trigger = <0>; qcom,mdss-dsi-dma-trigger = <0>; From 29703850fb195c50aff4e024c53382927ea6f0f1 Mon Sep 17 00:00:00 2001 From: Chandrasekhar Mattaparthy Date: Tue, 21 Jul 2020 19:22:27 +0530 Subject: [PATCH 213/592] ARM: dts: msm: Add DVT-2 support for APQ hardware Modify subtype to correct version for APQ h/w. Change-Id: I85391bccd4088acdaaa984ad4c5f8e9ae840b7ba Signed-off-by: Chandrasekhar Mattaparthy --- arch/arm64/boot/dts/qcom/sda429-bg-dvt2-wtp-overlay.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/sda429-bg-dvt2-wtp-overlay.dts b/arch/arm64/boot/dts/qcom/sda429-bg-dvt2-wtp-overlay.dts index 03c3a00fa5ad..97fc1bdc5cfa 100644 --- a/arch/arm64/boot/dts/qcom/sda429-bg-dvt2-wtp-overlay.dts +++ b/arch/arm64/boot/dts/qcom/sda429-bg-dvt2-wtp-overlay.dts @@ -21,7 +21,7 @@ model = "Qualcomm Technologies, Inc. SDA429 QRD BG WTP Overlay"; compatible = "qcom,sdm429w-qrd", "qcom,sdm429w", "qcom,qrd"; qcom,msm-id = <437 0x0>; - qcom,board-id = <0x00010b 8>; + qcom,board-id = <0x00010b 0xA>; qcom,pmic-id = <0x0002001b 0x0 0x0 0x0>; }; From c242f1866e7e0b8a75059d37d8ae4862570d744e Mon Sep 17 00:00:00 2001 From: Venkata Rao Kakani Date: Tue, 21 Jul 2020 12:48:28 +0530 Subject: [PATCH 214/592] init: early_services: get status after launching early services Get early services mount status only after launching it. Change-Id: If3e4784ce4824f9c592c0900aa1cbf51b9093ab4 Signed-off-by: Venkata Rao Kakani --- init/main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/init/main.c b/init/main.c index 22f1c5b9e8e5..e2294e865a6b 100644 --- a/init/main.c +++ b/init/main.c @@ -1022,7 +1022,7 @@ static int __ref kernel_init(void *unused) { int ret; #ifdef CONFIG_EARLY_SERVICES - int status = get_early_services_status(); + int status = 0; #endif kernel_init_freeable(); /* need to finish all async __init code before freeing the memory */ @@ -1037,6 +1037,7 @@ static int __ref kernel_init(void *unused) place_marker("M - DRIVER Kernel Boot Done"); #ifdef CONFIG_EARLY_SERVICES + status = get_early_services_status(); if (status) { struct kstat stat; /* Wait for early services SE policy load completion signal */ From 7bcf0d2b71497daf1351c67484be01184f842349 Mon Sep 17 00:00:00 2001 From: Rajeev Nandan Date: Fri, 5 Jun 2020 10:06:43 +0530 Subject: [PATCH 215/592] drm/msm/dsi-staging: fix t_clk_pre in high dsi clock use case The t_clk_pre extend register used to configure the resolution of the t_clk_pre setting. Without this set, the duration of the t_clk_pre would be half of what is needed. This change adds the provision to configure this register. Change-Id: Iac12ac3da949e042fd560fa3945a97555d1283e6 Signed-off-by: Rajeev Nandan --- drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c | 8 ++++++++ drivers/gpu/drm/msm/dsi-staging/dsi_defs.h | 3 +++ drivers/gpu/drm/msm/dsi-staging/dsi_panel.c | 3 +++ 3 files changed, 14 insertions(+) diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c index a7b79708a848..655f1f5875e5 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c @@ -102,6 +102,14 @@ void dsi_ctrl_hw_cmn_host_setup(struct dsi_ctrl_hw *ctrl, dsi_setup_trigger_controls(ctrl, cfg); dsi_split_link_setup(ctrl, cfg); + /* Setup T_CLK_PRE extend register */ + reg_value = DSI_R32(ctrl, DSI_TEST_PATTERN_GEN_VIDEO_ENABLE); + if (cfg->t_clk_pre_extend) + reg_value |= BIT(0); + else + reg_value &= ~BIT(0); + DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_VIDEO_ENABLE, reg_value); + /* Setup clocking timing controls */ reg_value = ((cfg->t_clk_post & 0x3F) << 8); reg_value |= (cfg->t_clk_pre & 0x3F); diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h b/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h index 4cc58112f8f8..9e54f78449ef 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h @@ -478,6 +478,8 @@ struct dsi_split_link_config { * @t_clk_pre: Number of byte clock cycles that the high spped clock * shall be driven prior to data lane transitions from LP * to HS mode. + * @t_clk_pre_extend: Increment t_clk_pre counter by 2 byteclk if set to + * true, otherwise increment by 1 byteclk. * @ignore_rx_eot: Ignore Rx EOT packets if set to true. * @append_tx_eot: Append EOT packets for forward transmissions if set to * true. @@ -505,6 +507,7 @@ struct dsi_host_common_cfg { bool bit_swap_blue; u32 t_clk_post; u32 t_clk_pre; + bool t_clk_pre_extend; bool ignore_rx_eot; bool append_tx_eot; u32 ext_bridge_num; diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c index dcdcd45c7648..eb59c1cb7ca0 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c @@ -1212,6 +1212,9 @@ static int dsi_panel_parse_misc_host_config(struct dsi_host_common_cfg *host, pr_debug("[%s] t_clk_pre = %d\n", name, val); } + host->t_clk_pre_extend = utils->read_bool(utils->data, + "qcom,mdss-dsi-t-clk-pre-extend"); + host->ignore_rx_eot = utils->read_bool(utils->data, "qcom,mdss-dsi-rx-eot-ignore"); From 2726e8a0b8c0db0e97caea09ddaff3925392d32f Mon Sep 17 00:00:00 2001 From: Venkata Prahlad Valluru Date: Fri, 17 Jul 2020 18:56:54 +0530 Subject: [PATCH 216/592] ARM: dts: qcom: add display nodes for SDA429w devices Add display nodes for WTP and DVT2 devices. Change-Id: I74a727135e7479815712184360b5f0238aaef73c Signed-off-by: Venkata Prahlad Valluru --- .../dts/qcom/sda429-bg-dvt2-wtp-overlay.dts | 53 +++++++++++++++++++ .../boot/dts/qcom/sda429-wtp-overlay.dts | 53 +++++++++++++++++++ 2 files changed, 106 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sda429-bg-dvt2-wtp-overlay.dts b/arch/arm64/boot/dts/qcom/sda429-bg-dvt2-wtp-overlay.dts index 03c3a00fa5ad..8546cbbe9f88 100644 --- a/arch/arm64/boot/dts/qcom/sda429-bg-dvt2-wtp-overlay.dts +++ b/arch/arm64/boot/dts/qcom/sda429-bg-dvt2-wtp-overlay.dts @@ -16,6 +16,7 @@ #include #include "sda429-bg-dvt2-wtp.dtsi" +#include "sdm429-mdss-panels.dtsi" / { model = "Qualcomm Technologies, Inc. SDA429 QRD BG WTP Overlay"; @@ -25,6 +26,58 @@ qcom,pmic-id = <0x0002001b 0x0 0x0 0x0>; }; +&mdss_mdp { + qcom,mdss-pref-prim-intf = "dsi"; +}; + +&mdss_dsi { + /delete-property/ vdda-supply; + /delete-property/ vddio-supply; + vdda-supply = <&L6A>; /* 0.8v */ + vddio-supply = <&L13A>; /* 1.8v */ + + qcom,ctrl-supply-entries { + #address-cells = <1>; + #size-cells = <0>; + + qcom,ctrl-supply-entry@0 { + reg = <0>; + qcom,supply-name = "vdda"; + qcom,supply-min-voltage = <800000>; + qcom,supply-max-voltage = <800000>; + qcom,supply-enable-load = <100000>; + qcom,supply-disable-load = <100>; + qcom,supply-post-on-sleep = <20>; + }; + }; +}; + +&mdss_dsi0 { + qcom,dsi-pref-prim-pan = <&dsi_auo_416p_amoled_cmd>; + /delete-property/ vdd-supply; + pinctrl-names = "mdss_default", "mdss_sleep"; + pinctrl-0 = <&mdss_te_active>; + pinctrl-1 = <&mdss_te_suspend>; + vddio-supply = <&L11A>; + qcom,platform-te-gpio = <&tlmm 24 0>; + qcom,platform-reset-gpio = <&tlmm 60 0>; + qcom,platform-enable-gpio = <&pm660_gpios 12 0>; + +}; + +&mdss_dsi0_pll { + /delete-property/ vddio-supply; + vddio-supply = <&L13A>; +}; + +&mdss_dsi1 { + status = "disabled"; +}; + +&mdss_dsi1_pll { + status = "disabled"; +}; + &i2c_4 { status = "ok"; diff --git a/arch/arm64/boot/dts/qcom/sda429-wtp-overlay.dts b/arch/arm64/boot/dts/qcom/sda429-wtp-overlay.dts index 7bbdfa9ae059..aa6d7612dd96 100644 --- a/arch/arm64/boot/dts/qcom/sda429-wtp-overlay.dts +++ b/arch/arm64/boot/dts/qcom/sda429-wtp-overlay.dts @@ -16,6 +16,7 @@ #include #include "sda429-wtp.dtsi" +#include "sdm429-mdss-panels.dtsi" / { model = "Qualcomm Technologies, Inc. SDA429 QRD BG WTP Overlay"; @@ -25,6 +26,58 @@ qcom,pmic-id = <0x0002001b 0x0 0x0 0x0>; }; +&mdss_mdp { + qcom,mdss-pref-prim-intf = "dsi"; +}; + +&mdss_dsi { + /delete-property/ vdda-supply; + /delete-property/ vddio-supply; + vdda-supply = <&L6A>; /* 0.8v */ + vddio-supply = <&L13A>; /* 1.8v */ + + qcom,ctrl-supply-entries { + #address-cells = <1>; + #size-cells = <0>; + + qcom,ctrl-supply-entry@0 { + reg = <0>; + qcom,supply-name = "vdda"; + qcom,supply-min-voltage = <800000>; + qcom,supply-max-voltage = <800000>; + qcom,supply-enable-load = <100000>; + qcom,supply-disable-load = <100>; + qcom,supply-post-on-sleep = <20>; + }; + }; +}; + +&mdss_dsi0 { + qcom,dsi-pref-prim-pan = <&dsi_auo_416p_amoled_cmd>; + /delete-property/ vdd-supply; + pinctrl-names = "mdss_default", "mdss_sleep"; + pinctrl-0 = <&mdss_te_active>; + pinctrl-1 = <&mdss_te_suspend>; + vddio-supply = <&L11A>; + qcom,platform-te-gpio = <&tlmm 24 0>; + qcom,platform-reset-gpio = <&tlmm 60 0>; + qcom,platform-enable-gpio = <&pm660_gpios 12 0>; + +}; + +&mdss_dsi0_pll { + /delete-property/ vddio-supply; + vddio-supply = <&L13A>; +}; + +&mdss_dsi1 { + status = "disabled"; +}; + +&mdss_dsi1_pll { + status = "disabled"; +}; + &i2c_4 { status = "ok"; From ab2598ec8fa56b999a4d224490d028d01183f0e6 Mon Sep 17 00:00:00 2001 From: wadesong Date: Wed, 22 Jul 2020 08:53:11 +0800 Subject: [PATCH 217/592] cfg80211: Indicate backport support for sband iftype data Add a new macro CFG80211_SBAND_IFTYPE_DATA_BACKPORT to indicate the fact that sband iftype data has been supported for HE phy capabilities. Change-Id: I4cc333199308255f5795d9aa96739e05df9f209a Signed-off-by: Wade Song --- include/net/cfg80211.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 9866157b52fc..cf0b6f9eff56 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -65,6 +65,9 @@ /* Indicate backport support for key configuration for Beacon protection*/ #define CFG80211_BIGTK_CONFIGURATION_SUPPORT 1 +/* Indicate backport support for sband iftype data */ +#define CFG80211_SBAND_IFTYPE_DATA_BACKPORT 1 + /** * DOC: Introduction * From 48e332bcde64295b8323c5b65d3591188a65ee31 Mon Sep 17 00:00:00 2001 From: Yunyun Cao Date: Wed, 22 Jul 2020 10:12:06 +0800 Subject: [PATCH 218/592] msm: ais: remove unnecessary writing to csid rdi cfg0 register Remove unnecessary writing to csid rdi cfg0 register to avoid unknown hardware behavior. Change-Id: I2435f3b448e817cd33d838e0716718c83eedc3ca Signed-off-by: Yunyun Cao --- .../ais/ais_isp/csid_hw/ais_ife_csid_core.c | 32 +++++++------------ 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/drivers/media/platform/msm/ais/ais_isp/csid_hw/ais_ife_csid_core.c b/drivers/media/platform/msm/ais/ais_isp/csid_hw/ais_ife_csid_core.c index eaf983776cb0..77b0e1905d49 100644 --- a/drivers/media/platform/msm/ais/ais_isp/csid_hw/ais_ife_csid_core.c +++ b/drivers/media/platform/msm/ais/ais_isp/csid_hw/ais_ife_csid_core.c @@ -577,24 +577,6 @@ static int ais_ife_csid_config_rdi_path( else path_cfg->pix_enable = true; - /* - * RDI path config and enable the time stamp capture - * Enable the measurement blocks - */ - cfg0 = (path_cfg->vc << csid_reg->cmn_reg->vc_shift_val) | - (path_cfg->dt << csid_reg->cmn_reg->dt_shift_val) | - (path_cfg->cid << csid_reg->cmn_reg->dt_id_shift_val) | - (path_cfg->decode_fmt << csid_reg->cmn_reg->fmt_shift_val) | - (path_cfg->plain_fmt << csid_reg->cmn_reg->plain_fmt_shit_val) | - (path_cfg->crop_enable << - csid_reg->cmn_reg->crop_h_en_shift_val) | - (path_cfg->crop_enable << - csid_reg->cmn_reg->crop_v_en_shift_val) | - (1 << 2) | 3; - - cam_io_w_mb(cfg0, soc_info->reg_map[0].mem_base + - csid_reg->rdi_reg[id]->csid_rdi_cfg0_addr); - /* select the post irq sub sample strobe for time stamp capture */ cam_io_w_mb(CSID_TIMESTAMP_STB_POST_IRQ, soc_info->reg_map[0].mem_base + csid_reg->rdi_reg[id]->csid_rdi_cfg1_addr); @@ -701,8 +683,18 @@ static int ais_ife_csid_config_rdi_path( } } - /* Enable the path */ - cfg0 |= (1 << csid_reg->cmn_reg->path_en_shift_val); + /* RDI path config and enable*/ + cfg0 = (path_cfg->vc << csid_reg->cmn_reg->vc_shift_val) | + (path_cfg->dt << csid_reg->cmn_reg->dt_shift_val) | + (path_cfg->cid << csid_reg->cmn_reg->dt_id_shift_val) | + (path_cfg->decode_fmt << csid_reg->cmn_reg->fmt_shift_val) | + (path_cfg->plain_fmt << csid_reg->cmn_reg->plain_fmt_shit_val) | + (path_cfg->crop_enable << + csid_reg->cmn_reg->crop_h_en_shift_val) | + (path_cfg->crop_enable << + csid_reg->cmn_reg->crop_v_en_shift_val) | + (1 << csid_reg->cmn_reg->path_en_shift_val) | + (1 << 2) | 3; cam_io_w_mb(cfg0, soc_info->reg_map[0].mem_base + csid_reg->rdi_reg[id]->csid_rdi_cfg0_addr); From 6322156964a43ec96c7e1f06153726bf090cb42b Mon Sep 17 00:00:00 2001 From: Bhaumik Bhatt Date: Thu, 16 Jan 2020 16:21:16 -0800 Subject: [PATCH 219/592] mhi: core: do not toggle PCIe low power mode in sleeping context Do not toggle PCIe low power mode in sleeping context as the calls can grab a mutex. Change-Id: I12eed6a01d80b36412ec3e18af382a031a9d108d Signed-off-by: Bhaumik Bhatt --- drivers/bus/mhi/core/mhi_main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/bus/mhi/core/mhi_main.c b/drivers/bus/mhi/core/mhi_main.c index e4c3e1fceebe..703df0e16cba 100644 --- a/drivers/bus/mhi/core/mhi_main.c +++ b/drivers/bus/mhi/core/mhi_main.c @@ -2603,6 +2603,7 @@ int mhi_get_remote_time_sync(struct mhi_device *mhi_dev, ret = -EIO; goto error_invalid_state; } + read_unlock_bh(&mhi_cntrl->pm_lock); /* disable link level low power modes */ ret = mhi_cntrl->lpm_disable(mhi_cntrl, mhi_cntrl->priv_data); @@ -2625,6 +2626,7 @@ int mhi_get_remote_time_sync(struct mhi_device *mhi_dev, mhi_cntrl->lpm_enable(mhi_cntrl, mhi_cntrl->priv_data); + read_lock_bh(&mhi_cntrl->pm_lock); error_invalid_state: mhi_cntrl->wake_put(mhi_cntrl, false); read_unlock_bh(&mhi_cntrl->pm_lock); From 68059c75d4719a64911c457b047a767e4784339b Mon Sep 17 00:00:00 2001 From: Vipin Deep Kaur Date: Wed, 8 Jul 2020 13:00:58 +0530 Subject: [PATCH 220/592] spi: spi-geni-qcom: Return error if setup transfer fails setup_fifo_xfer/setup_gsi_xfer api may fail while transfer preparation, return error to the client in such case instead of advancing with the erroneous transfer to prevent unpredictable transfer scenarios. Change-Id: Ic02285df53713c813b56d88ad4d6731ace72d54a Signed-off-by: Vipin Deep Kaur --- drivers/spi/spi-geni-qcom.c | 40 +++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c index 7508a4ba90ee..efb1fe9da703 100644 --- a/drivers/spi/spi-geni-qcom.c +++ b/drivers/spi/spi-geni-qcom.c @@ -1070,10 +1070,11 @@ static int spi_geni_unprepare_transfer_hardware(struct spi_master *spi) return 0; } -static void setup_fifo_xfer(struct spi_transfer *xfer, +static int setup_fifo_xfer(struct spi_transfer *xfer, struct spi_geni_master *mas, u16 mode, struct spi_master *spi) { + int ret = 0; u32 m_cmd = 0; u32 m_param = 0; u32 spi_tx_cfg = geni_read_reg(mas->base, SE_SPI_TRANS_CFG); @@ -1086,7 +1087,6 @@ static void setup_fifo_xfer(struct spi_transfer *xfer, /* Speed and bits per word can be overridden per transfer */ if (xfer->speed_hz != mas->cur_speed_hz) { - int ret = 0; u32 clk_sel = 0; u32 m_clk_cfg = 0; int idx = 0; @@ -1096,7 +1096,7 @@ static void setup_fifo_xfer(struct spi_transfer *xfer, if (ret) { dev_err(mas->dev, "%s:Err setting clks:%d\n", __func__, ret); - return; + return ret; } mas->cur_speed_hz = xfer->speed_hz; clk_sel |= (idx & CLK_SEL_MSK); @@ -1177,13 +1177,14 @@ static void setup_fifo_xfer(struct spi_transfer *xfer, __func__, trans_len, xfer->len, spi_tx_cfg, m_cmd, xfer->cs_change, mas->cur_xfer_mode); if ((m_cmd & SPI_RX_ONLY) && (mas->cur_xfer_mode == SE_DMA)) { - int ret = 0; - ret = geni_se_rx_dma_prep(mas->wrapper_dev, mas->base, xfer->rx_buf, xfer->len, &xfer->rx_dma); - if (ret) + if (ret) { GENI_SE_ERR(mas->ipc, true, mas->dev, "Failed to setup Rx dma %d\n", ret); + xfer->rx_dma = 0; + return ret; + } } if (m_cmd & SPI_TX_ONLY) { if (mas->cur_xfer_mode == FIFO_MODE) { @@ -1195,14 +1196,18 @@ static void setup_fifo_xfer(struct spi_transfer *xfer, ret = geni_se_tx_dma_prep(mas->wrapper_dev, mas->base, (void *)xfer->tx_buf, xfer->len, &xfer->tx_dma); - if (ret) + if (ret) { GENI_SE_ERR(mas->ipc, true, mas->dev, "Failed to setup tx dma %d\n", ret); + xfer->tx_dma = 0; + return ret; + } } } /* Ensure all writes are done before the WM interrupt */ mb(); + return ret; } static void handle_fifo_timeout(struct spi_master *spi, @@ -1237,7 +1242,7 @@ static void handle_fifo_timeout(struct spi_master *spi, } dma_unprep: if (mas->cur_xfer_mode == SE_DMA) { - if (xfer->tx_buf) { + if (xfer->tx_buf && xfer->tx_dma) { reinit_completion(&mas->xfer_done); writel_relaxed(1, mas->base + SE_DMA_TX_FSM_RST); @@ -1249,7 +1254,7 @@ dma_unprep: geni_se_tx_dma_unprep(mas->wrapper_dev, xfer->tx_dma, xfer->len); } - if (xfer->rx_buf) { + if (xfer->rx_buf && xfer->rx_dma) { reinit_completion(&mas->xfer_done); writel_relaxed(1, mas->base + SE_DMA_RX_FSM_RST); @@ -1294,7 +1299,14 @@ static int spi_geni_transfer_one(struct spi_master *spi, if (mas->cur_xfer_mode != GSI_DMA) { reinit_completion(&mas->xfer_done); - setup_fifo_xfer(xfer, mas, slv->mode, spi); + ret = setup_fifo_xfer(xfer, mas, slv->mode, spi); + if (ret) { + GENI_SE_ERR(mas->ipc, true, mas->dev, + "setup_fifo_xfer failed: %d\n", ret); + mas->cur_xfer = NULL; + goto err_fifo_geni_transfer_one; + } + if (spi->slave) spi->slave_state = true; mutex_unlock(&mas->spi_ssr.ssr_lock); @@ -1333,7 +1345,13 @@ static int spi_geni_transfer_one(struct spi_master *spi, reinit_completion(&mas->tx_cb); reinit_completion(&mas->rx_cb); - setup_gsi_xfer(xfer, mas, slv, spi); + ret = setup_gsi_xfer(xfer, mas, slv, spi); + if (ret) { + GENI_SE_ERR(mas->ipc, true, mas->dev, + "setup_gsi_xfer failed: %d\n", ret); + mas->cur_xfer = NULL; + goto err_gsi_geni_transfer_one; + } if ((mas->num_xfers >= NUM_SPI_XFER) || (list_is_last(&xfer->transfer_list, &spi->cur_msg->transfers))) { From 896194319524e134ddc893c7bef3aaeb5cea404c Mon Sep 17 00:00:00 2001 From: Zhihao Cheng Date: Sat, 11 Jan 2020 17:50:36 +0800 Subject: [PATCH 221/592] ubifs: Fix deadlock in concurrent bulk-read and writepage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In ubifs, concurrent execution of writepage and bulk read on the same file may cause ABBA deadlock, for example (Reproduce method see Link): Process A(Bulk-read starts from page4) Process B(write page4 back) vfs_read wb_workfn or fsync ... ... generic_file_buffered_read write_cache_pages ubifs_readpage LOCK(page4) ubifs_bulk_read ubifs_writepage LOCK(ui->ui_mutex) ubifs_write_inode ubifs_do_bulk_read LOCK(ui->ui_mutex) find_or_create_page(alloc page4) ↑ LOCK(page4) <-- ABBA deadlock occurs! In order to ensure the serialization execution of bulk read, we can't remove the big lock 'ui->ui_mutex' in ubifs_bulk_read(). Instead, we allow ubifs_do_bulk_read() to lock page failed by replacing find_or_create_page(FGP_LOCK) with pagecache_get_page(FGP_LOCK | FGP_NOWAIT). Change-Id: I49a5b8d22c66bc4e45c1b93de59baff55d69ff43 Signed-off-by: Zhihao Cheng Suggested-by: zhangyi (F) Cc: Fixes: 4793e7c5e1c ("UBIFS: add bulk-read facility") Link: https://bugzilla.kernel.org/show_bug.cgi?id=206153 Signed-off-by: Richard Weinberger Git-commit: f5de5b83303e61b1f3fb09bd77ce3ac2d7a475f2 Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/ Signed-off-by: Pradeep P V K --- fs/ubifs/file.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c index ff44fd90d51b..76fff889a2f7 100644 --- a/fs/ubifs/file.c +++ b/fs/ubifs/file.c @@ -797,7 +797,9 @@ static int ubifs_do_bulk_read(struct ubifs_info *c, struct bu_info *bu, if (page_offset > end_index) break; - page = find_or_create_page(mapping, page_offset, ra_gfp_mask); + page = pagecache_get_page(mapping, page_offset, + FGP_LOCK|FGP_ACCESSED|FGP_CREAT|FGP_NOWAIT, + ra_gfp_mask); if (!page) break; if (!PageUptodate(page)) From 80d493db23803ea0be49761290d8c5ec3b24126a Mon Sep 17 00:00:00 2001 From: Lakshit Tyagi Date: Wed, 15 Jul 2020 16:48:32 +0530 Subject: [PATCH 222/592] net: stmmac: Fixed autoneg disable issue Don't support 1Gbps link speed when autoneg is disabled. Change-Id: Ic40703beab56684689e686fc3e717d99be8d5bb0 Signed-off-by: Lakshit Tyagi --- drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c index 6f4152fbab2f..8875bfcdde16 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c @@ -386,6 +386,7 @@ stmmac_ethtool_set_link_ksettings(struct net_device *dev, struct stmmac_priv *priv = netdev_priv(dev); struct phy_device *phy = dev->phydev; int rc; + u32 cmd_speed = cmd->base.speed; if (priv->hw->pcs & STMMAC_PCS_RGMII || priv->hw->pcs & STMMAC_PCS_SGMII) { @@ -412,11 +413,14 @@ stmmac_ethtool_set_link_ksettings(struct net_device *dev, return 0; } + /* Half duplex is not supported */ - if (cmd->base.duplex != DUPLEX_FULL) + if (cmd->base.duplex != DUPLEX_FULL || + (cmd_speed == SPEED_1000 && cmd->base.autoneg == AUTONEG_DISABLE)) rc = -EINVAL; else rc = phy_ethtool_ksettings_set(phy, cmd); + return rc; } From 2cde9c9686af7403765295663d5cee3d4974f699 Mon Sep 17 00:00:00 2001 From: Sayali Lokhande Date: Tue, 21 Jul 2020 15:42:22 +0530 Subject: [PATCH 223/592] defconfig: Enable Incremental FS support This change enables Incremental FS support on msm-4.14 based targets as required for Android R. Change-Id: I68ce8fce603a2aada9288a1cbd4b7a7d83c5f2c8 Signed-off-by: Sayali Lokhande --- arch/arm64/configs/vendor/atoll-perf_defconfig | 1 + arch/arm64/configs/vendor/atoll_defconfig | 1 + arch/arm64/configs/vendor/sdmsteppe-auto-perf_defconfig | 1 + arch/arm64/configs/vendor/sdmsteppe-auto_defconfig | 1 + arch/arm64/configs/vendor/sdmsteppe-perf_defconfig | 1 + arch/arm64/configs/vendor/sdmsteppe_defconfig | 1 + arch/arm64/configs/vendor/sm8150-perf_defconfig | 1 + arch/arm64/configs/vendor/sm8150_defconfig | 1 + 8 files changed, 8 insertions(+) diff --git a/arch/arm64/configs/vendor/atoll-perf_defconfig b/arch/arm64/configs/vendor/atoll-perf_defconfig index fec102ee0204..0591bef7db46 100644 --- a/arch/arm64/configs/vendor/atoll-perf_defconfig +++ b/arch/arm64/configs/vendor/atoll-perf_defconfig @@ -682,6 +682,7 @@ CONFIG_QUOTA_NETLINK_INTERFACE=y CONFIG_QFMT_V2=y CONFIG_FUSE_FS=y CONFIG_OVERLAY_FS=y +CONFIG_INCREMENTAL_FS=y CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y CONFIG_TMPFS_POSIX_ACL=y diff --git a/arch/arm64/configs/vendor/atoll_defconfig b/arch/arm64/configs/vendor/atoll_defconfig index b9f29521b8f3..f8f33553672f 100644 --- a/arch/arm64/configs/vendor/atoll_defconfig +++ b/arch/arm64/configs/vendor/atoll_defconfig @@ -713,6 +713,7 @@ CONFIG_QUOTA_NETLINK_INTERFACE=y CONFIG_QFMT_V2=y CONFIG_FUSE_FS=y CONFIG_OVERLAY_FS=y +CONFIG_INCREMENTAL_FS=y CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y CONFIG_TMPFS_POSIX_ACL=y diff --git a/arch/arm64/configs/vendor/sdmsteppe-auto-perf_defconfig b/arch/arm64/configs/vendor/sdmsteppe-auto-perf_defconfig index 3ed484a1a0c4..151f629ca328 100644 --- a/arch/arm64/configs/vendor/sdmsteppe-auto-perf_defconfig +++ b/arch/arm64/configs/vendor/sdmsteppe-auto-perf_defconfig @@ -651,6 +651,7 @@ CONFIG_QUOTA_NETLINK_INTERFACE=y CONFIG_QFMT_V2=y CONFIG_FUSE_FS=y CONFIG_OVERLAY_FS=y +CONFIG_INCREMENTAL_FS=y CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y CONFIG_TMPFS_POSIX_ACL=y diff --git a/arch/arm64/configs/vendor/sdmsteppe-auto_defconfig b/arch/arm64/configs/vendor/sdmsteppe-auto_defconfig index c7b325846756..49733043c7b4 100644 --- a/arch/arm64/configs/vendor/sdmsteppe-auto_defconfig +++ b/arch/arm64/configs/vendor/sdmsteppe-auto_defconfig @@ -689,6 +689,7 @@ CONFIG_QUOTA_NETLINK_INTERFACE=y CONFIG_QFMT_V2=y CONFIG_FUSE_FS=y CONFIG_OVERLAY_FS=y +CONFIG_INCREMENTAL_FS=y CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y CONFIG_TMPFS_POSIX_ACL=y diff --git a/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig b/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig index c60b1cc772a6..c0658e01e8d5 100644 --- a/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig +++ b/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig @@ -660,6 +660,7 @@ CONFIG_QUOTA_NETLINK_INTERFACE=y CONFIG_QFMT_V2=y CONFIG_FUSE_FS=y CONFIG_OVERLAY_FS=y +CONFIG_INCREMENTAL_FS=y CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y CONFIG_TMPFS_POSIX_ACL=y diff --git a/arch/arm64/configs/vendor/sdmsteppe_defconfig b/arch/arm64/configs/vendor/sdmsteppe_defconfig index d1ea546f00d0..5c3c04c4f708 100644 --- a/arch/arm64/configs/vendor/sdmsteppe_defconfig +++ b/arch/arm64/configs/vendor/sdmsteppe_defconfig @@ -698,6 +698,7 @@ CONFIG_QUOTA_NETLINK_INTERFACE=y CONFIG_QFMT_V2=y CONFIG_FUSE_FS=y CONFIG_OVERLAY_FS=y +CONFIG_INCREMENTAL_FS=y CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y CONFIG_TMPFS_POSIX_ACL=y diff --git a/arch/arm64/configs/vendor/sm8150-perf_defconfig b/arch/arm64/configs/vendor/sm8150-perf_defconfig index ae6e24be182f..0a0252777cfc 100644 --- a/arch/arm64/configs/vendor/sm8150-perf_defconfig +++ b/arch/arm64/configs/vendor/sm8150-perf_defconfig @@ -668,6 +668,7 @@ CONFIG_QUOTA_NETLINK_INTERFACE=y CONFIG_QFMT_V2=y CONFIG_FUSE_FS=y CONFIG_OVERLAY_FS=y +CONFIG_INCREMENTAL_FS=y CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y CONFIG_TMPFS_POSIX_ACL=y diff --git a/arch/arm64/configs/vendor/sm8150_defconfig b/arch/arm64/configs/vendor/sm8150_defconfig index 00883b59ca12..44121189e378 100644 --- a/arch/arm64/configs/vendor/sm8150_defconfig +++ b/arch/arm64/configs/vendor/sm8150_defconfig @@ -699,6 +699,7 @@ CONFIG_QUOTA_NETLINK_INTERFACE=y CONFIG_QFMT_V2=y CONFIG_FUSE_FS=y CONFIG_OVERLAY_FS=y +CONFIG_INCREMENTAL_FS=y CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y CONFIG_TMPFS_POSIX_ACL=y From 80922d2c77d7935e46a696cb5507df5f98087bba Mon Sep 17 00:00:00 2001 From: Dundi Raviteja Date: Tue, 21 Jul 2020 20:19:13 +0530 Subject: [PATCH 224/592] ARM: dts: msm8916: Update reserved-memory for wcnss, venus and mba Reserved memory for wcnss, venus and mba nodes updated mistakenly in earlier commit. Revert them back to original values. Change-Id: I17e11d8ce161b0802fbd8bd81e6e830f7f586024 Fixes: 8c5aade5252c ("UPSTREAM: ath10k: support extended board data download for dual-band QCA9984) Signed-off-by: Dundi Raviteja --- arch/arm64/boot/dts/qcom/msm8916.dtsi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi index ee36196df1d1..4a8f48564538 100644 --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2015, 2020 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -84,18 +84,18 @@ }; wcnss_mem: wcnss@89300000 { - reg = <0x0 0x89300000 0x0 0x700000>; + reg = <0x0 0x89300000 0x0 0x600000>; no-map; }; venus_mem: venus@89900000 { - reg = <0x0 0x89A00000 0x0 0x600000>; + reg = <0x0 0x89900000 0x0 0x600000>; no-map; }; mba_mem: mba@8ea00000 { no-map; - reg = <0 0x8A000000 0 0x100000>; + reg = <0 0x8ea00000 0 0x100000>; }; }; From 455f20091209213c0df1f09161ff42efafc4d2cf Mon Sep 17 00:00:00 2001 From: Dundi Raviteja Date: Wed, 22 Jul 2020 19:56:56 +0530 Subject: [PATCH 225/592] wcnss: Enable smd channel ready Enable smd channel ready after getting nv binary download response. Change-Id: Ie36b8d1c0273c832892b338ac81cf9738fe6f9f4 Signed-off-by: Dundi Raviteja --- drivers/soc/qcom/wcnss/wcnss_wlan.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/soc/qcom/wcnss/wcnss_wlan.c b/drivers/soc/qcom/wcnss/wcnss_wlan.c index 2ec29350f6f8..b939c02b36ec 100644 --- a/drivers/soc/qcom/wcnss/wcnss_wlan.c +++ b/drivers/soc/qcom/wcnss/wcnss_wlan.c @@ -1573,6 +1573,7 @@ static int wcnss_ctrl_probe(struct rpmsg_device *rpdev) static void wcnss_ctrl_remove(struct rpmsg_device *rpdev) { + penv->smd_channel_ready = 0; of_platform_depopulate(&rpdev->dev); } @@ -2378,6 +2379,8 @@ static void wcnss_process_smd_msg(void *buf, int len) if (nvresp->status != WAIT_FOR_CBC_IND) penv->is_cbc_done = 1; + penv->smd_channel_ready = 1; + if (penv->ops) penv->ops->driver_state(penv->ops->priv_data, WCNSS_SMD_OPEN); From 89b30398dade6a0b8fad72524ac1a1549e594b6d Mon Sep 17 00:00:00 2001 From: Ramachandran Venkataramani Date: Wed, 22 Jul 2020 10:36:04 -0700 Subject: [PATCH 226/592] ARM: dts: qcom: Add system secure ion heap for Quin GVM Add system secure ion heap for use with secure DRM usecases on Quin GVMs. Change-Id: I1f5b0237bf2dde45c90854e449eab6557d74d949 Signed-off-by: Ramachandran Venkataramani --- arch/arm64/boot/dts/qcom/quin-vm-common.dtsi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/quin-vm-common.dtsi b/arch/arm64/boot/dts/qcom/quin-vm-common.dtsi index 8c6dc3bebce6..90aa33ba6541 100644 --- a/arch/arm64/boot/dts/qcom/quin-vm-common.dtsi +++ b/arch/arm64/boot/dts/qcom/quin-vm-common.dtsi @@ -124,6 +124,11 @@ memory-region = <&qseecom_ta_mem>; qcom,ion-heap-type = "DMA"; }; + + qcom,ion-heap@9 { + reg = <9>; + qcom,ion-heap-type = "SYSTEM_SECURE"; + }; }; hab: qcom,hab { From 98849f68d12b4212b9d2a7c50228deb014ce85ee Mon Sep 17 00:00:00 2001 From: Yong Ding Date: Tue, 16 Jun 2020 18:46:24 +0800 Subject: [PATCH 227/592] soc: qcom: hab: fix some issues in the remote open cancelling case The version numbers shall be copied into the local variables for any potential version comparison. Change-Id: Ib2648805bd7832b4fd7508b10d1382c8055a139f Signed-off-by: Yong Ding --- drivers/soc/qcom/hab/hab_open.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/soc/qcom/hab/hab_open.c b/drivers/soc/qcom/hab/hab_open.c index a90460a1295e..8caccdd22c7d 100644 --- a/drivers/soc/qcom/hab/hab_open.c +++ b/drivers/soc/qcom/hab/hab_open.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -240,6 +240,8 @@ int hab_open_receive_cancel(struct physical_channel *pchan, request->xdata.vchan_id = data.vchan_id; request->xdata.sub_id = data.sub_id; request->xdata.open_id = data.open_id; + request->xdata.ver_fe = data.ver_fe; + request->xdata.ver_be = data.ver_be; do_gettimeofday(&tv); node->age = tv.tv_sec + HAB_OPEN_REQ_EXPIRE_TIME_S + From fbbdd70acf1da7e17f34d5c39f37094c8ff68acf Mon Sep 17 00:00:00 2001 From: Jiacheng Zheng Date: Thu, 23 Jul 2020 13:57:28 +0800 Subject: [PATCH 228/592] defconfig: sdmshrike: use uncompressed linux kernel Time wasted on decompression is much more than time saved on ufs loading, boot time can be improved by around 100ms. Change-Id: Ia6118cb2820622b7c20961a488b3094f0c4cc1d1 Signed-off-by: Jiacheng Zheng --- arch/arm64/configs/vendor/sdmshrike-perf_defconfig | 1 + arch/arm64/configs/vendor/sdmshrike_defconfig | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm64/configs/vendor/sdmshrike-perf_defconfig b/arch/arm64/configs/vendor/sdmshrike-perf_defconfig index 1d6ef880eaa8..98a1c46dea3a 100644 --- a/arch/arm64/configs/vendor/sdmshrike-perf_defconfig +++ b/arch/arm64/configs/vendor/sdmshrike-perf_defconfig @@ -76,6 +76,7 @@ CONFIG_SETEND_EMULATION=y CONFIG_RANDOMIZE_BASE=y # CONFIG_EFI is not set CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y +CONFIG_BUILD_ARM64_UNCOMPRESSED_KERNEL=y # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set CONFIG_COMPAT=y CONFIG_PM_WAKELOCKS=y diff --git a/arch/arm64/configs/vendor/sdmshrike_defconfig b/arch/arm64/configs/vendor/sdmshrike_defconfig index cb315f41648e..84bd6089822f 100644 --- a/arch/arm64/configs/vendor/sdmshrike_defconfig +++ b/arch/arm64/configs/vendor/sdmshrike_defconfig @@ -82,6 +82,7 @@ CONFIG_SETEND_EMULATION=y # CONFIG_ARM64_VHE is not set CONFIG_RANDOMIZE_BASE=y CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y +CONFIG_BUILD_ARM64_UNCOMPRESSED_KERNEL=y # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set CONFIG_COMPAT=y CONFIG_PM_WAKELOCKS=y From f7c1e9ebdaac1b984b7e50f4f9f9172be83cbbdc Mon Sep 17 00:00:00 2001 From: Sneh Shah Date: Thu, 25 Jun 2020 12:22:54 +0530 Subject: [PATCH 229/592] net: stmmac: Add check for micrel phy for phy interrupt Add check for micrel phy for phy interrupt before enabling phy irq. Change-Id: I5f850a4c4b36373676ac3bd792eac327001a0f76 Signed-off-by: Sneh Shah --- .../net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 13 +++++++------ .../net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.h | 1 - drivers/net/ethernet/stmicro/stmmac/stmmac.h | 3 +++ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 9 +++++++++ include/linux/stmmac.h | 1 + 5 files changed, 20 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index 66ffde0d5567..160267c0a1ae 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -1038,9 +1038,15 @@ static irqreturn_t ETHQOS_PHY_ISR(int irq, void *dev_data) return IRQ_HANDLED; } -static int ethqos_phy_intr_enable(struct qcom_ethqos *ethqos) +int ethqos_phy_intr_enable(struct stmmac_priv *priv) { int ret = 0; + struct qcom_ethqos *ethqos = priv->plat->bsp_priv; + + if (ethqos_phy_intr_config(ethqos)) { + ret = 1; + return ret; + } INIT_WORK(ðqos->emac_phy_work, ethqos_defer_phy_isr_work); init_completion(ðqos->clk_enable_done); @@ -1052,7 +1058,6 @@ static int ethqos_phy_intr_enable(struct qcom_ethqos *ethqos) ethqos->phy_intr); return ret; } - phy_intr_en = true; return ret; } @@ -1879,10 +1884,6 @@ static int qcom_ethqos_probe(struct platform_device *pdev) if (ret) goto err_clk; - if (!ethqos_phy_intr_config(ethqos)) - ethqos_phy_intr_enable(ethqos); - else - ETHQOSERR("Phy interrupt configuration failed"); rgmii_dump(ethqos); if (ethqos->emac_ver == EMAC_HW_v2_3_2) { diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.h b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.h index 5b06145c6e8e..79b63a8b3674 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.h @@ -222,7 +222,6 @@ do {\ #define ATH8035_PHY_ID 0x004dd072 #define QCA8337_PHY_ID 0x004dd036 #define ATH8030_PHY_ID 0x004dd076 -#define MICREL_PHY_ID PHY_ID_KSZ9031 #define DWC_ETH_QOS_MICREL_PHY_INTCS 0x1b #define DWC_ETH_QOS_MICREL_PHY_CTL 0x1f #define DWC_ETH_QOS_BASIC_STATUS 0x0001 diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index 58ccbf8386ea..19f8c92d4900 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -173,9 +173,12 @@ extern struct stmmac_emb_smmu_cb_ctx stmmac_emb_smmu_ctx; #define GET_MEM_PDEV_DEV (stmmac_emb_smmu_ctx.valid ? \ &stmmac_emb_smmu_ctx.smmu_pdev->dev : priv->device) +#define MICREL_PHY_ID 0x00221620 + int ethqos_handle_prv_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); int ethqos_init_pps(struct stmmac_priv *priv); +int ethqos_phy_intr_enable(struct stmmac_priv *priv); extern bool phy_intr_en; void qcom_ethqos_request_phy_wol(struct plat_stmmacenet_data *plat_dat); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index f6ba02ef92e2..bf48433d6403 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1053,6 +1053,15 @@ static int stmmac_init_phy(struct net_device *dev) if (phydev->is_pseudo_fixed_link) phydev->irq = PHY_POLL; + if (((phydev->phy_id & phydev->drv->phy_id_mask) == MICREL_PHY_ID) && + !priv->plat->phy_intr_en) { + ret = ethqos_phy_intr_enable(priv); + if (ret) + pr_alert("qcom-ethqos: Unable to enable PHY interrupt\n"); + else + priv->plat->phy_intr_en = true; + } + if (phy_intr_en) { if (phydev->drv->config_intr && !phydev->drv->config_intr(phydev)) { diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h index 39c4005a0396..9ed7771ba212 100644 --- a/include/linux/stmmac.h +++ b/include/linux/stmmac.h @@ -200,5 +200,6 @@ struct plat_stmmacenet_data { (struct sk_buff *skb); bool early_eth; bool crc_strip_en; + bool phy_intr_en; }; #endif From 30214bea787340d765a77645e981405dbffc9a56 Mon Sep 17 00:00:00 2001 From: Ashish Kori Date: Thu, 23 Jul 2020 13:25:48 +0530 Subject: [PATCH 230/592] platform: msm: qcom-geni-se: Correct print statement format Correct print statement in 'commit c816ae601343e ("platform: msm: qcom-geni-se: Enable SSC QUP SE clks before SCM call")'. Change-Id: I4b59d9b1907ddb6a332c1cb494071bcacf60a0ad Signed-off-by: Ashish Kori --- drivers/platform/msm/qcom-geni-se.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/platform/msm/qcom-geni-se.c b/drivers/platform/msm/qcom-geni-se.c index d2b8a8d75099..1c6615a76b69 100644 --- a/drivers/platform/msm/qcom-geni-se.c +++ b/drivers/platform/msm/qcom-geni-se.c @@ -2026,7 +2026,8 @@ static int geni_se_probe(struct platform_device *pdev) ret = devm_clk_bulk_get(dev, SSC_NUM_CLKS, geni_se_dev->ssc_clks); if (ret) { - dev_err(dev, "%s: Err getting core/2x clk:%d\n", ret); + dev_err(dev, "%s: Err getting core/2x clk:%d\n", + __func__, ret); return ret; } From 5c96bedfe194df98fcade85af411a122b390585e Mon Sep 17 00:00:00 2001 From: Jeya R Date: Thu, 23 Jul 2020 16:00:50 +0530 Subject: [PATCH 231/592] msm: ADSPRPC: Map and FD non-NULL check before dereferencing When fd is zero, we set context fds to NULL. This will avoid calling map create for context. Proper check is required to avoid dereferencing of map and fd. Change-Id: Id8d4b93d7d999e14ac1ebd8291137f799a73cf1a Acked-by: Ekansh Gupta Signed-off-by: Jeya R --- drivers/char/adsprpc.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 8ed94351e897..b9cc61c282c6 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -1599,9 +1599,10 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx) PERF_END); for (i = bufs; i < bufs + handles; ++i) { struct fastrpc_mmap *map = ctx->maps[i]; - - pages[i].addr = map->phys; - pages[i].size = map->size; + if (map) { + pages[i].addr = map->phys; + pages[i].size = map->size; + } } fdlist = (uint64_t *)&pages[bufs + handles]; for (i = 0; i < M_FDLIST; i++) @@ -1679,7 +1680,8 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx) } PERF_END); for (i = bufs; rpra && lrpra && i < bufs + handles; i++) { - rpra[i].dma.fd = lrpra[i].dma.fd = ctx->fds[i]; + if (ctx->fds) + rpra[i].dma.fd = lrpra[i].dma.fd = ctx->fds[i]; rpra[i].dma.len = lrpra[i].dma.len = (uint32_t)lpra[i].buf.len; rpra[i].dma.offset = lrpra[i].dma.offset = (uint32_t)(uintptr_t)lpra[i].buf.pv; From 1a8cefa213b207a7e8894fbed494f5d2e75cc3e9 Mon Sep 17 00:00:00 2001 From: Archit Saxena Date: Wed, 1 Jul 2020 20:25:53 +0530 Subject: [PATCH 232/592] ARM : dts: msm: Add DCVS and sched nodes Add dcvs and sched nodes to sdm429. Change-Id: I637b76c4e34cd37c922efe75475c383393d3ebea Signed-off-by: Archit Saxena --- arch/arm64/boot/dts/qcom/sdm429-cpu.dtsi | 14 ++--- arch/arm64/boot/dts/qcom/sdm429.dtsi | 66 +++++++++++++++++++++++- 2 files changed, 69 insertions(+), 11 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sdm429-cpu.dtsi b/arch/arm64/boot/dts/qcom/sdm429-cpu.dtsi index e5c016ee8f0e..8632471a74cd 100644 --- a/arch/arm64/boot/dts/qcom/sdm429-cpu.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm429-cpu.dtsi @@ -43,7 +43,7 @@ reg = <0x100>; enable-method = "psci"; cpu-release-addr = <0x0 0x90000000>; - efficiency = <1024>; + capacity-dmips-mhz = <1024>; sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_0>; next-level-cache = <&L2_1>; #cooling-cells = <2>; @@ -69,7 +69,7 @@ reg = <0x101>; enable-method = "psci"; cpu-release-addr = <0x0 0x90000000>; - efficiency = <1024>; + capacity-dmips-mhz = <1024>; sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_0>; next-level-cache = <&L2_1>; #cooling-cells = <2>; @@ -89,7 +89,7 @@ reg = <0x102>; enable-method = "psci"; cpu-release-addr = <0x0 0x90000000>; - efficiency = <1024>; + capacity-dmips-mhz = <1024>; sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_0>; next-level-cache = <&L2_1>; #cooling-cells = <2>; @@ -109,7 +109,7 @@ reg = <0x103>; enable-method = "psci"; cpu-release-addr = <0x0 0x90000000>; - efficiency = <1024>; + capacity-dmips-mhz = <1024>; sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_0>; next-level-cache = <&L2_1>; #cooling-cells = <2>; @@ -134,9 +134,6 @@ 1305600 207 1497600 256 1708800 327 - 1804800 343 - 1958400 445 - 2016000 470 >; idle-cost-data = < 100 80 60 40 @@ -148,9 +145,6 @@ 1305600 61 1497600 71 1708800 85 - 1804800 88 - 1958400 110 - 2016000 120 >; idle-cost-data = < 4 3 2 1 diff --git a/arch/arm64/boot/dts/qcom/sdm429.dtsi b/arch/arm64/boot/dts/qcom/sdm429.dtsi index 31218880dc07..1882b0235edb 100644 --- a/arch/arm64/boot/dts/qcom/sdm429.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm429.dtsi @@ -19,6 +19,9 @@ #include #include +#define MHZ_TO_MBPS(mhz, w) ((mhz * 1000000 * w) / (1024 * 1024)) +#define BW_OPP_ENTRY(mhz, w) opp-mhz {opp-hz = /bits/ 64 ;} + / { model = "Qualcomm Technologies, Inc. SDM429"; compatible = "qcom,sdm429"; @@ -423,7 +426,6 @@ cpu-pmu { compatible = "arm,armv8-pmuv3"; interrupts = <1 7 0xff00>; - status = "disabled"; }; qcom,sps { @@ -1317,6 +1319,68 @@ qcom,ea-pc = <0x230>; status = "disabled"; }; + + qcom,msm-adsp-loader { + status = "ok"; + compatible = "qcom,adsp-loader"; + qcom,adsp-state = <0>; + }; + + msm_cpufreq: qcom,msm-cpufreq { + compatible = "qcom,msm-cpufreq"; + clock-names = "cpu0_clk"; + clocks = <&cpu APCS_MUX_C1_CLK>; + + qcom,cpufreq-table = + < 960000 >, + < 1305600 >, + < 1497600 >, + < 1708800 >; + }; + ddr_bw_opp_table: ddr-bw-opp-table { + compatible = "operating-points-v2"; + BW_OPP_ENTRY( 211,8); /* 2265 MB/s */ + BW_OPP_ENTRY( 384, 8); /* 4539 MB/s */ + BW_OPP_ENTRY( 662, 8); /* 5416 MB/s */ + BW_OPP_ENTRY( 749, 8); + }; + + cpubw: qcom,cpubw { + compatible = "qcom,devbw"; + governor = "performance"; + qcom,src-dst-ports = <1 512>; + qcom,active-only; + operating-points-v2 = <&ddr_bw_opp_table>; + }; + + com,cpu-bwmon { + compatible = "qcom,bimc-bwmon2"; + reg = <0x408000 0x300>, <0x401000 0x200>; + reg-names = "base", "global_base"; + interrupts = <0 183 4>; + qcom,mport = <0>; + qcom,target-dev = <&cpubw>; + }; + + cpu0_cpu_ddr_latfloor: qcom,cpu0-cpu-ddr-latfloor { + compatible = "qcom,devbw"; + governor = "performance"; + qcom,src-dst-ports = <1 512>; + qcom,active-only; + operating-points-v2 = <&ddr_bw_opp_table>; + }; + + cpu0_computemon: qcom,cpu0-computemon { + compatible = "qcom,arm-cpu-mon"; + qcom,cpulist = <&CPU0 &CPU1 &CPU2 &CPU3>; + qcom,target-dev = <&cpu0_cpu_ddr_latfloor>; + qcom,core-dev-table = + < 960000 MHZ_TO_MBPS( 211, 8) >, + < 1305600 MHZ_TO_MBPS( 384, 8) >, + < 1497600 MHZ_TO_MBPS( 662, 8) >, + < 1708800 MHZ_TO_MBPS( 749, 8) >; + }; + }; #include "sdm429-gdsc.dtsi" From 8ef34645b8e6fcb0a21cbbb11ddb248ce123d6b0 Mon Sep 17 00:00:00 2001 From: Archit Saxena Date: Mon, 29 Jun 2020 12:59:02 +0530 Subject: [PATCH 233/592] defconfig: sdm429: Add configs related to DCVS and scheduler Add configs related to DCVS and scheduler for sdm429w target. Change-Id: I610373fb8cf75cb9e80a0ebfd11c9c60005ea78f Signed-off-by: Archit Saxena --- arch/arm/configs/vendor/sdm429-bg-perf_defconfig | 2 ++ arch/arm/configs/vendor/sdm429-bg_defconfig | 1 + 2 files changed, 3 insertions(+) diff --git a/arch/arm/configs/vendor/sdm429-bg-perf_defconfig b/arch/arm/configs/vendor/sdm429-bg-perf_defconfig index fa92c8e76d54..f412e97df448 100644 --- a/arch/arm/configs/vendor/sdm429-bg-perf_defconfig +++ b/arch/arm/configs/vendor/sdm429-bg-perf_defconfig @@ -76,6 +76,7 @@ CONFIG_CPU_FREQ_GOV_ONDEMAND=y CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y CONFIG_CPU_BOOST=y CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y +CONFIG_CPU_FREQ_MSM=y CONFIG_CPU_IDLE=y CONFIG_ARM_CPUIDLE=y CONFIG_VFP=y @@ -626,6 +627,7 @@ CONFIG_PAGE_OWNER=y CONFIG_MAGIC_SYSRQ=y CONFIG_PANIC_TIMEOUT=5 CONFIG_SCHEDSTATS=y +CONFIG_SCHED_STACK_END_CHECK=y CONFIG_IPC_LOGGING=y CONFIG_CORESIGHT=y CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y diff --git a/arch/arm/configs/vendor/sdm429-bg_defconfig b/arch/arm/configs/vendor/sdm429-bg_defconfig index 167ce3b8f5d0..11011eee9bed 100644 --- a/arch/arm/configs/vendor/sdm429-bg_defconfig +++ b/arch/arm/configs/vendor/sdm429-bg_defconfig @@ -78,6 +78,7 @@ CONFIG_CPU_FREQ_GOV_ONDEMAND=y CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y CONFIG_CPU_BOOST=y CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y +CONFIG_CPU_FREQ_MSM=y CONFIG_CPU_IDLE=y CONFIG_ARM_CPUIDLE=y CONFIG_VFP=y From 6f1fb56634ba45fcf933f983c2c279b9bb27ab82 Mon Sep 17 00:00:00 2001 From: Archit Saxena Date: Thu, 9 Jul 2020 15:58:16 +0530 Subject: [PATCH 234/592] ARM: dts: msm: Add mem_dump and RTB node for sdm429 Add rtb and memdump node for sdm429 target. Change-Id: I5d3f34c948b40ee63e400c932bfc4aea1da60c7c Signed-off-by: Archit Saxena --- arch/arm64/boot/dts/qcom/sdm429.dtsi | 41 +++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/sdm429.dtsi b/arch/arm64/boot/dts/qcom/sdm429.dtsi index 1882b0235edb..b7e4f9567998 100644 --- a/arch/arm64/boot/dts/qcom/sdm429.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm429.dtsi @@ -473,7 +473,6 @@ qcom,msm-rtb { compatible = "qcom,msm-rtb"; qcom,rtb-size = <0x100000>; /* 1M EBI1 buffer */ - status = "disabled"; }; qcom,rmtfs_sharedmem@00000000 { @@ -615,6 +614,46 @@ }; }; + mem_dump { + compatible = "qcom,mem-dump"; + memory-region = <0x85>; + + rpm_sw_dump { + qcom,dump-size = <0x28000>; + qcom,dump-id = <0xea>; + }; + + pmic_dump { + qcom,dump-size = <0x10000>; + qcom,dump-id = <0xe4>; + }; + + vsense_dump { + qcom,dump-size = <0x1000>; + qcom,dump-id = <0xe9>; + }; + + tmc_etf_dump { + qcom,dump-size = <0x10000>; + qcom,dump-id = <0xf0>; + }; + + tmc_etr_reg_dump { + qcom,dump-size = <0x1000>; + qcom,dump-id = <0x100>; + }; + + tmc_etf_reg_dump { + qcom,dump-size = <0x1000>; + qcom,dump-id = <0x101>; + }; + + misc_data_dump { + qcom,dump-size = <0x1000>; + qcom,dump-id = <0xe8>; + }; + }; + qcom,lpass@c000000 { compatible = "qcom,pil-tz-generic"; reg = <0xc000000 0x00100>; From 8a4b105f61dbb2a1210519bc979ff9086533c2f7 Mon Sep 17 00:00:00 2001 From: Harish Bandi Date: Fri, 17 Jul 2020 20:01:32 +0530 Subject: [PATCH 235/592] ARM: dts: msm: add hs uart node for BT on QCS410 device Add hs uart node for BT on QCS410 device. Change-Id: I0d5a408c817829a2b0c6c94e061f94f48bc1c54f Signed-off-by: Harish Bandi --- arch/arm64/boot/dts/qcom/qcs410-iot.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcs410-iot.dtsi b/arch/arm64/boot/dts/qcom/qcs410-iot.dtsi index ae583f20ad78..078a863d63d6 100644 --- a/arch/arm64/boot/dts/qcom/qcs410-iot.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs410-iot.dtsi @@ -37,6 +37,14 @@ status = "disabled"; }; +&qupv3_se0_2uart { + status = "ok"; +}; + +&qupv3_se7_4uart { + status = "ok"; +}; + &pm6150l_gpios { key_vol_up { key_vol_up_default: key_vol_up_default { From 30dc35e84fb2ddd03531ea4f2b262367f30d8729 Mon Sep 17 00:00:00 2001 From: Sanjay Dwivedi Date: Thu, 23 Jul 2020 13:01:00 +0530 Subject: [PATCH 236/592] ARM: dts: msm: Update mpss_adsp carved memory for sa515m cdp New memory map is proposed for mapping 248 MB of memory to MPSS. Change-Id: Ice91140c58d4fdd7d4bda2bbbb5909e148d5bc93 Signed-off-by: Sanjay Dwivedi --- arch/arm64/boot/dts/qcom/sdxprairie-v2-dsda-cdp.dts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sdxprairie-v2-dsda-cdp.dts b/arch/arm64/boot/dts/qcom/sdxprairie-v2-dsda-cdp.dts index 99e9f86f5f14..e99fc9415bae 100644 --- a/arch/arm64/boot/dts/qcom/sdxprairie-v2-dsda-cdp.dts +++ b/arch/arm64/boot/dts/qcom/sdxprairie-v2-dsda-cdp.dts @@ -99,3 +99,7 @@ regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; }; + +&mpss_adsp_mem { + reg = <0x90800000 0xf800000>; +}; From c043315fc85a78662e9f079714c4b6133d346081 Mon Sep 17 00:00:00 2001 From: Sanjay Dwivedi Date: Mon, 22 Jun 2020 23:56:43 +0530 Subject: [PATCH 237/592] ARM: dts: msm: add support for SMP2P shutdown ack from modem Add the device entry to define the SMP2P interface for shutdown acknowledgment from modem after SSCTL command is sent from MPSS to APPS. Also define the correct SSCTL instance ID to register the SSCTL QMI service. Change-Id: I8420857df0c0b9d364b04fb465b79c331f3881cd Signed-off-by: Sanjay Dwivedi --- .../arm64/boot/dts/qcom/sdxprairie-smp2p.dtsi | 132 ++++++++++++++++++ arch/arm64/boot/dts/qcom/sdxprairie.dtsi | 11 ++ 2 files changed, 143 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/sdxprairie-smp2p.dtsi diff --git a/arch/arm64/boot/dts/qcom/sdxprairie-smp2p.dtsi b/arch/arm64/boot/dts/qcom/sdxprairie-smp2p.dtsi new file mode 100644 index 000000000000..f31c53b3506e --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sdxprairie-smp2p.dtsi @@ -0,0 +1,132 @@ +/* Copyright (c) 2020, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include + +&soc { + qcom,smp2p-modem@17811008 { + compatible = "qcom,smp2p"; + reg = <0x17811008 0x4>; + qcom,remote-pid = <1>; + qcom,irq-bitmask = <0x4000>; + interrupts = ; + }; + + smp2pgpio_smp2p_15_in: qcom,smp2pgpio-smp2p-15-in { + compatible = "qcom,smp2pgpio"; + qcom,entry-name = "smp2p"; + qcom,remote-pid = <15>; + qcom,is-inbound; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + qcom,smp2pgpio_test_smp2p_15_in { + compatible = "qcom,smp2pgpio_test_smp2p_15_in"; + gpios = <&smp2pgpio_smp2p_15_in 0 0>; + }; + + smp2pgpio_smp2p_15_out: qcom,smp2pgpio-smp2p-15-out { + compatible = "qcom,smp2pgpio"; + qcom,entry-name = "smp2p"; + qcom,remote-pid = <15>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + qcom,smp2pgpio_test_smp2p_15_out { + compatible = "qcom,smp2pgpio_test_smp2p_15_out"; + gpios = <&smp2pgpio_smp2p_15_out 0 0>; + }; + + smp2pgpio_smp2p_1_in: qcom,smp2pgpio-smp2p-1-in { + compatible = "qcom,smp2pgpio"; + qcom,entry-name = "smp2p"; + qcom,remote-pid = <1>; + qcom,is-inbound; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + qcom,smp2pgpio_test_smp2p_1_in { + compatible = "qcom,smp2pgpio_test_smp2p_1_in"; + gpios = <&smp2pgpio_smp2p_1_in 0 0>; + }; + + smp2pgpio_smp2p_1_out: qcom,smp2pgpio-smp2p-1-out { + compatible = "qcom,smp2pgpio"; + qcom,entry-name = "smp2p"; + qcom,remote-pid = <1>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + qcom,smp2pgpio_test_smp2p_1_out { + compatible = "qcom,smp2pgpio_test_smp2p_1_out"; + gpios = <&smp2pgpio_smp2p_1_out 0 0>; + }; + + /* ssr - inbound entry from mss */ + smp2pgpio_ssr_smp2p_1_in: qcom,smp2pgpio-ssr-smp2p-1-in { + compatible = "qcom,smp2pgpio"; + qcom,entry-name = "slave-kernel"; + qcom,remote-pid = <1>; + qcom,is-inbound; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + /* ssr - outbound entry to mss */ + smp2pgpio_ssr_smp2p_1_out: qcom,smp2pgpio-ssr-smp2p-1-out { + compatible = "qcom,smp2pgpio"; + qcom,entry-name = "master-kernel"; + qcom,remote-pid = <1>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + /* ipa - outbound entry to mss */ + smp2pgpio_ipa_1_out: qcom,smp2pgpio-ipa-1-out { + compatible = "qcom,smp2pgpio"; + qcom,entry-name = "ipa"; + qcom,remote-pid = <1>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + /* ipa - inbound entry from mss */ + smp2pgpio_ipa_1_in: qcom,smp2pgpio-ipa-1-in { + compatible = "qcom,smp2pgpio"; + qcom,entry-name = "ipa"; + qcom,remote-pid = <1>; + qcom,is-inbound; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; +}; + diff --git a/arch/arm64/boot/dts/qcom/sdxprairie.dtsi b/arch/arm64/boot/dts/qcom/sdxprairie.dtsi index 1213da795253..e2327a27c58e 100644 --- a/arch/arm64/boot/dts/qcom/sdxprairie.dtsi +++ b/arch/arm64/boot/dts/qcom/sdxprairie.dtsi @@ -480,6 +480,16 @@ qcom,smem-states = <&modem_smp2p_out 0>; qcom,smem-state-names = "qcom,force-stop"; + /* GPIO intput to mss */ + qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_1_in 0 0>; + qcom,gpio-err-ready = <&smp2pgpio_ssr_smp2p_1_in 1 0>; + qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_1_in 2 0>; + qcom,gpio-stop-ack = <&smp2pgpio_ssr_smp2p_1_in 3 0>; + qcom,gpio-shutdown-ack = <&smp2pgpio_ssr_smp2p_1_in 7 0>; + + /* GPIO output to mss */ + qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_1_out 0 0>; + status = "ok"; }; @@ -1619,6 +1629,7 @@ #include "sdxprairie-aqc.dtsi" #include "sdxprairie-thermal.dtsi" #include "sdxprairie-qcom-smmu.dtsi" +#include "sdxprairie-smp2p.dtsi" &gdsc_usb30 { status = "ok"; From feef0394649d381f50fd798c3e736c58d75cd3c5 Mon Sep 17 00:00:00 2001 From: Puranam V G Tejaswi Date: Fri, 24 Jul 2020 08:54:54 +0530 Subject: [PATCH 238/592] msm: kgsl: Fix possible use-after-free while adding context to active list Consider a scenario where a context is valid when the check is made in adreno_dispatcher_queue_cmds(), but by the time we reach _track_context(), context has been detached. We would try to delete the entry from the active context list as part of detaching the context though the entry is not added yet. Now in _track_context() the context is actually added. When the context is finally destroyed, we would be left with invalid entry in the list. Next time when a context is added, an attempt would be made to use a freed entry. Fix this by moving the entry deletion part under drawctxt lock. Change-Id: Idab7cbf10987598b3e6395b2d50c20d1990d1f02 Signed-off-by: Puranam V G Tejaswi --- drivers/gpu/msm/adreno_drawctxt.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c index df8e8acecb4c..aa945a4bd302 100644 --- a/drivers/gpu/msm/adreno_drawctxt.c +++ b/drivers/gpu/msm/adreno_drawctxt.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2002,2007-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2002,2007-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -487,11 +487,12 @@ void adreno_drawctxt_detach(struct kgsl_context *context) drawctxt = ADRENO_CONTEXT(context); rb = drawctxt->rb; + spin_lock(&drawctxt->lock); + spin_lock(&adreno_dev->active_list_lock); list_del_init(&drawctxt->active_node); spin_unlock(&adreno_dev->active_list_lock); - spin_lock(&drawctxt->lock); count = drawctxt_detach_drawobjs(drawctxt, list); spin_unlock(&drawctxt->lock); From 5a8f1488038a8a8dfa657360fa4d498e14345291 Mon Sep 17 00:00:00 2001 From: Vivek Pernamitta Date: Fri, 10 Jul 2020 13:11:37 +0530 Subject: [PATCH 239/592] mhi: core: Error handling for pending packets in mission_mode Clearing pending packets global reference count in mhi_controller only when channel is in mission mode in error handling mechanism with command completion timeout in mhi prepeare channel Change-Id: Ib86b4f2a2ff5f28d27cf6174f65987d4f9ca1aea Signed-off-by: Vivek Pernamitta --- drivers/bus/mhi/core/mhi_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/bus/mhi/core/mhi_main.c b/drivers/bus/mhi/core/mhi_main.c index e4c3e1fceebe..6f1377aabc6b 100644 --- a/drivers/bus/mhi/core/mhi_main.c +++ b/drivers/bus/mhi/core/mhi_main.c @@ -1912,7 +1912,8 @@ int mhi_prepare_channel(struct mhi_controller *mhi_cntrl, return 0; error_dec_pendpkt: - atomic_dec(&mhi_cntrl->pending_pkts); + if (in_mission_mode) + atomic_dec(&mhi_cntrl->pending_pkts); error_pm_state: if (!mhi_chan->offload_ch) mhi_deinit_chan_ctxt(mhi_cntrl, mhi_chan); From da74c853e9ead266c3b415529e1b79c8f3b36626 Mon Sep 17 00:00:00 2001 From: Suresh Kumar Allam Date: Tue, 14 Jul 2020 11:00:19 +0530 Subject: [PATCH 240/592] arm: dts: qcom: add tz_apps and qseecom Add tz apps mem carve out and enable qseecom on mdm9607. Change-Id: I593697c2ba3e20a90a269641a5fd0b5bddd69ccb Signed-off-by: Suresh Kumar Allam Signed-off-by: Haribabu Gattem --- arch/arm64/boot/dts/qcom/mdm9607.dtsi | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/mdm9607.dtsi b/arch/arm64/boot/dts/qcom/mdm9607.dtsi index 23c160c7fa8c..a21deb71ecec 100644 --- a/arch/arm64/boot/dts/qcom/mdm9607.dtsi +++ b/arch/arm64/boot/dts/qcom/mdm9607.dtsi @@ -57,6 +57,12 @@ reg = <0x87c00000 0x400000>; }; + tz_apps_mem: tz_apps_region@0 { + compatible = "removed-dma-pool"; + no-map; + reg = <0x88000000 0x500000>; + }; + audio_mem: audio_region@0 { compatible = "shared-dma-pool"; reusable; @@ -69,7 +75,7 @@ reusable; alignment = <0x400000>; size = <0x0400000>; - status = "disabled"; + status = "ok"; }; }; @@ -1675,7 +1681,7 @@ qcom_seecom: qseecom@87a80000 { compatible = "qcom,qseecom"; - reg = <0x87a80000 0x100000>; + reg = <0x88000000 0x500000>; reg-names = "secapp-region"; memory-region = <&qseecom_mem>; qcom,hlos-num-ce-hw-instances = <1>; @@ -1697,7 +1703,7 @@ clock-names = "core_clk_src", "core_clk", "iface_clk", "bus_clk"; qcom,ce-opp-freq = <100000000>; - status = "disabled"; + status = "ok"; }; qcom_tzlog: tz-log@8600720 { From 6df9995df19e349dad713a729d6e293adf73dc95 Mon Sep 17 00:00:00 2001 From: Manaf Meethalavalappu Pallikunhi Date: Fri, 24 Jul 2020 12:34:39 +0530 Subject: [PATCH 241/592] drivers: thermal: qmi_cooling: Add support for modem_v2x cooling device Add support for 'modem_v2x' QMI cooling device to qmi cooling device driver. This cooling device can be used to mitigate modem CV2X at high temperature via qmi interface. Change-Id: Ie6cf8e2174afbc4a25619e1002a5c0937fd5ba41 Signed-off-by: Manaf Meethalavalappu Pallikunhi --- Documentation/devicetree/bindings/thermal/qti-qmi-cdev.txt | 6 ++++++ drivers/thermal/qcom/qmi_cooling.c | 6 +++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/thermal/qti-qmi-cdev.txt b/Documentation/devicetree/bindings/thermal/qti-qmi-cdev.txt index 15d0f4a607b1..0e136972f5f7 100644 --- a/Documentation/devicetree/bindings/thermal/qti-qmi-cdev.txt +++ b/Documentation/devicetree/bindings/thermal/qti-qmi-cdev.txt @@ -52,6 +52,7 @@ Subsystem properties: "mmw_skin1" -> MMW skin mitigation device1, "mmw_skin2" -> MMW skin mitigation device2, "mmw_skin3" -> MMW skin mitigation device3, + "modem_v2x" -> modem CV2X mitigation device, "cpr_cold" -> for cpr restriction, "cdsp_sw" -> for CDSP DCVS mitigation device, "cdsp_hw" -> for CDSP hardware mitigation device. @@ -95,6 +96,11 @@ Example: qcom,qmi-dev-name = "cpr_cold"; #cooling-cells = <2>; }; + + modem_v2x: modem_v2x { + qcom,qmi-dev-name = "modem_v2x"; + #cooling-cells = <2>; + }; }; adsp { diff --git a/drivers/thermal/qcom/qmi_cooling.c b/drivers/thermal/qcom/qmi_cooling.c index 2309f029c859..a9e0d73784ff 100644 --- a/drivers/thermal/qcom/qmi_cooling.c +++ b/drivers/thermal/qcom/qmi_cooling.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -133,6 +133,10 @@ static struct qmi_dev_info device_clients[] = { .dev_name = "mmw_skin3", .type = QMI_CDEV_MAX_LIMIT_TYPE, }, + { + .dev_name = "modem_v2x", + .type = QMI_CDEV_MAX_LIMIT_TYPE, + }, { .dev_name = "cdsp_sw", .type = QMI_CDEV_MAX_LIMIT_TYPE, From e2e9fd5fe17f093096191b28ac5dd59af88dd0b0 Mon Sep 17 00:00:00 2001 From: Manaf Meethalavalappu Pallikunhi Date: Wed, 22 Jul 2020 21:20:44 +0530 Subject: [PATCH 242/592] ARM: dts: msm: Add and enable Tj based modem_v2x mitigation for SA515 Add support for modem_v2x cooling device and enable Tj based modem_v2x mitigation for SA515 variants based on latest recommendation. Change-Id: I825fa7a09928bf401daab088abbe8761839281dd Signed-off-by: Manaf Meethalavalappu Pallikunhi --- arch/arm64/boot/dts/qcom/sa515m-ccard.dtsi | 54 ++++++++++++++++++ .../arm64/boot/dts/qcom/sa515m-flashless.dtsi | 56 +++++++++++++++++++ arch/arm64/boot/dts/qcom/sa515m-v2-ttp.dtsi | 56 +++++++++++++++++++ .../boot/dts/qcom/sdxprairie-v2-dsda-cdp.dts | 56 +++++++++++++++++++ 4 files changed, 222 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sa515m-ccard.dtsi b/arch/arm64/boot/dts/qcom/sa515m-ccard.dtsi index 2adf53c610e1..6504d82f6f3a 100644 --- a/arch/arm64/boot/dts/qcom/sa515m-ccard.dtsi +++ b/arch/arm64/boot/dts/qcom/sa515m-ccard.dtsi @@ -82,6 +82,15 @@ gpios = <&tlmm 32 GPIO_ACTIVE_HIGH>; status = "okay"; }; + + qmi-tmd-devices { + modem { + modem_v2x: modem_v2x { + qcom,qmi-dev-name = "modem_v2x"; + #cooling-cells = <2>; + }; + }; + }; }; &mpss_adsp_mem { @@ -121,6 +130,51 @@ }; }; }; + + mdm-core-0-v2x-step { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens0 6>; + thermal-governor = "step_wise"; + wake-capable-sensor; + + trips { + tj_v2x_config0: active-config0 { + temperature = <105000>; + hysteresis = <5000>; + type = "passive"; + }; + + tj_v2x_config1: active-config1 { + temperature = <110000>; + hysteresis = <5000>; + type = "passive"; + }; + + tj_v2x_config2: active-config2 { + temperature = <115000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + + cooling-maps { + modem_tj0_v2x_cdev { + trip = <&tj_v2x_config0>; + cooling-device = <&modem_v2x 1 1>; + }; + + modem_tj1_v2x_cdev { + trip = <&tj_v2x_config1>; + cooling-device = <&modem_v2x 2 2>; + }; + + modem_tj2_v2x_cdev { + trip = <&tj_v2x_config2>; + cooling-device = <&modem_v2x 3 3>; + }; + }; + }; }; &usb { diff --git a/arch/arm64/boot/dts/qcom/sa515m-flashless.dtsi b/arch/arm64/boot/dts/qcom/sa515m-flashless.dtsi index 1c1a676c0413..3445ca95d43a 100644 --- a/arch/arm64/boot/dts/qcom/sa515m-flashless.dtsi +++ b/arch/arm64/boot/dts/qcom/sa515m-flashless.dtsi @@ -20,6 +20,17 @@ qcom,auto-boot; }; +&soc { + qmi-tmd-devices { + modem { + modem_v2x: modem_v2x { + qcom,qmi-dev-name = "modem_v2x"; + #cooling-cells = <2>; + }; + }; + }; +}; + &thermal_zones { /* update Tj thresholds */ mdm-core-0-step { @@ -40,4 +51,49 @@ }; }; }; + + mdm-core-0-v2x-step { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens0 6>; + thermal-governor = "step_wise"; + wake-capable-sensor; + + trips { + tj_v2x_config0: active-config0 { + temperature = <105000>; + hysteresis = <5000>; + type = "passive"; + }; + + tj_v2x_config1: active-config1 { + temperature = <110000>; + hysteresis = <5000>; + type = "passive"; + }; + + tj_v2x_config2: active-config2 { + temperature = <115000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + + cooling-maps { + modem_tj0_v2x_cdev { + trip = <&tj_v2x_config0>; + cooling-device = <&modem_v2x 1 1>; + }; + + modem_tj1_v2x_cdev { + trip = <&tj_v2x_config1>; + cooling-device = <&modem_v2x 2 2>; + }; + + modem_tj2_v2x_cdev { + trip = <&tj_v2x_config2>; + cooling-device = <&modem_v2x 3 3>; + }; + }; + }; }; diff --git a/arch/arm64/boot/dts/qcom/sa515m-v2-ttp.dtsi b/arch/arm64/boot/dts/qcom/sa515m-v2-ttp.dtsi index e35648a1520a..b8547fbf19c9 100644 --- a/arch/arm64/boot/dts/qcom/sa515m-v2-ttp.dtsi +++ b/arch/arm64/boot/dts/qcom/sa515m-v2-ttp.dtsi @@ -17,6 +17,17 @@ reg = <0x90800000 0xf800000>; }; +&soc { + qmi-tmd-devices { + modem { + modem_v2x: modem_v2x { + qcom,qmi-dev-name = "modem_v2x"; + #cooling-cells = <2>; + }; + }; + }; +}; + /* delete pm8150b nodes */ &thermal_zones { /delete-node/ pm8150b-wp-therm; @@ -50,6 +61,51 @@ }; }; }; + + mdm-core-0-v2x-step { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens0 6>; + thermal-governor = "step_wise"; + wake-capable-sensor; + + trips { + tj_v2x_config0: active-config0 { + temperature = <105000>; + hysteresis = <5000>; + type = "passive"; + }; + + tj_v2x_config1: active-config1 { + temperature = <110000>; + hysteresis = <5000>; + type = "passive"; + }; + + tj_v2x_config2: active-config2 { + temperature = <115000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + + cooling-maps { + modem_tj0_v2x_cdev { + trip = <&tj_v2x_config0>; + cooling-device = <&modem_v2x 1 1>; + }; + + modem_tj1_v2x_cdev { + trip = <&tj_v2x_config1>; + cooling-device = <&modem_v2x 2 2>; + }; + + modem_tj2_v2x_cdev { + trip = <&tj_v2x_config2>; + cooling-device = <&modem_v2x 3 3>; + }; + }; + }; }; &usb { diff --git a/arch/arm64/boot/dts/qcom/sdxprairie-v2-dsda-cdp.dts b/arch/arm64/boot/dts/qcom/sdxprairie-v2-dsda-cdp.dts index 99e9f86f5f14..cd82608a9af7 100644 --- a/arch/arm64/boot/dts/qcom/sdxprairie-v2-dsda-cdp.dts +++ b/arch/arm64/boot/dts/qcom/sdxprairie-v2-dsda-cdp.dts @@ -22,6 +22,17 @@ qcom,board-id = <0x6010001 0x0>; }; +&soc { + qmi-tmd-devices { + modem { + modem_v2x: modem_v2x { + qcom,qmi-dev-name = "modem_v2x"; + #cooling-cells = <2>; + }; + }; + }; +}; + /* delete pm8150b nodes */ &thermal_zones { /delete-node/ pm8150b-wp-therm; @@ -55,6 +66,51 @@ }; }; }; + + mdm-core-0-v2x-step { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens0 6>; + thermal-governor = "step_wise"; + wake-capable-sensor; + + trips { + tj_v2x_config0: active-config0 { + temperature = <105000>; + hysteresis = <5000>; + type = "passive"; + }; + + tj_v2x_config1: active-config1 { + temperature = <110000>; + hysteresis = <5000>; + type = "passive"; + }; + + tj_v2x_config2: active-config2 { + temperature = <115000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + + cooling-maps { + modem_tj0_v2x_cdev { + trip = <&tj_v2x_config0>; + cooling-device = <&modem_v2x 1 1>; + }; + + modem_tj1_v2x_cdev { + trip = <&tj_v2x_config1>; + cooling-device = <&modem_v2x 2 2>; + }; + + modem_tj2_v2x_cdev { + trip = <&tj_v2x_config2>; + cooling-device = <&modem_v2x 3 3>; + }; + }; + }; }; &usb { From 061cfeb8b0425ac34cca11c3cf4f37c91133d697 Mon Sep 17 00:00:00 2001 From: Akshay Adiga Date: Wed, 22 Jul 2020 11:17:07 +0530 Subject: [PATCH 243/592] sx150x-pinctrl: Avoid i2c transfer during kexec machine_crash_shutdown() calls irq_bus_sync_unlock() with local irq disabled. sx150x_irq_bus_sync tries to transfer over i2c bus and hangs because of disabled irqs. Add panic handler, so that sx150x_irq_bus_sync_unlock can return before write to iomap register. Mulitple instances of sx150x device may be present, hence a global flag to indicate machine_crash_shutdown() context. Change-Id: If992f730ba36b81b2a231f3605673e8bae278d16 Signed-off-by: Akshay Adiga --- drivers/pinctrl/pinctrl-sx150x.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/drivers/pinctrl/pinctrl-sx150x.c b/drivers/pinctrl/pinctrl-sx150x.c index 75d5a096676d..8d28839de8a0 100644 --- a/drivers/pinctrl/pinctrl-sx150x.c +++ b/drivers/pinctrl/pinctrl-sx150x.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. * * Copyright (c) 2016, BayLibre, SAS. All rights reserved. * Author: Neil Armstrong @@ -40,6 +40,9 @@ #include "pinconf.h" #include "pinctrl-utils.h" +static bool in_kexec_panic; +static struct notifier_block *panic_block; + /* The chip models of sx150x */ enum { SX150X_123 = 0, @@ -581,6 +584,14 @@ static void sx150x_irq_bus_sync_unlock(struct irq_data *d) struct sx150x_pinctrl *pctl = gpiochip_get_data(irq_data_get_irq_chip_data(d)); + /* In crash kexec panic path interrupt is disabled. + * Writing to regmap will need interrupt/polling mode, + * as it goes though i2c. + */ + if (in_kexec_panic) { + mutex_unlock(&pctl->lock); + return; + } regmap_write(pctl->regmap, pctl->data->reg_irq_mask, pctl->irq.masked); regmap_write(pctl->regmap, pctl->data->reg_sense, pctl->irq.sense); mutex_unlock(&pctl->lock); @@ -1102,6 +1113,14 @@ const struct regmap_config sx150x_regmap_config = { .volatile_reg = sx150x_reg_volatile, }; +static int sx150x_panic_handler(struct notifier_block *this, + unsigned long event, void *ptr) +{ + if (crash_kexec_post_notifiers) + in_kexec_panic = 1; + return NOTIFY_DONE; +} + static int sx150x_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -1301,6 +1320,12 @@ static struct i2c_driver sx150x_driver = { static int __init sx150x_init(void) { + panic_block = kzalloc(sizeof(*panic_block), GFP_KERNEL); + if (!panic_block) + return -ENOMEM; + panic_block->notifier_call = sx150x_panic_handler; + atomic_notifier_chain_register(&panic_notifier_list, + panic_block); return i2c_add_driver(&sx150x_driver); } subsys_initcall(sx150x_init); From 96a9e10b1848e71895fe3c47fe93b2ffe7db19ae Mon Sep 17 00:00:00 2001 From: Arun Prakash Date: Mon, 20 Jul 2020 23:50:48 +0530 Subject: [PATCH 244/592] ARM: dts: msm: Add uart support for kdump kernel on sa8155 Add uart and all dependent DT entries for uart to work on kdump kernel. Change-Id: Iefcb3ed2cb5e5c66e4e8d717f3975cbed71e44d0 Signed-off-by: Arun Prakash --- arch/arm64/boot/dts/qcom/sa8155-capture.dtsi | 208 ++++++++++++++++++- 1 file changed, 200 insertions(+), 8 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sa8155-capture.dtsi b/arch/arm64/boot/dts/qcom/sa8155-capture.dtsi index 374be7156b3a..5c3d5c1c20ea 100644 --- a/arch/arm64/boot/dts/qcom/sa8155-capture.dtsi +++ b/arch/arm64/boot/dts/qcom/sa8155-capture.dtsi @@ -18,6 +18,10 @@ #include #include #include +#include +#include +#include + / { model = "Qualcomm Technologies, Inc. SM8150"; @@ -82,6 +86,8 @@ }; }; +#include "sm8150-gdsc.dtsi" + &soc { status = "ok"; #address-cells = <0x1>; @@ -148,13 +154,6 @@ 0x18100 0x18100 0x18100 0x18100>; }; - qcom,qupv3_1_geni_se@ac0000 { - compatible = "qcom,qupv3-geni-se"; - reg = <0xac0000 0x6000>; - qcom,bus-mas-id = <0x98>; - qcom,bus-slv-id = <0x200>; - }; - apps_rsc: mailbox@18220000 { compatible = "qcom,tcs-drv"; status="ok"; @@ -168,8 +167,201 @@ , ; }; + + clock_rpmh: qcom,rpmhclk { + compatible = "qcom,rpmh-clk-sm8150"; + mboxes = <&apps_rsc 0>; + mbox-names = "apps"; + #clock-cells = <1>; + }; + + disp_rsc: mailbox@af20000 { + compatible = "qcom,tcs-drv"; + label = "display_rsc"; + reg = <0xaf20000 0x100>, <0xaf21c00 0x3000>; + interrupts = <0 129 0>; + #mbox-cells = <1>; + qcom,drv-id = <0>; + qcom,tcs-config = , + , + , + ; + }; + + qmp_aop: qcom,qmp-aop@c300000 { + compatible = "qcom,qmp-mbox"; + reg = <0xc300000 0x1000>, <0x17c0000C 0x4>; + reg-names = "msgram", "irq-reg-base"; + qcom,irq-mask = <0x1>; + interrupts = ; + + label = "aop"; + qcom,early-boot; + priority = <0>; + mbox-desc-offset = <0x0>; + #mbox-cells = <1>; + }; + + cmd_db: qcom,cmd-db@c3f000c { + compatible = "qcom,cmd-db"; + reg = <0xc3f000c 8>; + }; + + qupv3_1: qcom,qupv3_1_geni_se@ac0000 { + compatible = "qcom,qupv3-geni-se"; + reg = <0xac0000 0x6000>; + qcom,bus-mas-id = ; + qcom,bus-slv-id = ; + qcom,iommu-s1-bypass; + + iommu_qupv3_1_geni_se_cb: qcom,iommu_qupv3_1_geni_se_cb { + compatible = "qcom,qupv3-geni-se-cb"; + iommus = <&apps_smmu 0x603 0x0>; + }; + + }; + /* 2-wire UART */ + + /* Debug UART Instance for CDP/MTP platform */ + qupv3_se12_2uart: qcom,qup_uart@0xa90000 { + compatible = "qcom,msm-geni-console"; + reg = <0xa90000 0x4000>; + reg-names = "se_phys"; + clock-names = "se-clk", "m-ahb", "s-ahb"; + clocks = <&clock_gcc GCC_QUPV3_WRAP1_S4_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_1_M_AHB_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_1_S_AHB_CLK>; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&qupv3_se12_2uart_active>; + pinctrl-1 = <&qupv3_se12_2uart_sleep>; + interrupts = ; + qcom,wrapper-core = <&qupv3_1>; + status = "ok"; + }; + + apps_smmu: apps-smmu@0x15000000 { + compatible = "qcom,qsmmu-v500"; + reg = <0x15000000 0x100000>, + <0x15182000 0x20>; + reg-names = "base", "tcu-base"; + #iommu-cells = <2>; + qcom,skip-init; + qcom,use-3-lvl-tables; + qcom,disable-atos; + #global-interrupts = <1>; + #size-cells = <1>; + #address-cells = <1>; + ranges; + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + qcom,msm-bus,name = "apps_smmu"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,active-only; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + , + , + <0 0>, + , + , + <0 1000>; + }; +}; + +&apps_smmu { + qcom,actlr = + /* HF0 and HF1 TBUs: +3 deep PF */ + <0x800 0x7ff 0x103>, + + /* SF TBU: +3 deep PF */ + <0x2000 0x3ff 0x103>, + + /* NPU SIDs: +15 deep PF */ + <0x1480 0x3 0x303>, + <0x1484 0x1 0x303>, + <0x1080 0x3 0x303>, + <0x1084 0x1 0x303>; }; #include "sa8155-regulator.dtsi" #include "sm8150-pinctrl.dtsi" - +#include "sm8150-bus.dtsi" From d3ff13ccf45cf62536ae678e10201e18e66ab0f8 Mon Sep 17 00:00:00 2001 From: Vasantha Balla Date: Thu, 2 Jul 2020 15:56:00 +0530 Subject: [PATCH 245/592] msm: vidc: fix deadlock between queue and flush buffer handling qbuf ioctl acquired bufq[port].lock in one thread and flush call acquired registeredbufs.lock in another thread. So thread-1 is waiting for registeredbufs.lock & thread-2 is waiting for bufq[port].lock i.e leading to deadlock. So added change to avoid above mentioned deadlock. Change-Id: Ie21984fdb562ca7a09f801f036f3a78429ceab94 Signed-off-by: Govindaraj Rajagopal Signed-off-by: Vasantha Balla --- drivers/media/platform/msm/vidc/msm_vidc.c | 22 ++++---- .../media/platform/msm/vidc/msm_vidc_common.c | 51 +++++++++++++------ .../platform/msm/vidc/msm_vidc_internal.h | 4 +- .../media/platform/msm/vidc/vidc_hfi_api.h | 7 ++- 4 files changed, 50 insertions(+), 34 deletions(-) diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c index 740df57d2ead..dbcc9434185d 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc.c +++ b/drivers/media/platform/msm/vidc/msm_vidc.c @@ -521,6 +521,15 @@ int msm_vidc_qbuf(void *instance, struct v4l2_buffer *b) return -EINVAL; } + q = msm_comm_get_vb2q(inst, b->type); + if (!q) { + dprintk(VIDC_ERR, + "Failed to find buffer queue for type = %d\n", b->type); + return -EINVAL; + } + mutex_lock(&q->lock); + + for (i = 0; i < b->length; i++) { b->m.planes[i].m.fd = b->m.planes[i].reserved[0]; b->m.planes[i].data_offset = b->m.planes[i].reserved[1]; @@ -545,19 +554,11 @@ int msm_vidc_qbuf(void *instance, struct v4l2_buffer *b) tag_data.output_tag = b->m.planes[0].reserved[6]; msm_comm_store_tags(inst, &tag_data); - q = msm_comm_get_vb2q(inst, b->type); - if (!q) { - dprintk(VIDC_ERR, - "Failed to find buffer queue for type = %d\n", b->type); - return -EINVAL; - } - - mutex_lock(&q->lock); rc = vb2_qbuf(&q->vb2_bufq, b); - mutex_unlock(&q->lock); if (rc) dprintk(VIDC_ERR, "Failed to qbuf, %d\n", rc); + mutex_unlock(&q->lock); return rc; } EXPORT_SYMBOL(msm_vidc_qbuf); @@ -1879,7 +1880,6 @@ void *msm_vidc_open(int core_id, int session_type) mutex_init(&inst->bufq[CAPTURE_PORT].lock); mutex_init(&inst->bufq[OUTPUT_PORT].lock); mutex_init(&inst->lock); - mutex_init(&inst->flush_lock); INIT_MSM_VIDC_LIST(&inst->scratchbufs); INIT_MSM_VIDC_LIST(&inst->freqs); @@ -2003,7 +2003,6 @@ fail_bufq_capture: mutex_destroy(&inst->bufq[CAPTURE_PORT].lock); mutex_destroy(&inst->bufq[OUTPUT_PORT].lock); mutex_destroy(&inst->lock); - mutex_destroy(&inst->flush_lock); DEINIT_MSM_VIDC_LIST(&inst->scratchbufs); DEINIT_MSM_VIDC_LIST(&inst->persistbufs); @@ -2157,7 +2156,6 @@ int msm_vidc_destroy(struct msm_vidc_inst *inst) mutex_destroy(&inst->bufq[CAPTURE_PORT].lock); mutex_destroy(&inst->bufq[OUTPUT_PORT].lock); mutex_destroy(&inst->lock); - mutex_destroy(&inst->flush_lock); msm_vidc_debugfs_deinit_inst(inst); diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c index 9bac7d10c4d7..516af3055a73 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_common.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c @@ -2079,7 +2079,11 @@ static void handle_session_flush(enum hal_command_response cmd, void *data) return; } - mutex_lock(&inst->flush_lock); + if (response->data.flush_type & HAL_FLUSH_INPUT) + mutex_lock(&inst->bufq[OUTPUT_PORT].lock); + if (response->data.flush_type & HAL_FLUSH_OUTPUT) + mutex_lock(&inst->bufq[CAPTURE_PORT].lock); + if (msm_comm_get_stream_output_mode(inst) == HAL_VIDEO_DECODER_SECONDARY) { @@ -2122,7 +2126,11 @@ static void handle_session_flush(enum hal_command_response cmd, void *data) v4l2_event_queue_fh(&inst->event_handler, &flush_event); exit: - mutex_unlock(&inst->flush_lock); + if (response->data.flush_type & HAL_FLUSH_OUTPUT) + mutex_unlock(&inst->bufq[CAPTURE_PORT].lock); + if (response->data.flush_type & HAL_FLUSH_INPUT) + mutex_unlock(&inst->bufq[OUTPUT_PORT].lock); + put_inst(inst); } @@ -2331,7 +2339,7 @@ struct vb2_buffer *msm_comm_get_vb_using_vidc_buffer( return NULL; } - mutex_lock(&inst->bufq[port].lock); + WARN_ON(!mutex_is_locked(&inst->bufq[port].lock)); found = false; q = &inst->bufq[port].vb2_bufq; if (!q->streaming) { @@ -2347,7 +2355,6 @@ struct vb2_buffer *msm_comm_get_vb_using_vidc_buffer( } } unlock: - mutex_unlock(&inst->bufq[port].lock); if (!found) { print_vidc_buffer(VIDC_ERR, "vb2 not found for", inst, mbuf); return NULL; @@ -2362,6 +2369,7 @@ int msm_comm_vb2_buffer_done(struct msm_vidc_inst *inst, struct vb2_buffer *vb2; struct vb2_v4l2_buffer *vbuf; u32 i, port; + int rc = 0; if (!inst || !mbuf) { dprintk(VIDC_ERR, "%s: invalid params %pK %pK\n", @@ -2378,16 +2386,20 @@ int msm_comm_vb2_buffer_done(struct msm_vidc_inst *inst, else return -EINVAL; - vb2 = msm_comm_get_vb_using_vidc_buffer(inst, mbuf); - if (!vb2) - return -EINVAL; - /* * access vb2 buffer under q->lock and if streaming only to * ensure the buffer was not free'd by vb2 framework while * we are accessing it here. */ mutex_lock(&inst->bufq[port].lock); + vb2 = msm_comm_get_vb_using_vidc_buffer(inst, mbuf); + if (!vb2) { + rc = -EINVAL; + dprintk(VIDC_ERR, "%s:port %d buffer not found\n", + __func__, port); + goto unlock; + } + if (inst->bufq[port].vb2_bufq.streaming) { vbuf = to_vb2_v4l2_buffer(vb2); vbuf->flags = mbuf->vvb.flags; @@ -2403,9 +2415,9 @@ int msm_comm_vb2_buffer_done(struct msm_vidc_inst *inst, dprintk(VIDC_ERR, "%s: port %d is not streaming\n", __func__, port); } +unlock: mutex_unlock(&inst->bufq[port].lock); - - return 0; + return rc; } bool heic_encode_session_supported(struct msm_vidc_inst *inst) @@ -5316,7 +5328,11 @@ int msm_comm_flush(struct msm_vidc_inst *inst, u32 flags) return 0; } - mutex_lock(&inst->flush_lock); + if (ip_flush) + mutex_lock(&inst->bufq[OUTPUT_PORT].lock); + if (op_flush) + mutex_lock(&inst->bufq[CAPTURE_PORT].lock); + /* enable in flush */ inst->in_flush = true; @@ -5370,7 +5386,12 @@ int msm_comm_flush(struct msm_vidc_inst *inst, u32 flags) rc = call_hfi_op(hdev, session_flush, inst->session, HAL_FLUSH_OUTPUT); } - mutex_unlock(&inst->flush_lock); + + if (op_flush) + mutex_unlock(&inst->bufq[CAPTURE_PORT].lock); + if (ip_flush) + mutex_unlock(&inst->bufq[OUTPUT_PORT].lock); + if (rc) { dprintk(VIDC_ERR, "Sending flush to firmware failed, flush out all buffers\n"); @@ -6453,7 +6474,6 @@ int msm_comm_flush_vidc_buffer(struct msm_vidc_inst *inst, else return -EINVAL; - mutex_lock(&inst->bufq[port].lock); if (inst->bufq[port].vb2_bufq.streaming) { vb->planes[0].bytesused = 0; vb2_buffer_done(vb, VB2_BUF_STATE_DONE); @@ -6461,7 +6481,6 @@ int msm_comm_flush_vidc_buffer(struct msm_vidc_inst *inst, dprintk(VIDC_ERR, "%s: port %d is not streaming\n", __func__, port); } - mutex_unlock(&inst->bufq[port].lock); return 0; } @@ -6815,7 +6834,7 @@ void handle_release_buffer_reference(struct msm_vidc_inst *inst, int i = 0; u32 planes[VIDEO_MAX_PLANES] = {0}; - mutex_lock(&inst->flush_lock); + mutex_lock(&inst->bufq[CAPTURE_PORT].lock); mutex_lock(&inst->registeredbufs.lock); found = false; /* check if mbuf was not removed by any chance */ @@ -6904,7 +6923,7 @@ unlock: print_vidc_buffer(VIDC_ERR, "rbr qbuf failed", inst, mbuf); } - mutex_unlock(&inst->flush_lock); + mutex_unlock(&inst->bufq[CAPTURE_PORT].lock); } int msm_comm_unmap_vidc_buffer(struct msm_vidc_inst *inst, diff --git a/drivers/media/platform/msm/vidc/msm_vidc_internal.h b/drivers/media/platform/msm/vidc/msm_vidc_internal.h index 21453f6a6c8a..b89bb08b3ae5 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_internal.h +++ b/drivers/media/platform/msm/vidc/msm_vidc_internal.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -442,7 +442,7 @@ struct msm_vidc_core { struct msm_vidc_inst { struct list_head list; - struct mutex sync_lock, lock, flush_lock; + struct mutex sync_lock, lock; struct msm_vidc_core *core; enum session_type session_type; void *session; diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h index 8950bcf80677..798f57ba8bc2 100644 --- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h +++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h @@ -995,10 +995,9 @@ struct hal_fw_info { }; enum hal_flush { - HAL_FLUSH_INPUT, - HAL_FLUSH_OUTPUT, - HAL_FLUSH_ALL, - HAL_UNUSED_FLUSH = 0x10000000, + HAL_FLUSH_INPUT = BIT(0), + HAL_FLUSH_OUTPUT = BIT(1), + HAL_FLUSH_ALL = HAL_FLUSH_INPUT | HAL_FLUSH_OUTPUT, }; enum hal_event_type { From 40001d5642a544331e5fd6f29426908280cfd931 Mon Sep 17 00:00:00 2001 From: Ajay Agarwal Date: Mon, 29 Jun 2020 13:39:29 +0530 Subject: [PATCH 246/592] usb: dwc3-msm: Add markers for peripheral bus resume Add prints and markers for peripheral bus resume. While at it, also fix USB resume print in composite driver. Change-Id: Idaaba41e59ee2e93c1fd5956d352bdce673247b3 Signed-off-by: Ajay Agarwal --- drivers/usb/dwc3/dwc3-msm.c | 13 +++++++++++++ drivers/usb/gadget/composite.c | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index 9bfad4bfbb02..f35b1a0b42f5 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -47,6 +47,7 @@ #include #include #include +#include #include "power.h" #include "core.h" @@ -3294,6 +3295,12 @@ static irqreturn_t msm_dwc3_pwr_irq(int irq, void *data) dwc->t_pwr_evt_irq = ktime_get(); dev_dbg(mdwc->dev, "%s received\n", __func__); + + if (mdwc->drd_state == DRD_STATE_PERIPHERAL_SUSPEND) { + dev_info(mdwc->dev, "USB Resume start\n"); + place_marker("M - USB device resume started"); + } + /* * When in Low Power Mode, can't read PWR_EVNT_IRQ_STAT_REG to acertain * which interrupts have been triggered, as the clocks are disabled. @@ -5161,6 +5168,12 @@ static int dwc3_msm_pm_resume(struct device *dev) flush_workqueue(mdwc->dwc3_wq); atomic_set(&mdwc->pm_suspended, 0); + if (atomic_read(&dwc->in_lpm) && + mdwc->drd_state == DRD_STATE_PERIPHERAL_SUSPEND) { + dev_info(mdwc->dev, "USB Resume start\n"); + place_marker("M - USB device resume started"); + } + if (!dwc->ignore_wakeup_src_in_hostmode || !mdwc->in_host_mode) { /* kick in otg state machine */ queue_work(mdwc->dwc3_wq, &mdwc->resume_work); diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 73f1fd35e386..ad9f3f423e61 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -2431,7 +2431,7 @@ void composite_resume(struct usb_gadget *gadget) /* REVISIT: should we have config level * suspend/resume callbacks? */ - INFO(cdev, "USB Resume\n"); + INFO(cdev, "USB Resume end\n"); place_marker("M - USB device is resumed"); if (cdev->driver->resume) cdev->driver->resume(cdev); From d85ee47a654d754ff70b2744f2dd7b7ea8be1bed Mon Sep 17 00:00:00 2001 From: Venkata Rao Kakani Date: Fri, 24 Jul 2020 16:44:41 +0530 Subject: [PATCH 247/592] ARM: dts: msm: enable usb suspend function in host mode Enable usb suspend functionality when usb mode is host for automotive linux guests. Change-Id: I9f3b869ac94d93974500244eec7aa6123a39ebc8 Signed-off-by: Venkata Rao Kakani --- arch/arm64/boot/dts/qcom/sa6155p-vm-usb.dtsi | 3 ++- arch/arm64/boot/dts/qcom/sa8155-vm-usb.dtsi | 4 ++-- arch/arm64/boot/dts/qcom/sa8195-vm-usb.dtsi | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sa6155p-vm-usb.dtsi b/arch/arm64/boot/dts/qcom/sa6155p-vm-usb.dtsi index ef2dcb739f35..b74f80add290 100644 --- a/arch/arm64/boot/dts/qcom/sa6155p-vm-usb.dtsi +++ b/arch/arm64/boot/dts/qcom/sa6155p-vm-usb.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -58,6 +58,7 @@ 0x1a4>; /* GSI_IF_STS */ qcom,dwc-usb3-msm-tx-fifo-size = <21288>; qcom,pm-qos-latency = <61>; + qcom,ignore-wakeup-src-in-hostmode; status = "disabled"; dwc3@a600000 { compatible = "snps,dwc3"; diff --git a/arch/arm64/boot/dts/qcom/sa8155-vm-usb.dtsi b/arch/arm64/boot/dts/qcom/sa8155-vm-usb.dtsi index 90366d5cb5db..80c4744e12e1 100644 --- a/arch/arm64/boot/dts/qcom/sa8155-vm-usb.dtsi +++ b/arch/arm64/boot/dts/qcom/sa8155-vm-usb.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -58,7 +58,7 @@ 0x144 /* GSI_RING_BASE_ADDR_H */ 0x1a4>; /* GSI_IF_STS */ qcom,dwc-usb3-msm-tx-fifo-size = <27696>; - + qcom,ignore-wakeup-src-in-hostmode; status = "disabled"; dwc3@a600000 { diff --git a/arch/arm64/boot/dts/qcom/sa8195-vm-usb.dtsi b/arch/arm64/boot/dts/qcom/sa8195-vm-usb.dtsi index 1035d25de40b..01e507a282e6 100644 --- a/arch/arm64/boot/dts/qcom/sa8195-vm-usb.dtsi +++ b/arch/arm64/boot/dts/qcom/sa8195-vm-usb.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -56,7 +56,7 @@ 0x144 /* GSI_RING_BASE_ADDR_H */ 0x1a4>; /* GSI_IF_STS */ qcom,dwc-usb3-msm-tx-fifo-size = <27696>; - + qcom,ignore-wakeup-src-in-hostmode; status = "disabled"; dwc3@a600000 { From dbd1b34f9ad336e4312395564929e2fa9a9f3ae3 Mon Sep 17 00:00:00 2001 From: Sanjay Dwivedi Date: Thu, 23 Jul 2020 13:01:00 +0530 Subject: [PATCH 248/592] ARM: dts: msm: Update mpss_adsp carved memory for sa515m cdp New memory map is proposed for mapping 248 MB of memory to MPSS. Change-Id: Ice91140c58d4fdd7d4bda2bbbb5909e148d5bc93 Signed-off-by: Sanjay Dwivedi --- arch/arm64/boot/dts/qcom/sdxprairie-v2-dsda-cdp.dts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sdxprairie-v2-dsda-cdp.dts b/arch/arm64/boot/dts/qcom/sdxprairie-v2-dsda-cdp.dts index 99e9f86f5f14..e99fc9415bae 100644 --- a/arch/arm64/boot/dts/qcom/sdxprairie-v2-dsda-cdp.dts +++ b/arch/arm64/boot/dts/qcom/sdxprairie-v2-dsda-cdp.dts @@ -99,3 +99,7 @@ regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; }; + +&mpss_adsp_mem { + reg = <0x90800000 0xf800000>; +}; From d8d76d30d077fff941b0b454fa4b41daa3665aea Mon Sep 17 00:00:00 2001 From: Siddartha Mohanadoss Date: Fri, 24 Jul 2020 10:40:21 -0700 Subject: [PATCH 249/592] PCI: Add PCIe quirks for PCIe root port Add the PCIe quirks for sdxprairie root port. Without this change there will be conflicts in the iommu group for the end points across the switch. Adding the quirk resolves each end points that has data traffic to get its own iommu group. Change-Id: I1c495889e76b84b2cef1cceee8fa3721778fc923 Signed-off-by: Siddartha Mohanadoss --- drivers/pci/quirks.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index e7ed051ec125..530646c4c591 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -4588,6 +4588,7 @@ static const struct pci_dev_acs_enabled { /* QCOM QDF2xxx root ports */ { 0x17cb, 0x400, pci_quirk_qcom_rp_acs }, { 0x17cb, 0x401, pci_quirk_qcom_rp_acs }, + { 0x17cb, 0x10c, pci_quirk_qcom_rp_acs }, /* Intel PCH root ports */ { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_quirk_intel_pch_acs }, { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_quirk_intel_spt_pch_acs }, From 10a2a60a75e5d36ddb5bcb887cbe68e920e7c0f8 Mon Sep 17 00:00:00 2001 From: Deepak Dimri Date: Thu, 9 Jul 2020 15:42:49 +0530 Subject: [PATCH 250/592] ARM: dts: msm: Update ADC channels for SA2150P based CCARD Change VADC channels ADC_AMUX_THM1 and ADC_AMUX_THM3 to read voltage for SA2150p based CCARD. Change-Id: I37cff1aa23c4906904f146ece246049f0d5a7130 Signed-off-by: Deepak Dimri --- arch/arm64/boot/dts/qcom/sa2150p-ccard.dtsi | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sa2150p-ccard.dtsi b/arch/arm64/boot/dts/qcom/sa2150p-ccard.dtsi index c669832ac929..29e8955016f2 100644 --- a/arch/arm64/boot/dts/qcom/sa2150p-ccard.dtsi +++ b/arch/arm64/boot/dts/qcom/sa2150p-ccard.dtsi @@ -300,3 +300,21 @@ }; }; }; + +&pms405_vadc { + pa_therm1 { + /delete-property/ qcom,ratiometric; + /delete-property/ qcom,hw-settle-time; + label = "pa_therm1"; + reg = ; + qcom,pre-scaling = <1 1>; + }; + + pa_therm3 { + /delete-property/ qcom,ratiometric; + /delete-property/ qcom,hw-settle-time; + label = "pa_therm3"; + reg = ; + qcom,pre-scaling = <1 1>; + }; +}; From da44b6e78b3e3ec319c56fda6b86be2e6182dab6 Mon Sep 17 00:00:00 2001 From: Manoj Prabhu B Date: Fri, 24 Jul 2020 12:27:37 +0530 Subject: [PATCH 251/592] diag: Update event and log code ranges Modify the last event id and last log code id ranges. Change-Id: Ifd1118a77fd6d2b9cb204f667e8c0d4181e8c444 Signed-off-by: Manoj Prabhu B --- include/linux/diagchar.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/diagchar.h b/include/linux/diagchar.h index 59e6a77064a3..562dbc88b3cf 100644 --- a/include/linux/diagchar.h +++ b/include/linux/diagchar.h @@ -149,7 +149,7 @@ * a new RANGE of SSIDs to the msg_mask_tbl. */ #define MSG_MASK_TBL_CNT 26 -#define APPS_EVENT_LAST_ID 0xCC2 +#define APPS_EVENT_LAST_ID 0xCCD #define MSG_SSID_0 0 #define MSG_SSID_0_LAST 134 @@ -928,7 +928,7 @@ static const uint32_t msg_bld_masks_25[] = { /* LOG CODES */ static const uint32_t log_code_last_tbl[] = { 0x0, /* EQUIP ID 0 */ - 0x1CDD, /* EQUIP ID 1 */ + 0x1CE8, /* EQUIP ID 1 */ 0x0, /* EQUIP ID 2 */ 0x0, /* EQUIP ID 3 */ 0x4910, /* EQUIP ID 4 */ From 4211691d298c5a0f924d6df5faafe0e1e3679a29 Mon Sep 17 00:00:00 2001 From: Srinivasarao P Date: Mon, 8 Jun 2020 14:28:43 +0530 Subject: [PATCH 252/592] Reverting crypto and incrementalfs changes a9a5450 ANDROID: dm: prevent default-key from being enabled without needed hooks e1a94e6 ANDROID: dm: add dm-default-key target for metadata encryption 232fd35 ANDROID: dm: enable may_passthrough_inline_crypto on some targets 53bc059 ANDROID: dm: add support for passing through inline crypto support aeed6db ANDROID: block: Introduce passthrough keyslot manager 4f27c8b ANDROID: ext4, f2fs: enable direct I/O with inline encryption c91db46 BACKPORT: FROMLIST: scsi: ufs: add program_key() variant op f9a8e4a ANDROID: block: export symbols needed for modules to use inline crypto 75fea5f ANDROID: block: fix some inline crypto bugs 2871f73 ANDROID: fscrypt: add support for hardware-wrapped keys bb5a657 ANDROID: block: add KSM op to derive software secret from wrapped key d42ba87 ANDROID: block: provide key size as input to inline crypto APIs 86646eb ANDROID: ufshcd-crypto: export cap find API 83bc20e ANDROID: scsi: ufs-qcom: Enable BROKEN_CRYPTO quirk flag c266a13 ANDROID: scsi: ufs: Add quirk bit for controllers that don't play well with inline crypto ea09b99 ANDROID: cuttlefish_defconfig: Enable blk-crypto fallback e12563c BACKPORT: FROMLIST: Update Inline Encryption from v5 to v6 of patch series 8e8f55d ANDROID: scsi: ufs: UFS init should not require inline crypto dae9899 ANDROID: scsi: ufs: UFS crypto variant operations API a69516d ANDROID: cuttlefish_defconfig: enable inline encryption b8f7b23 BACKPORT: FROMLIST: ext4: add inline encryption support e64327f BACKPORT: FROMLIST: f2fs: add inline encryption support a0dc8da BACKPORT: FROMLIST: fscrypt: add inline encryption support 19c3c62 BACKPORT: FROMLIST: scsi: ufs: Add inline encryption support to UFS f858a99 BACKPORT: FROMLIST: scsi: ufs: UFS crypto API 011b834 BACKPORT: FROMLIST: scsi: ufs: UFS driver v2.1 spec crypto additions ec0b569 BACKPORT: FROMLIST: block: blk-crypto for Inline Encryption 760b328 ANDROID: block: Fix bio_crypt_should_process WARN_ON 138adbb BACKPORT: FROMLIST: block: Add encryption context to struct bio 66b5609 BACKPORT: FROMLIST: block: Keyslot Manager for Inline Encryption 2664a43 ANDROID: Incremental fs: Fix initialization, use of bitfields 334164c ANDROID: Incremental fs: Fix crash on failed lookup bc5e5bc ANDROID: Incremental fs: Make files writeable d0d1db1 ANDROID: Incremental fs: Remove C++-style comments Change-Id: I1edf6038709374a595beada0bba1ba4b767e4c7d Signed-off-by: Srinivasarao P --- Documentation/block/00-INDEX | 2 - Documentation/block/index.rst | 26 - Documentation/block/inline-encryption.rst | 183 ------ arch/arm64/configs/cuttlefish_defconfig | 3 - arch/x86/configs/x86_64_cuttlefish_defconfig | 3 - block/Kconfig | 17 - block/Makefile | 3 - block/bio-crypt-ctx.c | 142 ---- block/bio.c | 23 +- block/blk-core.c | 11 +- block/blk-crypto-fallback.c | 650 ------------------- block/blk-crypto-internal.h | 58 -- block/blk-crypto.c | 251 ------- block/blk-merge.c | 11 - block/keyslot-manager.c | 560 ---------------- drivers/md/Kconfig | 21 - drivers/md/Makefile | 1 - drivers/md/dm-bow.c | 1 - drivers/md/dm-default-key.c | 403 ------------ drivers/md/dm-linear.c | 1 - drivers/md/dm-table.c | 52 -- drivers/md/dm.c | 100 +-- drivers/scsi/ufs/Kconfig | 9 - drivers/scsi/ufs/Makefile | 4 +- drivers/scsi/ufs/ufs-qcom.c | 7 - drivers/scsi/ufs/ufshcd-crypto.c | 499 -------------- drivers/scsi/ufs/ufshcd-crypto.h | 167 ----- drivers/scsi/ufs/ufshcd.c | 74 +-- drivers/scsi/ufs/ufshcd.h | 59 -- drivers/scsi/ufs/ufshci.h | 67 +- fs/buffer.c | 3 - fs/crypto/Kconfig | 6 - fs/crypto/Makefile | 1 - fs/crypto/bio.c | 28 +- fs/crypto/crypto.c | 2 +- fs/crypto/fname.c | 4 +- fs/crypto/fscrypt_private.h | 152 +---- fs/crypto/inline_crypt.c | 353 ---------- fs/crypto/keyring.c | 54 +- fs/crypto/keysetup.c | 169 ++--- fs/crypto/keysetup_v1.c | 17 +- fs/direct-io.c | 5 - fs/ext4/ext4.h | 1 - fs/ext4/inode.c | 14 +- fs/ext4/page-io.c | 6 +- fs/ext4/readpage.c | 11 +- fs/ext4/super.c | 13 - fs/f2fs/data.c | 68 +- fs/f2fs/f2fs.h | 11 +- fs/f2fs/super.c | 41 -- fs/incfs/data_mgmt.c | 17 +- fs/incfs/data_mgmt.h | 34 +- fs/incfs/vfs.c | 50 +- fs/iomap.c | 6 - include/linux/bio-crypt-ctx.h | 226 ------- include/linux/bio.h | 1 - include/linux/blk-crypto.h | 66 -- include/linux/blk_types.h | 9 - include/linux/blkdev.h | 6 - include/linux/device-mapper.h | 6 - include/linux/fscrypt.h | 72 -- include/linux/keyslot-manager.h | 84 --- include/uapi/linux/fscrypt.h | 5 +- include/uapi/linux/incrementalfs.h | 15 +- 64 files changed, 163 insertions(+), 4801 deletions(-) delete mode 100644 Documentation/block/index.rst delete mode 100644 Documentation/block/inline-encryption.rst delete mode 100644 block/bio-crypt-ctx.c delete mode 100644 block/blk-crypto-fallback.c delete mode 100644 block/blk-crypto-internal.h delete mode 100644 block/blk-crypto.c delete mode 100644 block/keyslot-manager.c delete mode 100644 drivers/md/dm-default-key.c delete mode 100644 drivers/scsi/ufs/ufshcd-crypto.c delete mode 100644 drivers/scsi/ufs/ufshcd-crypto.h delete mode 100644 fs/crypto/inline_crypt.c delete mode 100644 include/linux/bio-crypt-ctx.h delete mode 100644 include/linux/blk-crypto.h delete mode 100644 include/linux/keyslot-manager.h diff --git a/Documentation/block/00-INDEX b/Documentation/block/00-INDEX index 7300403c5a0d..8d55b4bbb5e2 100644 --- a/Documentation/block/00-INDEX +++ b/Documentation/block/00-INDEX @@ -16,8 +16,6 @@ data-integrity.txt - Block data integrity deadline-iosched.txt - Deadline IO scheduler tunables -inline-encryption.rst - - Blk-crypto internals and inline encryption ioprio.txt - Block io priorities (in CFQ scheduler) pr.txt diff --git a/Documentation/block/index.rst b/Documentation/block/index.rst deleted file mode 100644 index 026addfc69bc..000000000000 --- a/Documentation/block/index.rst +++ /dev/null @@ -1,26 +0,0 @@ -.. SPDX-License-Identifier: GPL-2.0 - -===== -Block -===== - -.. toctree:: - :maxdepth: 1 - - bfq-iosched - biodoc - biovecs - capability - cmdline-partition - data-integrity - deadline-iosched - inline-encryption - ioprio - kyber-iosched - null_blk - pr - queue-sysfs - request - stat - switching-sched - writeback_cache_control diff --git a/Documentation/block/inline-encryption.rst b/Documentation/block/inline-encryption.rst deleted file mode 100644 index 330106b23c09..000000000000 --- a/Documentation/block/inline-encryption.rst +++ /dev/null @@ -1,183 +0,0 @@ -.. SPDX-License-Identifier: GPL-2.0 - -================= -Inline Encryption -================= - -Objective -========= - -We want to support inline encryption (IE) in the kernel. -To allow for testing, we also want a crypto API fallback when actual -IE hardware is absent. We also want IE to work with layered devices -like dm and loopback (i.e. we want to be able to use the IE hardware -of the underlying devices if present, or else fall back to crypto API -en/decryption). - - -Constraints and notes -===================== - -- IE hardware have a limited number of "keyslots" that can be programmed - with an encryption context (key, algorithm, data unit size, etc.) at any time. - One can specify a keyslot in a data request made to the device, and the - device will en/decrypt the data using the encryption context programmed into - that specified keyslot. When possible, we want to make multiple requests with - the same encryption context share the same keyslot. - -- We need a way for filesystems to specify an encryption context to use for - en/decrypting a struct bio, and a device driver (like UFS) needs to be able - to use that encryption context when it processes the bio. - -- We need a way for device drivers to expose their capabilities in a unified - way to the upper layers. - - -Design -====== - -We add a struct bio_crypt_ctx to struct bio that can represent an -encryption context, because we need to be able to pass this encryption -context from the FS layer to the device driver to act upon. - -While IE hardware works on the notion of keyslots, the FS layer has no -knowledge of keyslots - it simply wants to specify an encryption context to -use while en/decrypting a bio. - -We introduce a keyslot manager (KSM) that handles the translation from -encryption contexts specified by the FS to keyslots on the IE hardware. -This KSM also serves as the way IE hardware can expose their capabilities to -upper layers. The generic mode of operation is: each device driver that wants -to support IE will construct a KSM and set it up in its struct request_queue. -Upper layers that want to use IE on this device can then use this KSM in -the device's struct request_queue to translate an encryption context into -a keyslot. The presence of the KSM in the request queue shall be used to mean -that the device supports IE. - -On the device driver end of the interface, the device driver needs to tell the -KSM how to actually manipulate the IE hardware in the device to do things like -programming the crypto key into the IE hardware into a particular keyslot. All -this is achieved through the :c:type:`struct keyslot_mgmt_ll_ops` that the -device driver passes to the KSM when creating it. - -It uses refcounts to track which keyslots are idle (either they have no -encryption context programmed, or there are no in-flight struct bios -referencing that keyslot). When a new encryption context needs a keyslot, it -tries to find a keyslot that has already been programmed with the same -encryption context, and if there is no such keyslot, it evicts the least -recently used idle keyslot and programs the new encryption context into that -one. If no idle keyslots are available, then the caller will sleep until there -is at least one. - - -Blk-crypto -========== - -The above is sufficient for simple cases, but does not work if there is a -need for a crypto API fallback, or if we are want to use IE with layered -devices. To these ends, we introduce blk-crypto. Blk-crypto allows us to -present a unified view of encryption to the FS (so FS only needs to specify -an encryption context and not worry about keyslots at all), and blk-crypto -can decide whether to delegate the en/decryption to IE hardware or to the -crypto API. Blk-crypto maintains an internal KSM that serves as the crypto -API fallback. - -Blk-crypto needs to ensure that the encryption context is programmed into the -"correct" keyslot manager for IE. If a bio is submitted to a layered device -that eventually passes the bio down to a device that really does support IE, we -want the encryption context to be programmed into a keyslot for the KSM of the -device with IE support. However, blk-crypto does not know a priori whether a -particular device is the final device in the layering structure for a bio or -not. So in the case that a particular device does not support IE, since it is -possibly the final destination device for the bio, if the bio requires -encryption (i.e. the bio is doing a write operation), blk-crypto must fallback -to the crypto API *before* sending the bio to the device. - -Blk-crypto ensures that: - -- The bio's encryption context is programmed into a keyslot in the KSM of the - request queue that the bio is being submitted to (or the crypto API fallback - KSM if the request queue doesn't have a KSM), and that the ``bc_ksm`` - in the ``bi_crypt_context`` is set to this KSM - -- That the bio has its own individual reference to the keyslot in this KSM. - Once the bio passes through blk-crypto, its encryption context is programmed - in some KSM. The "its own individual reference to the keyslot" ensures that - keyslots can be released by each bio independently of other bios while - ensuring that the bio has a valid reference to the keyslot when, for e.g., the - crypto API fallback KSM in blk-crypto performs crypto on the device's behalf. - The individual references are ensured by increasing the refcount for the - keyslot in the ``bc_ksm`` when a bio with a programmed encryption - context is cloned. - - -What blk-crypto does on bio submission --------------------------------------- - -**Case 1:** blk-crypto is given a bio with only an encryption context that hasn't -been programmed into any keyslot in any KSM (for e.g. a bio from the FS). - In this case, blk-crypto will program the encryption context into the KSM of the - request queue the bio is being submitted to (and if this KSM does not exist, - then it will program it into blk-crypto's internal KSM for crypto API - fallback). The KSM that this encryption context was programmed into is stored - as the ``bc_ksm`` in the bio's ``bi_crypt_context``. - -**Case 2:** blk-crypto is given a bio whose encryption context has already been -programmed into a keyslot in the *crypto API fallback* KSM. - In this case, blk-crypto does nothing; it treats the bio as not having - specified an encryption context. Note that we cannot do here what we will do - in Case 3 because we would have already encrypted the bio via the crypto API - by this point. - -**Case 3:** blk-crypto is given a bio whose encryption context has already been -programmed into a keyslot in some KSM (that is *not* the crypto API fallback -KSM). - In this case, blk-crypto first releases that keyslot from that KSM and then - treats the bio as in Case 1. - -This way, when a device driver is processing a bio, it can be sure that -the bio's encryption context has been programmed into some KSM (either the -device driver's request queue's KSM, or blk-crypto's crypto API fallback KSM). -It then simply needs to check if the bio's ``bc_ksm`` is the device's -request queue's KSM. If so, then it should proceed with IE. If not, it should -simply do nothing with respect to crypto, because some other KSM (perhaps the -blk-crypto crypto API fallback KSM) is handling the en/decryption. - -Blk-crypto will release the keyslot that is being held by the bio (and also -decrypt it if the bio is using the crypto API fallback KSM) once -``bio_remaining_done`` returns true for the bio. - - -Layered Devices -=============== - -Layered devices that wish to support IE need to create their own keyslot -manager for their request queue, and expose whatever functionality they choose. -When a layered device wants to pass a bio to another layer (either by -resubmitting the same bio, or by submitting a clone), it doesn't need to do -anything special because the bio (or the clone) will once again pass through -blk-crypto, which will work as described in Case 3. If a layered device wants -for some reason to do the IO by itself instead of passing it on to a child -device, but it also chose to expose IE capabilities by setting up a KSM in its -request queue, it is then responsible for en/decrypting the data itself. In -such cases, the device can choose to call the blk-crypto function -``blk_crypto_fallback_to_kernel_crypto_api`` (TODO: Not yet implemented), which will -cause the en/decryption to be done via the crypto API fallback. - - -Future Optimizations for layered devices -======================================== - -Creating a keyslot manager for the layered device uses up memory for each -keyslot, and in general, a layered device (like dm-linear) merely passes the -request on to a "child" device, so the keyslots in the layered device itself -might be completely unused. We can instead define a new type of KSM; the -"passthrough KSM", that layered devices can use to let blk-crypto know that -this layered device *will* pass the bio to some child device (and hence -through blk-crypto again, at which point blk-crypto can program the encryption -context, instead of programming it into the layered device's KSM). Again, if -the device "lies" and decides to do the IO itself instead of passing it on to -a child device, it is responsible for doing the en/decryption (and can choose -to call ``blk_crypto_fallback_to_kernel_crypto_api``). Another use case for the -"passthrough KSM" is for IE devices that want to manage their own keyslots/do -not have a limited number of keyslots. diff --git a/arch/arm64/configs/cuttlefish_defconfig b/arch/arm64/configs/cuttlefish_defconfig index c1b2fc17bdbb..b606278bce09 100644 --- a/arch/arm64/configs/cuttlefish_defconfig +++ b/arch/arm64/configs/cuttlefish_defconfig @@ -50,8 +50,6 @@ CONFIG_REFCOUNT_FULL=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODVERSIONS=y -CONFIG_BLK_INLINE_ENCRYPTION=y -CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y CONFIG_PCI=y CONFIG_PCI_HOST_GENERIC=y CONFIG_PREEMPT=y @@ -433,7 +431,6 @@ CONFIG_EXT4_ENCRYPTION=y CONFIG_F2FS_FS=y CONFIG_F2FS_FS_SECURITY=y CONFIG_F2FS_FS_ENCRYPTION=y -CONFIG_FS_ENCRYPTION_INLINE_CRYPT=y CONFIG_FS_VERITY=y CONFIG_FS_VERITY_BUILTIN_SIGNATURES=y # CONFIG_DNOTIFY is not set diff --git a/arch/x86/configs/x86_64_cuttlefish_defconfig b/arch/x86/configs/x86_64_cuttlefish_defconfig index b18d574c8143..6c4134cc1cbf 100644 --- a/arch/x86/configs/x86_64_cuttlefish_defconfig +++ b/arch/x86/configs/x86_64_cuttlefish_defconfig @@ -43,8 +43,6 @@ CONFIG_REFCOUNT_FULL=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODVERSIONS=y -CONFIG_BLK_INLINE_ENCRYPTION=y -CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y CONFIG_PARTITION_ADVANCED=y CONFIG_SMP=y CONFIG_HYPERVISOR_GUEST=y @@ -445,7 +443,6 @@ CONFIG_EXT4_ENCRYPTION=y CONFIG_F2FS_FS=y CONFIG_F2FS_FS_SECURITY=y CONFIG_F2FS_FS_ENCRYPTION=y -CONFIG_FS_ENCRYPTION_INLINE_CRYPT=y CONFIG_FS_VERITY=y CONFIG_FS_VERITY_BUILTIN_SIGNATURES=y CONFIG_QUOTA=y diff --git a/block/Kconfig b/block/Kconfig index 4d9bcb951d83..28ec55752b68 100644 --- a/block/Kconfig +++ b/block/Kconfig @@ -184,23 +184,6 @@ config BLK_SED_OPAL Enabling this option enables users to setup/unlock/lock Locking ranges for SED devices using the Opal protocol. -config BLK_INLINE_ENCRYPTION - bool "Enable inline encryption support in block layer" - help - Build the blk-crypto subsystem. Enabling this lets the - block layer handle encryption, so users can take - advantage of inline encryption hardware if present. - -config BLK_INLINE_ENCRYPTION_FALLBACK - bool "Enable crypto API fallback for blk-crypto" - depends on BLK_INLINE_ENCRYPTION - select CRYPTO - select CRYPTO_BLKCIPHER - help - Enabling this lets the block layer handle inline encryption - by falling back to the kernel crypto API when inline - encryption hardware is not present. - menu "Partition Types" source "block/partitions/Kconfig" diff --git a/block/Makefile b/block/Makefile index ab14055d8222..6a56303b9925 100644 --- a/block/Makefile +++ b/block/Makefile @@ -35,6 +35,3 @@ obj-$(CONFIG_BLK_DEV_ZONED) += blk-zoned.o obj-$(CONFIG_BLK_WBT) += blk-wbt.o obj-$(CONFIG_BLK_DEBUG_FS) += blk-mq-debugfs.o obj-$(CONFIG_BLK_SED_OPAL) += sed-opal.o -obj-$(CONFIG_BLK_INLINE_ENCRYPTION) += keyslot-manager.o bio-crypt-ctx.o \ - blk-crypto.o -obj-$(CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK) += blk-crypto-fallback.o \ No newline at end of file diff --git a/block/bio-crypt-ctx.c b/block/bio-crypt-ctx.c deleted file mode 100644 index 75008b2afea2..000000000000 --- a/block/bio-crypt-ctx.c +++ /dev/null @@ -1,142 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright 2019 Google LLC - */ - -#include -#include -#include -#include -#include - -#include "blk-crypto-internal.h" - -static int num_prealloc_crypt_ctxs = 128; - -module_param(num_prealloc_crypt_ctxs, int, 0444); -MODULE_PARM_DESC(num_prealloc_crypt_ctxs, - "Number of bio crypto contexts to preallocate"); - -static struct kmem_cache *bio_crypt_ctx_cache; -static mempool_t *bio_crypt_ctx_pool; - -int __init bio_crypt_ctx_init(void) -{ - size_t i; - - bio_crypt_ctx_cache = KMEM_CACHE(bio_crypt_ctx, 0); - if (!bio_crypt_ctx_cache) - return -ENOMEM; - - bio_crypt_ctx_pool = mempool_create_slab_pool(num_prealloc_crypt_ctxs, - bio_crypt_ctx_cache); - if (!bio_crypt_ctx_pool) - return -ENOMEM; - - /* This is assumed in various places. */ - BUILD_BUG_ON(BLK_ENCRYPTION_MODE_INVALID != 0); - - /* Sanity check that no algorithm exceeds the defined limits. */ - for (i = 0; i < BLK_ENCRYPTION_MODE_MAX; i++) { - BUG_ON(blk_crypto_modes[i].keysize > BLK_CRYPTO_MAX_KEY_SIZE); - BUG_ON(blk_crypto_modes[i].ivsize > BLK_CRYPTO_MAX_IV_SIZE); - } - - return 0; -} - -struct bio_crypt_ctx *bio_crypt_alloc_ctx(gfp_t gfp_mask) -{ - return mempool_alloc(bio_crypt_ctx_pool, gfp_mask); -} -EXPORT_SYMBOL_GPL(bio_crypt_alloc_ctx); - -void bio_crypt_free_ctx(struct bio *bio) -{ - mempool_free(bio->bi_crypt_context, bio_crypt_ctx_pool); - bio->bi_crypt_context = NULL; -} - -void bio_crypt_clone(struct bio *dst, struct bio *src, gfp_t gfp_mask) -{ - const struct bio_crypt_ctx *src_bc = src->bi_crypt_context; - - bio_clone_skip_dm_default_key(dst, src); - - /* - * If a bio is fallback_crypted, then it will be decrypted when - * bio_endio is called. As we only want the data to be decrypted once, - * copies of the bio must not have have a crypt context. - */ - if (!src_bc || bio_crypt_fallback_crypted(src_bc)) - return; - - dst->bi_crypt_context = bio_crypt_alloc_ctx(gfp_mask); - *dst->bi_crypt_context = *src_bc; - - if (src_bc->bc_keyslot >= 0) - keyslot_manager_get_slot(src_bc->bc_ksm, src_bc->bc_keyslot); -} -EXPORT_SYMBOL_GPL(bio_crypt_clone); - -bool bio_crypt_should_process(struct request *rq) -{ - struct bio *bio = rq->bio; - - if (!bio || !bio->bi_crypt_context) - return false; - - return rq->q->ksm == bio->bi_crypt_context->bc_ksm; -} -EXPORT_SYMBOL_GPL(bio_crypt_should_process); - -/* - * Checks that two bio crypt contexts are compatible - i.e. that - * they are mergeable except for data_unit_num continuity. - */ -bool bio_crypt_ctx_compatible(struct bio *b_1, struct bio *b_2) -{ - struct bio_crypt_ctx *bc1 = b_1->bi_crypt_context; - struct bio_crypt_ctx *bc2 = b_2->bi_crypt_context; - - if (!bc1) - return !bc2; - return bc2 && bc1->bc_key == bc2->bc_key; -} - -/* - * Checks that two bio crypt contexts are compatible, and also - * that their data_unit_nums are continuous (and can hence be merged) - * in the order b_1 followed by b_2. - */ -bool bio_crypt_ctx_mergeable(struct bio *b_1, unsigned int b1_bytes, - struct bio *b_2) -{ - struct bio_crypt_ctx *bc1 = b_1->bi_crypt_context; - struct bio_crypt_ctx *bc2 = b_2->bi_crypt_context; - - if (!bio_crypt_ctx_compatible(b_1, b_2)) - return false; - - return !bc1 || bio_crypt_dun_is_contiguous(bc1, b1_bytes, bc2->bc_dun); -} - -void bio_crypt_ctx_release_keyslot(struct bio_crypt_ctx *bc) -{ - keyslot_manager_put_slot(bc->bc_ksm, bc->bc_keyslot); - bc->bc_ksm = NULL; - bc->bc_keyslot = -1; -} - -int bio_crypt_ctx_acquire_keyslot(struct bio_crypt_ctx *bc, - struct keyslot_manager *ksm) -{ - int slot = keyslot_manager_get_slot_for_key(ksm, bc->bc_key); - - if (slot < 0) - return slot; - - bc->bc_keyslot = slot; - bc->bc_ksm = ksm; - return 0; -} diff --git a/block/bio.c b/block/bio.c index 6ef2e22d2bf3..a3c4fd9ec478 100644 --- a/block/bio.c +++ b/block/bio.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include "blk.h" @@ -244,8 +243,6 @@ fallback: void bio_uninit(struct bio *bio) { bio_disassociate_task(bio); - - bio_crypt_free_ctx(bio); } EXPORT_SYMBOL(bio_uninit); @@ -631,12 +628,15 @@ struct bio *bio_clone_fast(struct bio *bio, gfp_t gfp_mask, struct bio_set *bs) __bio_clone_fast(b, bio); - bio_crypt_clone(b, bio, gfp_mask); + if (bio_integrity(bio)) { + int ret; - if (bio_integrity(bio) && - bio_integrity_clone(b, bio, gfp_mask) < 0) { - bio_put(b); - return NULL; + ret = bio_integrity_clone(b, bio, gfp_mask); + + if (ret < 0) { + bio_put(b); + return NULL; + } } return b; @@ -704,8 +704,6 @@ struct bio *bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask, break; } - bio_crypt_clone(bio, bio_src, gfp_mask); - if (bio_integrity(bio_src)) { int ret; @@ -1037,7 +1035,6 @@ void bio_advance(struct bio *bio, unsigned bytes) if (bio_integrity(bio)) bio_integrity_advance(bio, bytes); - bio_crypt_advance(bio, bytes); bio_advance_iter(bio, &bio->bi_iter, bytes); } EXPORT_SYMBOL(bio_advance); @@ -1895,10 +1892,6 @@ void bio_endio(struct bio *bio) again: if (!bio_remaining_done(bio)) return; - - if (!blk_crypto_endio(bio)) - return; - if (!bio_integrity_endio(bio)) return; diff --git a/block/blk-core.c b/block/blk-core.c index 4322a1895e32..79352e101172 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -35,7 +35,6 @@ #include #include #include -#include #define CREATE_TRACE_POINTS #include @@ -2226,9 +2225,7 @@ blk_qc_t generic_make_request(struct bio *bio) /* Create a fresh bio_list for all subordinate requests */ bio_list_on_stack[1] = bio_list_on_stack[0]; bio_list_init(&bio_list_on_stack[0]); - - if (!blk_crypto_submit_bio(&bio)) - ret = q->make_request_fn(q, bio); + ret = q->make_request_fn(q, bio); blk_queue_exit(q); @@ -3670,11 +3667,5 @@ int __init blk_dev_init(void) blk_debugfs_root = debugfs_create_dir("block", NULL); #endif - if (bio_crypt_ctx_init() < 0) - panic("Failed to allocate mem for bio crypt ctxs\n"); - - if (blk_crypto_fallback_init() < 0) - panic("Failed to init blk-crypto-fallback\n"); - return 0; } diff --git a/block/blk-crypto-fallback.c b/block/blk-crypto-fallback.c deleted file mode 100644 index cce3317cba80..000000000000 --- a/block/blk-crypto-fallback.c +++ /dev/null @@ -1,650 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright 2019 Google LLC - */ - -/* - * Refer to Documentation/block/inline-encryption.rst for detailed explanation. - */ - -#define pr_fmt(fmt) "blk-crypto-fallback: " fmt - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "blk-crypto-internal.h" - -static unsigned int num_prealloc_bounce_pg = 32; -module_param(num_prealloc_bounce_pg, uint, 0); -MODULE_PARM_DESC(num_prealloc_bounce_pg, - "Number of preallocated bounce pages for the blk-crypto crypto API fallback"); - -static unsigned int blk_crypto_num_keyslots = 100; -module_param_named(num_keyslots, blk_crypto_num_keyslots, uint, 0); -MODULE_PARM_DESC(num_keyslots, - "Number of keyslots for the blk-crypto crypto API fallback"); - -static unsigned int num_prealloc_fallback_crypt_ctxs = 128; -module_param(num_prealloc_fallback_crypt_ctxs, uint, 0); -MODULE_PARM_DESC(num_prealloc_crypt_fallback_ctxs, - "Number of preallocated bio fallback crypto contexts for blk-crypto to use during crypto API fallback"); - -struct bio_fallback_crypt_ctx { - struct bio_crypt_ctx crypt_ctx; - /* - * Copy of the bvec_iter when this bio was submitted. - * We only want to en/decrypt the part of the bio as described by the - * bvec_iter upon submission because bio might be split before being - * resubmitted - */ - struct bvec_iter crypt_iter; - u64 fallback_dun[BLK_CRYPTO_DUN_ARRAY_SIZE]; -}; - -/* The following few vars are only used during the crypto API fallback */ -static struct kmem_cache *bio_fallback_crypt_ctx_cache; -static mempool_t *bio_fallback_crypt_ctx_pool; - -/* - * Allocating a crypto tfm during I/O can deadlock, so we have to preallocate - * all of a mode's tfms when that mode starts being used. Since each mode may - * need all the keyslots at some point, each mode needs its own tfm for each - * keyslot; thus, a keyslot may contain tfms for multiple modes. However, to - * match the behavior of real inline encryption hardware (which only supports a - * single encryption context per keyslot), we only allow one tfm per keyslot to - * be used at a time - the rest of the unused tfms have their keys cleared. - */ -static DEFINE_MUTEX(tfms_init_lock); -static bool tfms_inited[BLK_ENCRYPTION_MODE_MAX]; - -struct blk_crypto_decrypt_work { - struct work_struct work; - struct bio *bio; -}; - -static struct blk_crypto_keyslot { - struct crypto_skcipher *tfm; - enum blk_crypto_mode_num crypto_mode; - struct crypto_skcipher *tfms[BLK_ENCRYPTION_MODE_MAX]; -} *blk_crypto_keyslots; - -/* The following few vars are only used during the crypto API fallback */ -static struct keyslot_manager *blk_crypto_ksm; -static struct workqueue_struct *blk_crypto_wq; -static mempool_t *blk_crypto_bounce_page_pool; -static struct kmem_cache *blk_crypto_decrypt_work_cache; - -bool bio_crypt_fallback_crypted(const struct bio_crypt_ctx *bc) -{ - return bc && bc->bc_ksm == blk_crypto_ksm; -} - -/* - * This is the key we set when evicting a keyslot. This *should* be the all 0's - * key, but AES-XTS rejects that key, so we use some random bytes instead. - */ -static u8 blank_key[BLK_CRYPTO_MAX_KEY_SIZE]; - -static void blk_crypto_evict_keyslot(unsigned int slot) -{ - struct blk_crypto_keyslot *slotp = &blk_crypto_keyslots[slot]; - enum blk_crypto_mode_num crypto_mode = slotp->crypto_mode; - int err; - - WARN_ON(slotp->crypto_mode == BLK_ENCRYPTION_MODE_INVALID); - - /* Clear the key in the skcipher */ - err = crypto_skcipher_setkey(slotp->tfms[crypto_mode], blank_key, - blk_crypto_modes[crypto_mode].keysize); - WARN_ON(err); - slotp->crypto_mode = BLK_ENCRYPTION_MODE_INVALID; -} - -static int blk_crypto_keyslot_program(struct keyslot_manager *ksm, - const struct blk_crypto_key *key, - unsigned int slot) -{ - struct blk_crypto_keyslot *slotp = &blk_crypto_keyslots[slot]; - const enum blk_crypto_mode_num crypto_mode = key->crypto_mode; - int err; - - if (crypto_mode != slotp->crypto_mode && - slotp->crypto_mode != BLK_ENCRYPTION_MODE_INVALID) { - blk_crypto_evict_keyslot(slot); - } - - if (!slotp->tfms[crypto_mode]) - return -ENOMEM; - slotp->crypto_mode = crypto_mode; - err = crypto_skcipher_setkey(slotp->tfms[crypto_mode], key->raw, - key->size); - if (err) { - blk_crypto_evict_keyslot(slot); - return err; - } - return 0; -} - -static int blk_crypto_keyslot_evict(struct keyslot_manager *ksm, - const struct blk_crypto_key *key, - unsigned int slot) -{ - blk_crypto_evict_keyslot(slot); - return 0; -} - -/* - * The crypto API fallback KSM ops - only used for a bio when it specifies a - * blk_crypto_mode for which we failed to get a keyslot in the device's inline - * encryption hardware (which probably means the device doesn't have inline - * encryption hardware that supports that crypto mode). - */ -static const struct keyslot_mgmt_ll_ops blk_crypto_ksm_ll_ops = { - .keyslot_program = blk_crypto_keyslot_program, - .keyslot_evict = blk_crypto_keyslot_evict, -}; - -static void blk_crypto_encrypt_endio(struct bio *enc_bio) -{ - struct bio *src_bio = enc_bio->bi_private; - int i; - - for (i = 0; i < enc_bio->bi_vcnt; i++) - mempool_free(enc_bio->bi_io_vec[i].bv_page, - blk_crypto_bounce_page_pool); - - src_bio->bi_status = enc_bio->bi_status; - - bio_put(enc_bio); - bio_endio(src_bio); -} - -static struct bio *blk_crypto_clone_bio(struct bio *bio_src) -{ - struct bvec_iter iter; - struct bio_vec bv; - struct bio *bio; - - bio = bio_alloc_bioset(GFP_NOIO, bio_segments(bio_src), NULL); - if (!bio) - return NULL; - bio->bi_disk = bio_src->bi_disk; - bio->bi_opf = bio_src->bi_opf; - bio->bi_ioprio = bio_src->bi_ioprio; - bio->bi_write_hint = bio_src->bi_write_hint; - bio->bi_iter.bi_sector = bio_src->bi_iter.bi_sector; - bio->bi_iter.bi_size = bio_src->bi_iter.bi_size; - - bio_for_each_segment(bv, bio_src, iter) - bio->bi_io_vec[bio->bi_vcnt++] = bv; - - if (bio_integrity(bio_src) && - bio_integrity_clone(bio, bio_src, GFP_NOIO) < 0) { - bio_put(bio); - return NULL; - } - - bio_clone_blkcg_association(bio, bio_src); - - bio_clone_skip_dm_default_key(bio, bio_src); - - return bio; -} - -static int blk_crypto_alloc_cipher_req(struct bio *src_bio, - struct skcipher_request **ciph_req_ret, - struct crypto_wait *wait) -{ - struct skcipher_request *ciph_req; - const struct blk_crypto_keyslot *slotp; - - slotp = &blk_crypto_keyslots[src_bio->bi_crypt_context->bc_keyslot]; - ciph_req = skcipher_request_alloc(slotp->tfms[slotp->crypto_mode], - GFP_NOIO); - if (!ciph_req) { - src_bio->bi_status = BLK_STS_RESOURCE; - return -ENOMEM; - } - - skcipher_request_set_callback(ciph_req, - CRYPTO_TFM_REQ_MAY_BACKLOG | - CRYPTO_TFM_REQ_MAY_SLEEP, - crypto_req_done, wait); - *ciph_req_ret = ciph_req; - return 0; -} - -static int blk_crypto_split_bio_if_needed(struct bio **bio_ptr) -{ - struct bio *bio = *bio_ptr; - unsigned int i = 0; - unsigned int num_sectors = 0; - struct bio_vec bv; - struct bvec_iter iter; - - bio_for_each_segment(bv, bio, iter) { - num_sectors += bv.bv_len >> SECTOR_SHIFT; - if (++i == BIO_MAX_PAGES) - break; - } - if (num_sectors < bio_sectors(bio)) { - struct bio *split_bio; - - split_bio = bio_split(bio, num_sectors, GFP_NOIO, NULL); - if (!split_bio) { - bio->bi_status = BLK_STS_RESOURCE; - return -ENOMEM; - } - bio_chain(split_bio, bio); - generic_make_request(bio); - *bio_ptr = split_bio; - } - return 0; -} - -union blk_crypto_iv { - __le64 dun[BLK_CRYPTO_DUN_ARRAY_SIZE]; - u8 bytes[BLK_CRYPTO_MAX_IV_SIZE]; -}; - -static void blk_crypto_dun_to_iv(const u64 dun[BLK_CRYPTO_DUN_ARRAY_SIZE], - union blk_crypto_iv *iv) -{ - int i; - - for (i = 0; i < BLK_CRYPTO_DUN_ARRAY_SIZE; i++) - iv->dun[i] = cpu_to_le64(dun[i]); -} - -/* - * The crypto API fallback's encryption routine. - * Allocate a bounce bio for encryption, encrypt the input bio using crypto API, - * and replace *bio_ptr with the bounce bio. May split input bio if it's too - * large. - */ -static int blk_crypto_encrypt_bio(struct bio **bio_ptr) -{ - struct bio *src_bio; - struct skcipher_request *ciph_req = NULL; - DECLARE_CRYPTO_WAIT(wait); - u64 curr_dun[BLK_CRYPTO_DUN_ARRAY_SIZE]; - union blk_crypto_iv iv; - struct scatterlist src, dst; - struct bio *enc_bio; - unsigned int i, j; - int data_unit_size; - struct bio_crypt_ctx *bc; - int err = 0; - - /* Split the bio if it's too big for single page bvec */ - err = blk_crypto_split_bio_if_needed(bio_ptr); - if (err) - return err; - - src_bio = *bio_ptr; - bc = src_bio->bi_crypt_context; - data_unit_size = bc->bc_key->data_unit_size; - - /* Allocate bounce bio for encryption */ - enc_bio = blk_crypto_clone_bio(src_bio); - if (!enc_bio) { - src_bio->bi_status = BLK_STS_RESOURCE; - return -ENOMEM; - } - - /* - * Use the crypto API fallback keyslot manager to get a crypto_skcipher - * for the algorithm and key specified for this bio. - */ - err = bio_crypt_ctx_acquire_keyslot(bc, blk_crypto_ksm); - if (err) { - src_bio->bi_status = BLK_STS_IOERR; - goto out_put_enc_bio; - } - - /* and then allocate an skcipher_request for it */ - err = blk_crypto_alloc_cipher_req(src_bio, &ciph_req, &wait); - if (err) - goto out_release_keyslot; - - memcpy(curr_dun, bc->bc_dun, sizeof(curr_dun)); - sg_init_table(&src, 1); - sg_init_table(&dst, 1); - - skcipher_request_set_crypt(ciph_req, &src, &dst, data_unit_size, - iv.bytes); - - /* Encrypt each page in the bounce bio */ - for (i = 0; i < enc_bio->bi_vcnt; i++) { - struct bio_vec *enc_bvec = &enc_bio->bi_io_vec[i]; - struct page *plaintext_page = enc_bvec->bv_page; - struct page *ciphertext_page = - mempool_alloc(blk_crypto_bounce_page_pool, GFP_NOIO); - - enc_bvec->bv_page = ciphertext_page; - - if (!ciphertext_page) { - src_bio->bi_status = BLK_STS_RESOURCE; - err = -ENOMEM; - goto out_free_bounce_pages; - } - - sg_set_page(&src, plaintext_page, data_unit_size, - enc_bvec->bv_offset); - sg_set_page(&dst, ciphertext_page, data_unit_size, - enc_bvec->bv_offset); - - /* Encrypt each data unit in this page */ - for (j = 0; j < enc_bvec->bv_len; j += data_unit_size) { - blk_crypto_dun_to_iv(curr_dun, &iv); - err = crypto_wait_req(crypto_skcipher_encrypt(ciph_req), - &wait); - if (err) { - i++; - src_bio->bi_status = BLK_STS_RESOURCE; - goto out_free_bounce_pages; - } - bio_crypt_dun_increment(curr_dun, 1); - src.offset += data_unit_size; - dst.offset += data_unit_size; - } - } - - enc_bio->bi_private = src_bio; - enc_bio->bi_end_io = blk_crypto_encrypt_endio; - *bio_ptr = enc_bio; - - enc_bio = NULL; - err = 0; - goto out_free_ciph_req; - -out_free_bounce_pages: - while (i > 0) - mempool_free(enc_bio->bi_io_vec[--i].bv_page, - blk_crypto_bounce_page_pool); -out_free_ciph_req: - skcipher_request_free(ciph_req); -out_release_keyslot: - bio_crypt_ctx_release_keyslot(bc); -out_put_enc_bio: - if (enc_bio) - bio_put(enc_bio); - - return err; -} - -static void blk_crypto_free_fallback_crypt_ctx(struct bio *bio) -{ - mempool_free(container_of(bio->bi_crypt_context, - struct bio_fallback_crypt_ctx, - crypt_ctx), - bio_fallback_crypt_ctx_pool); - bio->bi_crypt_context = NULL; -} - -/* - * The crypto API fallback's main decryption routine. - * Decrypts input bio in place. - */ -static void blk_crypto_decrypt_bio(struct work_struct *work) -{ - struct blk_crypto_decrypt_work *decrypt_work = - container_of(work, struct blk_crypto_decrypt_work, work); - struct bio *bio = decrypt_work->bio; - struct skcipher_request *ciph_req = NULL; - DECLARE_CRYPTO_WAIT(wait); - struct bio_vec bv; - struct bvec_iter iter; - u64 curr_dun[BLK_CRYPTO_DUN_ARRAY_SIZE]; - union blk_crypto_iv iv; - struct scatterlist sg; - struct bio_crypt_ctx *bc = bio->bi_crypt_context; - struct bio_fallback_crypt_ctx *f_ctx = - container_of(bc, struct bio_fallback_crypt_ctx, crypt_ctx); - const int data_unit_size = bc->bc_key->data_unit_size; - unsigned int i; - int err; - - /* - * Use the crypto API fallback keyslot manager to get a crypto_skcipher - * for the algorithm and key specified for this bio. - */ - if (bio_crypt_ctx_acquire_keyslot(bc, blk_crypto_ksm)) { - bio->bi_status = BLK_STS_RESOURCE; - goto out_no_keyslot; - } - - /* and then allocate an skcipher_request for it */ - err = blk_crypto_alloc_cipher_req(bio, &ciph_req, &wait); - if (err) - goto out; - - memcpy(curr_dun, f_ctx->fallback_dun, sizeof(curr_dun)); - sg_init_table(&sg, 1); - skcipher_request_set_crypt(ciph_req, &sg, &sg, data_unit_size, - iv.bytes); - - /* Decrypt each segment in the bio */ - __bio_for_each_segment(bv, bio, iter, f_ctx->crypt_iter) { - struct page *page = bv.bv_page; - - sg_set_page(&sg, page, data_unit_size, bv.bv_offset); - - /* Decrypt each data unit in the segment */ - for (i = 0; i < bv.bv_len; i += data_unit_size) { - blk_crypto_dun_to_iv(curr_dun, &iv); - if (crypto_wait_req(crypto_skcipher_decrypt(ciph_req), - &wait)) { - bio->bi_status = BLK_STS_IOERR; - goto out; - } - bio_crypt_dun_increment(curr_dun, 1); - sg.offset += data_unit_size; - } - } - -out: - skcipher_request_free(ciph_req); - bio_crypt_ctx_release_keyslot(bc); -out_no_keyslot: - kmem_cache_free(blk_crypto_decrypt_work_cache, decrypt_work); - blk_crypto_free_fallback_crypt_ctx(bio); - bio_endio(bio); -} - -/* - * Queue bio for decryption. - * Returns true iff bio was queued for decryption. - */ -bool blk_crypto_queue_decrypt_bio(struct bio *bio) -{ - struct blk_crypto_decrypt_work *decrypt_work; - - /* If there was an IO error, don't queue for decrypt. */ - if (bio->bi_status) - goto out; - - decrypt_work = kmem_cache_zalloc(blk_crypto_decrypt_work_cache, - GFP_ATOMIC); - if (!decrypt_work) { - bio->bi_status = BLK_STS_RESOURCE; - goto out; - } - - INIT_WORK(&decrypt_work->work, blk_crypto_decrypt_bio); - decrypt_work->bio = bio; - queue_work(blk_crypto_wq, &decrypt_work->work); - - return true; -out: - blk_crypto_free_fallback_crypt_ctx(bio); - return false; -} - -/** - * blk_crypto_start_using_mode() - Start using a crypto algorithm on a device - * @mode_num: the blk_crypto_mode we want to allocate ciphers for. - * @data_unit_size: the data unit size that will be used - * @q: the request queue for the device - * - * Upper layers must call this function to ensure that a the crypto API fallback - * has transforms for this algorithm, if they become necessary. - * - * Return: 0 on success and -err on error. - */ -int blk_crypto_start_using_mode(enum blk_crypto_mode_num mode_num, - unsigned int data_unit_size, - struct request_queue *q) -{ - struct blk_crypto_keyslot *slotp; - unsigned int i; - int err = 0; - - /* - * Fast path - * Ensure that updates to blk_crypto_keyslots[i].tfms[mode_num] - * for each i are visible before we try to access them. - */ - if (likely(smp_load_acquire(&tfms_inited[mode_num]))) - return 0; - - /* - * If the keyslot manager of the request queue supports this - * crypto mode, then we don't need to allocate this mode. - */ - if (keyslot_manager_crypto_mode_supported(q->ksm, mode_num, - data_unit_size)) - return 0; - - mutex_lock(&tfms_init_lock); - if (likely(tfms_inited[mode_num])) - goto out; - - for (i = 0; i < blk_crypto_num_keyslots; i++) { - slotp = &blk_crypto_keyslots[i]; - slotp->tfms[mode_num] = crypto_alloc_skcipher( - blk_crypto_modes[mode_num].cipher_str, - 0, 0); - if (IS_ERR(slotp->tfms[mode_num])) { - err = PTR_ERR(slotp->tfms[mode_num]); - slotp->tfms[mode_num] = NULL; - goto out_free_tfms; - } - - crypto_skcipher_set_flags(slotp->tfms[mode_num], - CRYPTO_TFM_REQ_WEAK_KEY); - } - - /* - * Ensure that updates to blk_crypto_keyslots[i].tfms[mode_num] - * for each i are visible before we set tfms_inited[mode_num]. - */ - smp_store_release(&tfms_inited[mode_num], true); - goto out; - -out_free_tfms: - for (i = 0; i < blk_crypto_num_keyslots; i++) { - slotp = &blk_crypto_keyslots[i]; - crypto_free_skcipher(slotp->tfms[mode_num]); - slotp->tfms[mode_num] = NULL; - } -out: - mutex_unlock(&tfms_init_lock); - return err; -} -EXPORT_SYMBOL_GPL(blk_crypto_start_using_mode); - -int blk_crypto_fallback_evict_key(const struct blk_crypto_key *key) -{ - return keyslot_manager_evict_key(blk_crypto_ksm, key); -} - -int blk_crypto_fallback_submit_bio(struct bio **bio_ptr) -{ - struct bio *bio = *bio_ptr; - struct bio_crypt_ctx *bc = bio->bi_crypt_context; - struct bio_fallback_crypt_ctx *f_ctx; - - if (!tfms_inited[bc->bc_key->crypto_mode]) { - bio->bi_status = BLK_STS_IOERR; - return -EIO; - } - - if (bio_data_dir(bio) == WRITE) - return blk_crypto_encrypt_bio(bio_ptr); - - /* - * Mark bio as fallback crypted and replace the bio_crypt_ctx with - * another one contained in a bio_fallback_crypt_ctx, so that the - * fallback has space to store the info it needs for decryption. - */ - bc->bc_ksm = blk_crypto_ksm; - f_ctx = mempool_alloc(bio_fallback_crypt_ctx_pool, GFP_NOIO); - f_ctx->crypt_ctx = *bc; - memcpy(f_ctx->fallback_dun, bc->bc_dun, sizeof(f_ctx->fallback_dun)); - f_ctx->crypt_iter = bio->bi_iter; - - bio_crypt_free_ctx(bio); - bio->bi_crypt_context = &f_ctx->crypt_ctx; - - return 0; -} - -int __init blk_crypto_fallback_init(void) -{ - int i; - unsigned int crypto_mode_supported[BLK_ENCRYPTION_MODE_MAX]; - - prandom_bytes(blank_key, BLK_CRYPTO_MAX_KEY_SIZE); - - /* All blk-crypto modes have a crypto API fallback. */ - for (i = 0; i < BLK_ENCRYPTION_MODE_MAX; i++) - crypto_mode_supported[i] = 0xFFFFFFFF; - crypto_mode_supported[BLK_ENCRYPTION_MODE_INVALID] = 0; - - blk_crypto_ksm = keyslot_manager_create(blk_crypto_num_keyslots, - &blk_crypto_ksm_ll_ops, - crypto_mode_supported, NULL); - if (!blk_crypto_ksm) - return -ENOMEM; - - blk_crypto_wq = alloc_workqueue("blk_crypto_wq", - WQ_UNBOUND | WQ_HIGHPRI | - WQ_MEM_RECLAIM, num_online_cpus()); - if (!blk_crypto_wq) - return -ENOMEM; - - blk_crypto_keyslots = kcalloc(blk_crypto_num_keyslots, - sizeof(blk_crypto_keyslots[0]), - GFP_KERNEL); - if (!blk_crypto_keyslots) - return -ENOMEM; - - blk_crypto_bounce_page_pool = - mempool_create_page_pool(num_prealloc_bounce_pg, 0); - if (!blk_crypto_bounce_page_pool) - return -ENOMEM; - - blk_crypto_decrypt_work_cache = KMEM_CACHE(blk_crypto_decrypt_work, - SLAB_RECLAIM_ACCOUNT); - if (!blk_crypto_decrypt_work_cache) - return -ENOMEM; - - bio_fallback_crypt_ctx_cache = KMEM_CACHE(bio_fallback_crypt_ctx, 0); - if (!bio_fallback_crypt_ctx_cache) - return -ENOMEM; - - bio_fallback_crypt_ctx_pool = - mempool_create_slab_pool(num_prealloc_fallback_crypt_ctxs, - bio_fallback_crypt_ctx_cache); - if (!bio_fallback_crypt_ctx_pool) - return -ENOMEM; - - return 0; -} diff --git a/block/blk-crypto-internal.h b/block/blk-crypto-internal.h deleted file mode 100644 index 40d826b743da..000000000000 --- a/block/blk-crypto-internal.h +++ /dev/null @@ -1,58 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright 2019 Google LLC - */ - -#ifndef __LINUX_BLK_CRYPTO_INTERNAL_H -#define __LINUX_BLK_CRYPTO_INTERNAL_H - -#include - -/* Represents a crypto mode supported by blk-crypto */ -struct blk_crypto_mode { - const char *cipher_str; /* crypto API name (for fallback case) */ - unsigned int keysize; /* key size in bytes */ - unsigned int ivsize; /* iv size in bytes */ -}; - -extern const struct blk_crypto_mode blk_crypto_modes[]; - -#ifdef CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK - -int blk_crypto_fallback_submit_bio(struct bio **bio_ptr); - -bool blk_crypto_queue_decrypt_bio(struct bio *bio); - -int blk_crypto_fallback_evict_key(const struct blk_crypto_key *key); - -bool bio_crypt_fallback_crypted(const struct bio_crypt_ctx *bc); - -#else /* CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK */ - -static inline bool bio_crypt_fallback_crypted(const struct bio_crypt_ctx *bc) -{ - return false; -} - -static inline int blk_crypto_fallback_submit_bio(struct bio **bio_ptr) -{ - pr_warn_once("crypto API fallback disabled; failing request\n"); - (*bio_ptr)->bi_status = BLK_STS_NOTSUPP; - return -EIO; -} - -static inline bool blk_crypto_queue_decrypt_bio(struct bio *bio) -{ - WARN_ON(1); - return false; -} - -static inline int -blk_crypto_fallback_evict_key(const struct blk_crypto_key *key) -{ - return 0; -} - -#endif /* CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK */ - -#endif /* __LINUX_BLK_CRYPTO_INTERNAL_H */ diff --git a/block/blk-crypto.c b/block/blk-crypto.c deleted file mode 100644 index a8de0d9680e0..000000000000 --- a/block/blk-crypto.c +++ /dev/null @@ -1,251 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright 2019 Google LLC - */ - -/* - * Refer to Documentation/block/inline-encryption.rst for detailed explanation. - */ - -#define pr_fmt(fmt) "blk-crypto: " fmt - -#include -#include -#include -#include -#include - -#include "blk-crypto-internal.h" - -const struct blk_crypto_mode blk_crypto_modes[] = { - [BLK_ENCRYPTION_MODE_AES_256_XTS] = { - .cipher_str = "xts(aes)", - .keysize = 64, - .ivsize = 16, - }, - [BLK_ENCRYPTION_MODE_AES_128_CBC_ESSIV] = { - .cipher_str = "essiv(cbc(aes),sha256)", - .keysize = 16, - .ivsize = 16, - }, - [BLK_ENCRYPTION_MODE_ADIANTUM] = { - .cipher_str = "adiantum(xchacha12,aes)", - .keysize = 32, - .ivsize = 32, - }, -}; - -/* Check that all I/O segments are data unit aligned */ -static int bio_crypt_check_alignment(struct bio *bio) -{ - const unsigned int data_unit_size = - bio->bi_crypt_context->bc_key->data_unit_size; - struct bvec_iter iter; - struct bio_vec bv; - - bio_for_each_segment(bv, bio, iter) { - if (!IS_ALIGNED(bv.bv_len | bv.bv_offset, data_unit_size)) - return -EIO; - } - return 0; -} - -/** - * blk_crypto_submit_bio - handle submitting bio for inline encryption - * - * @bio_ptr: pointer to original bio pointer - * - * If the bio doesn't have inline encryption enabled or the submitter already - * specified a keyslot for the target device, do nothing. Else, a raw key must - * have been provided, so acquire a device keyslot for it if supported. Else, - * use the crypto API fallback. - * - * When the crypto API fallback is used for encryption, blk-crypto may choose to - * split the bio into 2 - the first one that will continue to be processed and - * the second one that will be resubmitted via generic_make_request. - * A bounce bio will be allocated to encrypt the contents of the aforementioned - * "first one", and *bio_ptr will be updated to this bounce bio. - * - * Return: 0 if bio submission should continue; nonzero if bio_endio() was - * already called so bio submission should abort. - */ -int blk_crypto_submit_bio(struct bio **bio_ptr) -{ - struct bio *bio = *bio_ptr; - struct request_queue *q; - struct bio_crypt_ctx *bc = bio->bi_crypt_context; - int err; - - if (!bc || !bio_has_data(bio)) - return 0; - - /* - * When a read bio is marked for fallback decryption, its bi_iter is - * saved so that when we decrypt the bio later, we know what part of it - * was marked for fallback decryption (when the bio is passed down after - * blk_crypto_submit bio, it may be split or advanced so we cannot rely - * on the bi_iter while decrypting in blk_crypto_endio) - */ - if (bio_crypt_fallback_crypted(bc)) - return 0; - - err = bio_crypt_check_alignment(bio); - if (err) { - bio->bi_status = BLK_STS_IOERR; - goto out; - } - - q = bio->bi_disk->queue; - - if (bc->bc_ksm) { - /* Key already programmed into device? */ - if (q->ksm == bc->bc_ksm) - return 0; - - /* Nope, release the existing keyslot. */ - bio_crypt_ctx_release_keyslot(bc); - } - - /* Get device keyslot if supported */ - if (keyslot_manager_crypto_mode_supported(q->ksm, - bc->bc_key->crypto_mode, - bc->bc_key->data_unit_size)) { - err = bio_crypt_ctx_acquire_keyslot(bc, q->ksm); - if (!err) - return 0; - - pr_warn_once("Failed to acquire keyslot for %s (err=%d). Falling back to crypto API.\n", - bio->bi_disk->disk_name, err); - } - - /* Fallback to crypto API */ - err = blk_crypto_fallback_submit_bio(bio_ptr); - if (err) - goto out; - - return 0; -out: - bio_endio(*bio_ptr); - return err; -} - -/** - * blk_crypto_endio - clean up bio w.r.t inline encryption during bio_endio - * - * @bio: the bio to clean up - * - * If blk_crypto_submit_bio decided to fallback to crypto API for this bio, - * we queue the bio for decryption into a workqueue and return false, - * and call bio_endio(bio) at a later time (after the bio has been decrypted). - * - * If the bio is not to be decrypted by the crypto API, this function releases - * the reference to the keyslot that blk_crypto_submit_bio got. - * - * Return: true if bio_endio should continue; false otherwise (bio_endio will - * be called again when bio has been decrypted). - */ -bool blk_crypto_endio(struct bio *bio) -{ - struct bio_crypt_ctx *bc = bio->bi_crypt_context; - - if (!bc) - return true; - - if (bio_crypt_fallback_crypted(bc)) { - /* - * The only bios who's crypto is handled by the blk-crypto - * fallback when they reach here are those with - * bio_data_dir(bio) == READ, since WRITE bios that are - * encrypted by the crypto API fallback are handled by - * blk_crypto_encrypt_endio(). - */ - return !blk_crypto_queue_decrypt_bio(bio); - } - - if (bc->bc_keyslot >= 0) - bio_crypt_ctx_release_keyslot(bc); - - return true; -} - -/** - * blk_crypto_init_key() - Prepare a key for use with blk-crypto - * @blk_key: Pointer to the blk_crypto_key to initialize. - * @raw_key: Pointer to the raw key. - * @raw_key_size: Size of raw key. Must be at least the required size for the - * chosen @crypto_mode; see blk_crypto_modes[]. (It's allowed - * to be longer than the mode's actual key size, in order to - * support inline encryption hardware that accepts wrapped keys.) - * @crypto_mode: identifier for the encryption algorithm to use - * @data_unit_size: the data unit size to use for en/decryption - * - * Return: The blk_crypto_key that was prepared, or an ERR_PTR() on error. When - * done using the key, it must be freed with blk_crypto_free_key(). - */ -int blk_crypto_init_key(struct blk_crypto_key *blk_key, - const u8 *raw_key, unsigned int raw_key_size, - enum blk_crypto_mode_num crypto_mode, - unsigned int data_unit_size) -{ - const struct blk_crypto_mode *mode; - static siphash_key_t hash_key; - - memset(blk_key, 0, sizeof(*blk_key)); - - if (crypto_mode >= ARRAY_SIZE(blk_crypto_modes)) - return -EINVAL; - - BUILD_BUG_ON(BLK_CRYPTO_MAX_WRAPPED_KEY_SIZE < BLK_CRYPTO_MAX_KEY_SIZE); - - mode = &blk_crypto_modes[crypto_mode]; - if (raw_key_size < mode->keysize || - raw_key_size > BLK_CRYPTO_MAX_WRAPPED_KEY_SIZE) - return -EINVAL; - - if (!is_power_of_2(data_unit_size)) - return -EINVAL; - - blk_key->crypto_mode = crypto_mode; - blk_key->data_unit_size = data_unit_size; - blk_key->data_unit_size_bits = ilog2(data_unit_size); - blk_key->size = raw_key_size; - memcpy(blk_key->raw, raw_key, raw_key_size); - - /* - * The keyslot manager uses the SipHash of the key to implement O(1) key - * lookups while avoiding leaking information about the keys. It's - * precomputed here so that it only needs to be computed once per key. - */ - get_random_once(&hash_key, sizeof(hash_key)); - blk_key->hash = siphash(raw_key, raw_key_size, &hash_key); - - return 0; -} -EXPORT_SYMBOL_GPL(blk_crypto_init_key); - -/** - * blk_crypto_evict_key() - Evict a key from any inline encryption hardware - * it may have been programmed into - * @q: The request queue who's keyslot manager this key might have been - * programmed into - * @key: The key to evict - * - * Upper layers (filesystems) should call this function to ensure that a key - * is evicted from hardware that it might have been programmed into. This - * will call keyslot_manager_evict_key on the queue's keyslot manager, if one - * exists, and supports the crypto algorithm with the specified data unit size. - * Otherwise, it will evict the key from the blk-crypto-fallback's ksm. - * - * Return: 0 on success, -err on error. - */ -int blk_crypto_evict_key(struct request_queue *q, - const struct blk_crypto_key *key) -{ - if (q->ksm && - keyslot_manager_crypto_mode_supported(q->ksm, key->crypto_mode, - key->data_unit_size)) - return keyslot_manager_evict_key(q->ksm, key); - - return blk_crypto_fallback_evict_key(key); -} -EXPORT_SYMBOL_GPL(blk_crypto_evict_key); diff --git a/block/blk-merge.c b/block/blk-merge.c index 71768dc75602..415b5dafd9e6 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -504,8 +504,6 @@ int ll_back_merge_fn(struct request_queue *q, struct request *req, req_set_nomerge(q, req); return 0; } - if (!bio_crypt_ctx_mergeable(req->bio, blk_rq_bytes(req), bio)) - return 0; if (!bio_flagged(req->biotail, BIO_SEG_VALID)) blk_recount_segments(q, req->biotail); if (!bio_flagged(bio, BIO_SEG_VALID)) @@ -528,8 +526,6 @@ int ll_front_merge_fn(struct request_queue *q, struct request *req, req_set_nomerge(q, req); return 0; } - if (!bio_crypt_ctx_mergeable(bio, bio->bi_iter.bi_size, req->bio)) - return 0; if (!bio_flagged(bio, BIO_SEG_VALID)) blk_recount_segments(q, bio); if (!bio_flagged(req->bio, BIO_SEG_VALID)) @@ -606,9 +602,6 @@ static int ll_merge_requests_fn(struct request_queue *q, struct request *req, if (blk_integrity_merge_rq(q, req, next) == false) return 0; - if (!bio_crypt_ctx_mergeable(req->bio, blk_rq_bytes(req), next->bio)) - return 0; - /* Merge is OK... */ req->nr_phys_segments = total_phys_segments; return 1; @@ -857,10 +850,6 @@ bool blk_rq_merge_ok(struct request *rq, struct bio *bio) if (rq->write_hint != bio->bi_write_hint) return false; - /* Only merge if the crypt contexts are compatible */ - if (!bio_crypt_ctx_compatible(bio, rq->bio)) - return false; - return true; } diff --git a/block/keyslot-manager.c b/block/keyslot-manager.c deleted file mode 100644 index 7e42813c9de0..000000000000 --- a/block/keyslot-manager.c +++ /dev/null @@ -1,560 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright 2019 Google LLC - */ - -/** - * DOC: The Keyslot Manager - * - * Many devices with inline encryption support have a limited number of "slots" - * into which encryption contexts may be programmed, and requests can be tagged - * with a slot number to specify the key to use for en/decryption. - * - * As the number of slots are limited, and programming keys is expensive on - * many inline encryption hardware, we don't want to program the same key into - * multiple slots - if multiple requests are using the same key, we want to - * program just one slot with that key and use that slot for all requests. - * - * The keyslot manager manages these keyslots appropriately, and also acts as - * an abstraction between the inline encryption hardware and the upper layers. - * - * Lower layer devices will set up a keyslot manager in their request queue - * and tell it how to perform device specific operations like programming/ - * evicting keys from keyslots. - * - * Upper layers will call keyslot_manager_get_slot_for_key() to program a - * key into some slot in the inline encryption hardware. - */ -#include -#include -#include -#include -#include -#include -#include - -struct keyslot { - atomic_t slot_refs; - struct list_head idle_slot_node; - struct hlist_node hash_node; - struct blk_crypto_key key; -}; - -struct keyslot_manager { - unsigned int num_slots; - struct keyslot_mgmt_ll_ops ksm_ll_ops; - unsigned int crypto_mode_supported[BLK_ENCRYPTION_MODE_MAX]; - void *ll_priv_data; - - /* Protects programming and evicting keys from the device */ - struct rw_semaphore lock; - - /* List of idle slots, with least recently used slot at front */ - wait_queue_head_t idle_slots_wait_queue; - struct list_head idle_slots; - spinlock_t idle_slots_lock; - - /* - * Hash table which maps key hashes to keyslots, so that we can find a - * key's keyslot in O(1) time rather than O(num_slots). Protected by - * 'lock'. A cryptographic hash function is used so that timing attacks - * can't leak information about the raw keys. - */ - struct hlist_head *slot_hashtable; - unsigned int slot_hashtable_size; - - /* Per-keyslot data */ - struct keyslot slots[]; -}; - -static inline bool keyslot_manager_is_passthrough(struct keyslot_manager *ksm) -{ - return ksm->num_slots == 0; -} - -/** - * keyslot_manager_create() - Create a keyslot manager - * @num_slots: The number of key slots to manage. - * @ksm_ll_ops: The struct keyslot_mgmt_ll_ops for the device that this keyslot - * manager will use to perform operations like programming and - * evicting keys. - * @crypto_mode_supported: Array of size BLK_ENCRYPTION_MODE_MAX of - * bitmasks that represents whether a crypto mode - * and data unit size are supported. The i'th bit - * of crypto_mode_supported[crypto_mode] is set iff - * a data unit size of (1 << i) is supported. We - * only support data unit sizes that are powers of - * 2. - * @ll_priv_data: Private data passed as is to the functions in ksm_ll_ops. - * - * Allocate memory for and initialize a keyslot manager. Called by e.g. - * storage drivers to set up a keyslot manager in their request_queue. - * - * Context: May sleep - * Return: Pointer to constructed keyslot manager or NULL on error. - */ -struct keyslot_manager *keyslot_manager_create(unsigned int num_slots, - const struct keyslot_mgmt_ll_ops *ksm_ll_ops, - const unsigned int crypto_mode_supported[BLK_ENCRYPTION_MODE_MAX], - void *ll_priv_data) -{ - struct keyslot_manager *ksm; - unsigned int slot; - unsigned int i; - - if (num_slots == 0) - return NULL; - - /* Check that all ops are specified */ - if (ksm_ll_ops->keyslot_program == NULL || - ksm_ll_ops->keyslot_evict == NULL) - return NULL; - - ksm = kvzalloc(struct_size(ksm, slots, num_slots), GFP_KERNEL); - if (!ksm) - return NULL; - - ksm->num_slots = num_slots; - ksm->ksm_ll_ops = *ksm_ll_ops; - memcpy(ksm->crypto_mode_supported, crypto_mode_supported, - sizeof(ksm->crypto_mode_supported)); - ksm->ll_priv_data = ll_priv_data; - - init_rwsem(&ksm->lock); - - init_waitqueue_head(&ksm->idle_slots_wait_queue); - INIT_LIST_HEAD(&ksm->idle_slots); - - for (slot = 0; slot < num_slots; slot++) { - list_add_tail(&ksm->slots[slot].idle_slot_node, - &ksm->idle_slots); - } - - spin_lock_init(&ksm->idle_slots_lock); - - ksm->slot_hashtable_size = roundup_pow_of_two(num_slots); - ksm->slot_hashtable = kvmalloc_array(ksm->slot_hashtable_size, - sizeof(ksm->slot_hashtable[0]), - GFP_KERNEL); - if (!ksm->slot_hashtable) - goto err_free_ksm; - for (i = 0; i < ksm->slot_hashtable_size; i++) - INIT_HLIST_HEAD(&ksm->slot_hashtable[i]); - - return ksm; - -err_free_ksm: - keyslot_manager_destroy(ksm); - return NULL; -} -EXPORT_SYMBOL_GPL(keyslot_manager_create); - -static inline struct hlist_head * -hash_bucket_for_key(struct keyslot_manager *ksm, - const struct blk_crypto_key *key) -{ - return &ksm->slot_hashtable[key->hash & (ksm->slot_hashtable_size - 1)]; -} - -static void remove_slot_from_lru_list(struct keyslot_manager *ksm, int slot) -{ - unsigned long flags; - - spin_lock_irqsave(&ksm->idle_slots_lock, flags); - list_del(&ksm->slots[slot].idle_slot_node); - spin_unlock_irqrestore(&ksm->idle_slots_lock, flags); -} - -static int find_keyslot(struct keyslot_manager *ksm, - const struct blk_crypto_key *key) -{ - const struct hlist_head *head = hash_bucket_for_key(ksm, key); - const struct keyslot *slotp; - - hlist_for_each_entry(slotp, head, hash_node) { - if (slotp->key.hash == key->hash && - slotp->key.crypto_mode == key->crypto_mode && - slotp->key.size == key->size && - slotp->key.data_unit_size == key->data_unit_size && - !crypto_memneq(slotp->key.raw, key->raw, key->size)) - return slotp - ksm->slots; - } - return -ENOKEY; -} - -static int find_and_grab_keyslot(struct keyslot_manager *ksm, - const struct blk_crypto_key *key) -{ - int slot; - - slot = find_keyslot(ksm, key); - if (slot < 0) - return slot; - if (atomic_inc_return(&ksm->slots[slot].slot_refs) == 1) { - /* Took first reference to this slot; remove it from LRU list */ - remove_slot_from_lru_list(ksm, slot); - } - return slot; -} - -/** - * keyslot_manager_get_slot_for_key() - Program a key into a keyslot. - * @ksm: The keyslot manager to program the key into. - * @key: Pointer to the key object to program, including the raw key, crypto - * mode, and data unit size. - * - * Get a keyslot that's been programmed with the specified key. If one already - * exists, return it with incremented refcount. Otherwise, wait for a keyslot - * to become idle and program it. - * - * Context: Process context. Takes and releases ksm->lock. - * Return: The keyslot on success, else a -errno value. - */ -int keyslot_manager_get_slot_for_key(struct keyslot_manager *ksm, - const struct blk_crypto_key *key) -{ - int slot; - int err; - struct keyslot *idle_slot; - - if (keyslot_manager_is_passthrough(ksm)) - return 0; - - down_read(&ksm->lock); - slot = find_and_grab_keyslot(ksm, key); - up_read(&ksm->lock); - if (slot != -ENOKEY) - return slot; - - for (;;) { - down_write(&ksm->lock); - slot = find_and_grab_keyslot(ksm, key); - if (slot != -ENOKEY) { - up_write(&ksm->lock); - return slot; - } - - /* - * If we're here, that means there wasn't a slot that was - * already programmed with the key. So try to program it. - */ - if (!list_empty(&ksm->idle_slots)) - break; - - up_write(&ksm->lock); - wait_event(ksm->idle_slots_wait_queue, - !list_empty(&ksm->idle_slots)); - } - - idle_slot = list_first_entry(&ksm->idle_slots, struct keyslot, - idle_slot_node); - slot = idle_slot - ksm->slots; - - err = ksm->ksm_ll_ops.keyslot_program(ksm, key, slot); - if (err) { - wake_up(&ksm->idle_slots_wait_queue); - up_write(&ksm->lock); - return err; - } - - /* Move this slot to the hash list for the new key. */ - if (idle_slot->key.crypto_mode != BLK_ENCRYPTION_MODE_INVALID) - hlist_del(&idle_slot->hash_node); - hlist_add_head(&idle_slot->hash_node, hash_bucket_for_key(ksm, key)); - - atomic_set(&idle_slot->slot_refs, 1); - idle_slot->key = *key; - - remove_slot_from_lru_list(ksm, slot); - - up_write(&ksm->lock); - return slot; -} - -/** - * keyslot_manager_get_slot() - Increment the refcount on the specified slot. - * @ksm: The keyslot manager that we want to modify. - * @slot: The slot to increment the refcount of. - * - * This function assumes that there is already an active reference to that slot - * and simply increments the refcount. This is useful when cloning a bio that - * already has a reference to a keyslot, and we want the cloned bio to also have - * its own reference. - * - * Context: Any context. - */ -void keyslot_manager_get_slot(struct keyslot_manager *ksm, unsigned int slot) -{ - if (keyslot_manager_is_passthrough(ksm)) - return; - - if (WARN_ON(slot >= ksm->num_slots)) - return; - - WARN_ON(atomic_inc_return(&ksm->slots[slot].slot_refs) < 2); -} - -/** - * keyslot_manager_put_slot() - Release a reference to a slot - * @ksm: The keyslot manager to release the reference from. - * @slot: The slot to release the reference from. - * - * Context: Any context. - */ -void keyslot_manager_put_slot(struct keyslot_manager *ksm, unsigned int slot) -{ - unsigned long flags; - - if (keyslot_manager_is_passthrough(ksm)) - return; - - if (WARN_ON(slot >= ksm->num_slots)) - return; - - if (atomic_dec_and_lock_irqsave(&ksm->slots[slot].slot_refs, - &ksm->idle_slots_lock, flags)) { - list_add_tail(&ksm->slots[slot].idle_slot_node, - &ksm->idle_slots); - spin_unlock_irqrestore(&ksm->idle_slots_lock, flags); - wake_up(&ksm->idle_slots_wait_queue); - } -} - -/** - * keyslot_manager_crypto_mode_supported() - Find out if a crypto_mode/data - * unit size combination is supported - * by a ksm. - * @ksm: The keyslot manager to check - * @crypto_mode: The crypto mode to check for. - * @data_unit_size: The data_unit_size for the mode. - * - * Calls and returns the result of the crypto_mode_supported function specified - * by the ksm. - * - * Context: Process context. - * Return: Whether or not this ksm supports the specified crypto_mode/ - * data_unit_size combo. - */ -bool keyslot_manager_crypto_mode_supported(struct keyslot_manager *ksm, - enum blk_crypto_mode_num crypto_mode, - unsigned int data_unit_size) -{ - if (!ksm) - return false; - if (WARN_ON(crypto_mode >= BLK_ENCRYPTION_MODE_MAX)) - return false; - if (WARN_ON(!is_power_of_2(data_unit_size))) - return false; - return ksm->crypto_mode_supported[crypto_mode] & data_unit_size; -} - -/** - * keyslot_manager_evict_key() - Evict a key from the lower layer device. - * @ksm: The keyslot manager to evict from - * @key: The key to evict - * - * Find the keyslot that the specified key was programmed into, and evict that - * slot from the lower layer device if that slot is not currently in use. - * - * Context: Process context. Takes and releases ksm->lock. - * Return: 0 on success, -EBUSY if the key is still in use, or another - * -errno value on other error. - */ -int keyslot_manager_evict_key(struct keyslot_manager *ksm, - const struct blk_crypto_key *key) -{ - int slot; - int err; - struct keyslot *slotp; - - if (keyslot_manager_is_passthrough(ksm)) { - if (ksm->ksm_ll_ops.keyslot_evict) { - down_write(&ksm->lock); - err = ksm->ksm_ll_ops.keyslot_evict(ksm, key, -1); - up_write(&ksm->lock); - return err; - } - return 0; - } - - down_write(&ksm->lock); - slot = find_keyslot(ksm, key); - if (slot < 0) { - err = slot; - goto out_unlock; - } - slotp = &ksm->slots[slot]; - - if (atomic_read(&slotp->slot_refs) != 0) { - err = -EBUSY; - goto out_unlock; - } - err = ksm->ksm_ll_ops.keyslot_evict(ksm, key, slot); - if (err) - goto out_unlock; - - hlist_del(&slotp->hash_node); - memzero_explicit(&slotp->key, sizeof(slotp->key)); - err = 0; -out_unlock: - up_write(&ksm->lock); - return err; -} - -/** - * keyslot_manager_reprogram_all_keys() - Re-program all keyslots. - * @ksm: The keyslot manager - * - * Re-program all keyslots that are supposed to have a key programmed. This is - * intended only for use by drivers for hardware that loses its keys on reset. - * - * Context: Process context. Takes and releases ksm->lock. - */ -void keyslot_manager_reprogram_all_keys(struct keyslot_manager *ksm) -{ - unsigned int slot; - - if (WARN_ON(keyslot_manager_is_passthrough(ksm))) - return; - - down_write(&ksm->lock); - for (slot = 0; slot < ksm->num_slots; slot++) { - const struct keyslot *slotp = &ksm->slots[slot]; - int err; - - if (slotp->key.crypto_mode == BLK_ENCRYPTION_MODE_INVALID) - continue; - - err = ksm->ksm_ll_ops.keyslot_program(ksm, &slotp->key, slot); - WARN_ON(err); - } - up_write(&ksm->lock); -} -EXPORT_SYMBOL_GPL(keyslot_manager_reprogram_all_keys); - -/** - * keyslot_manager_private() - return the private data stored with ksm - * @ksm: The keyslot manager - * - * Returns the private data passed to the ksm when it was created. - */ -void *keyslot_manager_private(struct keyslot_manager *ksm) -{ - return ksm->ll_priv_data; -} -EXPORT_SYMBOL_GPL(keyslot_manager_private); - -void keyslot_manager_destroy(struct keyslot_manager *ksm) -{ - if (ksm) { - kvfree(ksm->slot_hashtable); - memzero_explicit(ksm, struct_size(ksm, slots, ksm->num_slots)); - kvfree(ksm); - } -} -EXPORT_SYMBOL_GPL(keyslot_manager_destroy); - -/** - * keyslot_manager_create_passthrough() - Create a passthrough keyslot manager - * @ksm_ll_ops: The struct keyslot_mgmt_ll_ops - * @crypto_mode_supported: Bitmasks for supported encryption modes - * @ll_priv_data: Private data passed as is to the functions in ksm_ll_ops. - * - * Allocate memory for and initialize a passthrough keyslot manager. - * Called by e.g. storage drivers to set up a keyslot manager in their - * request_queue, when the storage driver wants to manage its keys by itself. - * This is useful for inline encryption hardware that don't have a small fixed - * number of keyslots, and for layered devices. - * - * See keyslot_manager_create() for more details about the parameters. - * - * Context: This function may sleep - * Return: Pointer to constructed keyslot manager or NULL on error. - */ -struct keyslot_manager *keyslot_manager_create_passthrough( - const struct keyslot_mgmt_ll_ops *ksm_ll_ops, - const unsigned int crypto_mode_supported[BLK_ENCRYPTION_MODE_MAX], - void *ll_priv_data) -{ - struct keyslot_manager *ksm; - - ksm = kzalloc(sizeof(*ksm), GFP_KERNEL); - if (!ksm) - return NULL; - - ksm->ksm_ll_ops = *ksm_ll_ops; - memcpy(ksm->crypto_mode_supported, crypto_mode_supported, - sizeof(ksm->crypto_mode_supported)); - ksm->ll_priv_data = ll_priv_data; - - init_rwsem(&ksm->lock); - - return ksm; -} -EXPORT_SYMBOL_GPL(keyslot_manager_create_passthrough); - -/** - * keyslot_manager_intersect_modes() - restrict supported modes by child device - * @parent: The keyslot manager for parent device - * @child: The keyslot manager for child device, or NULL - * - * Clear any crypto mode support bits in @parent that aren't set in @child. - * If @child is NULL, then all parent bits are cleared. - * - * Only use this when setting up the keyslot manager for a layered device, - * before it's been exposed yet. - */ -void keyslot_manager_intersect_modes(struct keyslot_manager *parent, - const struct keyslot_manager *child) -{ - if (child) { - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(child->crypto_mode_supported); i++) { - parent->crypto_mode_supported[i] &= - child->crypto_mode_supported[i]; - } - } else { - memset(parent->crypto_mode_supported, 0, - sizeof(parent->crypto_mode_supported)); - } -} -EXPORT_SYMBOL_GPL(keyslot_manager_intersect_modes); - -/** - * keyslot_manager_derive_raw_secret() - Derive software secret from wrapped key - * @ksm: The keyslot manager - * @wrapped_key: The wrapped key - * @wrapped_key_size: Size of the wrapped key in bytes - * @secret: (output) the software secret - * @secret_size: (output) the number of secret bytes to derive - * - * Given a hardware-wrapped key, ask the hardware to derive a secret which - * software can use for cryptographic tasks other than inline encryption. The - * derived secret is guaranteed to be cryptographically isolated from the key - * with which any inline encryption with this wrapped key would actually be - * done. I.e., both will be derived from the unwrapped key. - * - * Return: 0 on success, -EOPNOTSUPP if hardware-wrapped keys are unsupported, - * or another -errno code. - */ -int keyslot_manager_derive_raw_secret(struct keyslot_manager *ksm, - const u8 *wrapped_key, - unsigned int wrapped_key_size, - u8 *secret, unsigned int secret_size) -{ - int err; - - down_write(&ksm->lock); - if (ksm->ksm_ll_ops.derive_raw_secret) { - err = ksm->ksm_ll_ops.derive_raw_secret(ksm, wrapped_key, - wrapped_key_size, - secret, secret_size); - } else { - err = -EOPNOTSUPP; - } - up_write(&ksm->lock); - - return err; -} -EXPORT_SYMBOL_GPL(keyslot_manager_derive_raw_secret); diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig index 1abc2380d9a6..0e643556bb44 100644 --- a/drivers/md/Kconfig +++ b/drivers/md/Kconfig @@ -286,27 +286,6 @@ config DM_CRYPT If unsure, say N. -config DM_DEFAULT_KEY - tristate "Default-key target support" - depends on BLK_DEV_DM - depends on BLK_INLINE_ENCRYPTION - # dm-default-key doesn't require -o inlinecrypt, but it does currently - # rely on the inline encryption hooks being built into the kernel. - depends on FS_ENCRYPTION_INLINE_CRYPT - help - This device-mapper target allows you to create a device that - assigns a default encryption key to bios that aren't for the - contents of an encrypted file. - - This ensures that all blocks on-disk will be encrypted with - some key, without the performance hit of file contents being - encrypted twice when fscrypt (File-Based Encryption) is used. - - It is only appropriate to use dm-default-key when key - configuration is tightly controlled, like it is in Android, - such that all fscrypt keys are at least as hard to compromise - as the default key. - config DM_SNAPSHOT tristate "Snapshot target" depends on BLK_DEV_DM diff --git a/drivers/md/Makefile b/drivers/md/Makefile index 144aec4fd08d..214be71181f4 100644 --- a/drivers/md/Makefile +++ b/drivers/md/Makefile @@ -43,7 +43,6 @@ obj-$(CONFIG_BLK_DEV_DM_BUILTIN) += dm-builtin.o obj-$(CONFIG_DM_BUFIO) += dm-bufio.o obj-$(CONFIG_DM_BIO_PRISON) += dm-bio-prison.o obj-$(CONFIG_DM_CRYPT) += dm-crypt.o -obj-$(CONFIG_DM_DEFAULT_KEY) += dm-default-key.o obj-$(CONFIG_DM_DELAY) += dm-delay.o obj-$(CONFIG_DM_FLAKEY) += dm-flakey.o obj-$(CONFIG_DM_MULTIPATH) += dm-multipath.o dm-round-robin.o diff --git a/drivers/md/dm-bow.c b/drivers/md/dm-bow.c index 28df18633853..b92da30a3d42 100644 --- a/drivers/md/dm-bow.c +++ b/drivers/md/dm-bow.c @@ -726,7 +726,6 @@ static int dm_bow_ctr(struct dm_target *ti, unsigned int argc, char **argv) rb_insert_color(&br->node, &bc->ranges); ti->discards_supported = true; - ti->may_passthrough_inline_crypto = true; return 0; diff --git a/drivers/md/dm-default-key.c b/drivers/md/dm-default-key.c deleted file mode 100644 index 43a30c076aa6..000000000000 --- a/drivers/md/dm-default-key.c +++ /dev/null @@ -1,403 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) 2017 Google, Inc. - */ - -#include -#include -#include - -#define DM_MSG_PREFIX "default-key" - -#define DM_DEFAULT_KEY_MAX_KEY_SIZE 64 - -#define SECTOR_SIZE (1 << SECTOR_SHIFT) - -static const struct dm_default_key_cipher { - const char *name; - enum blk_crypto_mode_num mode_num; - int key_size; -} dm_default_key_ciphers[] = { - { - .name = "aes-xts-plain64", - .mode_num = BLK_ENCRYPTION_MODE_AES_256_XTS, - .key_size = 64, - }, { - .name = "xchacha12,aes-adiantum-plain64", - .mode_num = BLK_ENCRYPTION_MODE_ADIANTUM, - .key_size = 32, - }, -}; - -/** - * struct dm_default_c - private data of a default-key target - * @dev: the underlying device - * @start: starting sector of the range of @dev which this target actually maps. - * For this purpose a "sector" is 512 bytes. - * @cipher_string: the name of the encryption algorithm being used - * @iv_offset: starting offset for IVs. IVs are generated as if the target were - * preceded by @iv_offset 512-byte sectors. - * @sector_size: crypto sector size in bytes (usually 4096) - * @sector_bits: log2(sector_size) - * @key: the encryption key to use - */ -struct default_key_c { - struct dm_dev *dev; - sector_t start; - const char *cipher_string; - u64 iv_offset; - unsigned int sector_size; - unsigned int sector_bits; - struct blk_crypto_key key; -}; - -static const struct dm_default_key_cipher * -lookup_cipher(const char *cipher_string) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(dm_default_key_ciphers); i++) { - if (strcmp(cipher_string, dm_default_key_ciphers[i].name) == 0) - return &dm_default_key_ciphers[i]; - } - return NULL; -} - -static void default_key_dtr(struct dm_target *ti) -{ - struct default_key_c *dkc = ti->private; - int err; - - if (dkc->dev) { - err = blk_crypto_evict_key(dkc->dev->bdev->bd_queue, &dkc->key); - if (err && err != -ENOKEY) - DMWARN("Failed to evict crypto key: %d", err); - dm_put_device(ti, dkc->dev); - } - kzfree(dkc->cipher_string); - kzfree(dkc); -} - -static int default_key_ctr_optional(struct dm_target *ti, - unsigned int argc, char **argv) -{ - struct default_key_c *dkc = ti->private; - struct dm_arg_set as; - static const struct dm_arg _args[] = { - {0, 3, "Invalid number of feature args"}, - }; - unsigned int opt_params; - const char *opt_string; - bool iv_large_sectors = false; - char dummy; - int err; - - as.argc = argc; - as.argv = argv; - - err = dm_read_arg_group(_args, &as, &opt_params, &ti->error); - if (err) - return err; - - while (opt_params--) { - opt_string = dm_shift_arg(&as); - if (!opt_string) { - ti->error = "Not enough feature arguments"; - return -EINVAL; - } - if (!strcmp(opt_string, "allow_discards")) { - ti->num_discard_bios = 1; - } else if (sscanf(opt_string, "sector_size:%u%c", - &dkc->sector_size, &dummy) == 1) { - if (dkc->sector_size < SECTOR_SIZE || - dkc->sector_size > 4096 || - !is_power_of_2(dkc->sector_size)) { - ti->error = "Invalid sector_size"; - return -EINVAL; - } - } else if (!strcmp(opt_string, "iv_large_sectors")) { - iv_large_sectors = true; - } else { - ti->error = "Invalid feature arguments"; - return -EINVAL; - } - } - - /* dm-default-key doesn't implement iv_large_sectors=false. */ - if (dkc->sector_size != SECTOR_SIZE && !iv_large_sectors) { - ti->error = "iv_large_sectors must be specified"; - return -EINVAL; - } - - return 0; -} - -/* - * Construct a default-key mapping: - * - * - * This syntax matches dm-crypt's, but lots of unneeded functionality has been - * removed. Also, dm-default-key requires that the "iv_large_sectors" option be - * given whenever a non-default sector size is used. - */ -static int default_key_ctr(struct dm_target *ti, unsigned int argc, char **argv) -{ - struct default_key_c *dkc; - const struct dm_default_key_cipher *cipher; - u8 raw_key[DM_DEFAULT_KEY_MAX_KEY_SIZE]; - unsigned long long tmpll; - char dummy; - int err; - - if (argc < 5) { - ti->error = "Not enough arguments"; - return -EINVAL; - } - - dkc = kzalloc(sizeof(*dkc), GFP_KERNEL); - if (!dkc) { - ti->error = "Out of memory"; - return -ENOMEM; - } - ti->private = dkc; - - /* */ - dkc->cipher_string = kstrdup(argv[0], GFP_KERNEL); - if (!dkc->cipher_string) { - ti->error = "Out of memory"; - err = -ENOMEM; - goto bad; - } - cipher = lookup_cipher(dkc->cipher_string); - if (!cipher) { - ti->error = "Unsupported cipher"; - err = -EINVAL; - goto bad; - } - - /* */ - if (strlen(argv[1]) != 2 * cipher->key_size) { - ti->error = "Incorrect key size for cipher"; - err = -EINVAL; - goto bad; - } - if (hex2bin(raw_key, argv[1], cipher->key_size) != 0) { - ti->error = "Malformed key string"; - err = -EINVAL; - goto bad; - } - - /* */ - if (sscanf(argv[2], "%llu%c", &dkc->iv_offset, &dummy) != 1) { - ti->error = "Invalid iv_offset sector"; - err = -EINVAL; - goto bad; - } - - /* */ - err = dm_get_device(ti, argv[3], dm_table_get_mode(ti->table), - &dkc->dev); - if (err) { - ti->error = "Device lookup failed"; - goto bad; - } - - /* */ - if (sscanf(argv[4], "%llu%c", &tmpll, &dummy) != 1 || - tmpll != (sector_t)tmpll) { - ti->error = "Invalid start sector"; - err = -EINVAL; - goto bad; - } - dkc->start = tmpll; - - /* optional arguments */ - dkc->sector_size = SECTOR_SIZE; - if (argc > 5) { - err = default_key_ctr_optional(ti, argc - 5, &argv[5]); - if (err) - goto bad; - } - dkc->sector_bits = ilog2(dkc->sector_size); - if (ti->len & ((dkc->sector_size >> SECTOR_SHIFT) - 1)) { - ti->error = "Device size is not a multiple of sector_size"; - err = -EINVAL; - goto bad; - } - - err = blk_crypto_init_key(&dkc->key, raw_key, cipher->key_size, - cipher->mode_num, dkc->sector_size); - if (err) { - ti->error = "Error initializing blk-crypto key"; - goto bad; - } - - err = blk_crypto_start_using_mode(cipher->mode_num, dkc->sector_size, - dkc->dev->bdev->bd_queue); - if (err) { - ti->error = "Error starting to use blk-crypto"; - goto bad; - } - - ti->num_flush_bios = 1; - - ti->may_passthrough_inline_crypto = true; - - err = 0; - goto out; - -bad: - default_key_dtr(ti); -out: - memzero_explicit(raw_key, sizeof(raw_key)); - return err; -} - -static int default_key_map(struct dm_target *ti, struct bio *bio) -{ - const struct default_key_c *dkc = ti->private; - sector_t sector_in_target; - u64 dun[BLK_CRYPTO_DUN_ARRAY_SIZE] = { 0 }; - - bio_set_dev(bio, dkc->dev->bdev); - - /* - * If the bio is a device-level request which doesn't target a specific - * sector, there's nothing more to do. - */ - if (bio_sectors(bio) == 0) - return DM_MAPIO_REMAPPED; - - /* Map the bio's sector to the underlying device. (512-byte sectors) */ - sector_in_target = dm_target_offset(ti, bio->bi_iter.bi_sector); - bio->bi_iter.bi_sector = dkc->start + sector_in_target; - - /* - * If the bio should skip dm-default-key (i.e. if it's for an encrypted - * file's contents), or if it doesn't have any data (e.g. if it's a - * DISCARD request), there's nothing more to do. - */ - if (bio_should_skip_dm_default_key(bio) || !bio_has_data(bio)) - return DM_MAPIO_REMAPPED; - - /* - * Else, dm-default-key needs to set this bio's encryption context. - * It must not already have one. - */ - if (WARN_ON_ONCE(bio_has_crypt_ctx(bio))) - return DM_MAPIO_KILL; - - /* Calculate the DUN and enforce data-unit (crypto sector) alignment. */ - dun[0] = dkc->iv_offset + sector_in_target; /* 512-byte sectors */ - if (dun[0] & ((dkc->sector_size >> SECTOR_SHIFT) - 1)) - return DM_MAPIO_KILL; - dun[0] >>= dkc->sector_bits - SECTOR_SHIFT; /* crypto sectors */ - - bio_crypt_set_ctx(bio, &dkc->key, dun, GFP_NOIO); - - return DM_MAPIO_REMAPPED; -} - -static void default_key_status(struct dm_target *ti, status_type_t type, - unsigned int status_flags, char *result, - unsigned int maxlen) -{ - const struct default_key_c *dkc = ti->private; - unsigned int sz = 0; - int num_feature_args = 0; - - switch (type) { - case STATUSTYPE_INFO: - result[0] = '\0'; - break; - - case STATUSTYPE_TABLE: - /* Omit the key for now. */ - DMEMIT("%s - %llu %s %llu", dkc->cipher_string, dkc->iv_offset, - dkc->dev->name, (unsigned long long)dkc->start); - - num_feature_args += !!ti->num_discard_bios; - if (dkc->sector_size != SECTOR_SIZE) - num_feature_args += 2; - if (num_feature_args != 0) { - DMEMIT(" %d", num_feature_args); - if (ti->num_discard_bios) - DMEMIT(" allow_discards"); - if (dkc->sector_size != SECTOR_SIZE) { - DMEMIT(" sector_size:%u", dkc->sector_size); - DMEMIT(" iv_large_sectors"); - } - } - break; - } -} - -static int default_key_prepare_ioctl(struct dm_target *ti, - struct block_device **bdev, - fmode_t *mode) -{ - const struct default_key_c *dkc = ti->private; - const struct dm_dev *dev = dkc->dev; - - *bdev = dev->bdev; - - /* Only pass ioctls through if the device sizes match exactly. */ - if (dkc->start != 0 || - ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT) - return 1; - return 0; -} - -static int default_key_iterate_devices(struct dm_target *ti, - iterate_devices_callout_fn fn, - void *data) -{ - const struct default_key_c *dkc = ti->private; - - return fn(ti, dkc->dev, dkc->start, ti->len, data); -} - -static void default_key_io_hints(struct dm_target *ti, - struct queue_limits *limits) -{ - const struct default_key_c *dkc = ti->private; - const unsigned int sector_size = dkc->sector_size; - - limits->logical_block_size = - max_t(unsigned short, limits->logical_block_size, sector_size); - limits->physical_block_size = - max_t(unsigned int, limits->physical_block_size, sector_size); - limits->io_min = max_t(unsigned int, limits->io_min, sector_size); -} - -static struct target_type default_key_target = { - .name = "default-key", - .version = {2, 0, 0}, - .module = THIS_MODULE, - .ctr = default_key_ctr, - .dtr = default_key_dtr, - .map = default_key_map, - .status = default_key_status, - .prepare_ioctl = default_key_prepare_ioctl, - .iterate_devices = default_key_iterate_devices, - .io_hints = default_key_io_hints, -}; - -static int __init dm_default_key_init(void) -{ - return dm_register_target(&default_key_target); -} - -static void __exit dm_default_key_exit(void) -{ - dm_unregister_target(&default_key_target); -} - -module_init(dm_default_key_init); -module_exit(dm_default_key_exit); - -MODULE_AUTHOR("Paul Lawrence "); -MODULE_AUTHOR("Paul Crowley "); -MODULE_AUTHOR("Eric Biggers "); -MODULE_DESCRIPTION(DM_NAME " target for encrypting filesystem metadata"); -MODULE_LICENSE("GPL"); diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c index aa294720b14e..e6fd31b03c38 100644 --- a/drivers/md/dm-linear.c +++ b/drivers/md/dm-linear.c @@ -61,7 +61,6 @@ int dm_linear_ctr(struct dm_target *ti, unsigned int argc, char **argv) ti->num_discard_bios = 1; ti->num_write_same_bios = 1; ti->num_write_zeroes_bios = 1; - ti->may_passthrough_inline_crypto = true; ti->private = lc; return 0; diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 3d095bdc2681..6e184378ac61 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -21,8 +21,6 @@ #include #include #include -#include -#include #define DM_MSG_PREFIX "table" @@ -1598,54 +1596,6 @@ static void dm_table_verify_integrity(struct dm_table *t) } } -#ifdef CONFIG_BLK_INLINE_ENCRYPTION -static int device_intersect_crypto_modes(struct dm_target *ti, - struct dm_dev *dev, sector_t start, - sector_t len, void *data) -{ - struct keyslot_manager *parent = data; - struct keyslot_manager *child = bdev_get_queue(dev->bdev)->ksm; - - keyslot_manager_intersect_modes(parent, child); - return 0; -} - -/* - * Update the inline crypto modes supported by 'q->ksm' to be the intersection - * of the modes supported by all targets in the table. - * - * For any mode to be supported at all, all targets must have explicitly - * declared that they can pass through inline crypto support. For a particular - * mode to be supported, all underlying devices must also support it. - * - * Assume that 'q->ksm' initially declares all modes to be supported. - */ -static void dm_calculate_supported_crypto_modes(struct dm_table *t, - struct request_queue *q) -{ - struct dm_target *ti; - unsigned int i; - - for (i = 0; i < dm_table_get_num_targets(t); i++) { - ti = dm_table_get_target(t, i); - - if (!ti->may_passthrough_inline_crypto) { - keyslot_manager_intersect_modes(q->ksm, NULL); - return; - } - if (!ti->type->iterate_devices) - continue; - ti->type->iterate_devices(ti, device_intersect_crypto_modes, - q->ksm); - } -} -#else /* CONFIG_BLK_INLINE_ENCRYPTION */ -static inline void dm_calculate_supported_crypto_modes(struct dm_table *t, - struct request_queue *q) -{ -} -#endif /* !CONFIG_BLK_INLINE_ENCRYPTION */ - static int device_flush_capable(struct dm_target *ti, struct dm_dev *dev, sector_t start, sector_t len, void *data) { @@ -1920,8 +1870,6 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, dm_table_verify_integrity(t); - dm_calculate_supported_crypto_modes(t, q); - /* * Some devices don't use blk_integrity but still want stable pages * because they do their own checksumming. diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 0189f70e87a0..02ba6849f89d 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -24,8 +24,6 @@ #include #include #include -#include -#include #define DM_MSG_PREFIX "core" @@ -1251,10 +1249,9 @@ static int clone_bio(struct dm_target_io *tio, struct bio *bio, __bio_clone_fast(clone, bio); - bio_crypt_clone(clone, bio, GFP_NOIO); - if (unlikely(bio_integrity(bio) != NULL)) { int r; + if (unlikely(!dm_target_has_integrity(tio->ti->type) && !dm_target_passes_integrity(tio->ti->type))) { DMWARN("%s: the target %s doesn't support integrity data.", @@ -1664,8 +1661,6 @@ void dm_init_normal_md_queue(struct mapped_device *md) md->queue->backing_dev_info->congested_fn = dm_any_congested; } -static void dm_destroy_inline_encryption(struct request_queue *q); - static void cleanup_mapped_device(struct mapped_device *md) { if (md->wq) @@ -1690,10 +1685,8 @@ static void cleanup_mapped_device(struct mapped_device *md) put_disk(md->disk); } - if (md->queue) { - dm_destroy_inline_encryption(md->queue); + if (md->queue) blk_cleanup_queue(md->queue); - } cleanup_srcu_struct(&md->io_barrier); @@ -2042,89 +2035,6 @@ struct queue_limits *dm_get_queue_limits(struct mapped_device *md) } EXPORT_SYMBOL_GPL(dm_get_queue_limits); -#ifdef CONFIG_BLK_INLINE_ENCRYPTION -struct dm_keyslot_evict_args { - const struct blk_crypto_key *key; - int err; -}; - -static int dm_keyslot_evict_callback(struct dm_target *ti, struct dm_dev *dev, - sector_t start, sector_t len, void *data) -{ - struct dm_keyslot_evict_args *args = data; - int err; - - err = blk_crypto_evict_key(dev->bdev->bd_queue, args->key); - if (!args->err) - args->err = err; - /* Always try to evict the key from all devices. */ - return 0; -} - -/* - * When an inline encryption key is evicted from a device-mapper device, evict - * it from all the underlying devices. - */ -static int dm_keyslot_evict(struct keyslot_manager *ksm, - const struct blk_crypto_key *key, unsigned int slot) -{ - struct mapped_device *md = keyslot_manager_private(ksm); - struct dm_keyslot_evict_args args = { key }; - struct dm_table *t; - int srcu_idx; - int i; - struct dm_target *ti; - - t = dm_get_live_table(md, &srcu_idx); - if (!t) - return 0; - for (i = 0; i < dm_table_get_num_targets(t); i++) { - ti = dm_table_get_target(t, i); - if (!ti->type->iterate_devices) - continue; - ti->type->iterate_devices(ti, dm_keyslot_evict_callback, &args); - } - dm_put_live_table(md, srcu_idx); - return args.err; -} - -static struct keyslot_mgmt_ll_ops dm_ksm_ll_ops = { - .keyslot_evict = dm_keyslot_evict, -}; - -static int dm_init_inline_encryption(struct mapped_device *md) -{ - unsigned int mode_masks[BLK_ENCRYPTION_MODE_MAX]; - - /* - * Start out with all crypto mode support bits set. Any unsupported - * bits will be cleared later when calculating the device restrictions. - */ - memset(mode_masks, 0xFF, sizeof(mode_masks)); - - md->queue->ksm = keyslot_manager_create_passthrough(&dm_ksm_ll_ops, - mode_masks, md); - if (!md->queue->ksm) - return -ENOMEM; - return 0; -} - -static void dm_destroy_inline_encryption(struct request_queue *q) -{ - keyslot_manager_destroy(q->ksm); - q->ksm = NULL; -} -#else /* CONFIG_BLK_INLINE_ENCRYPTION */ -static inline int dm_init_inline_encryption(struct mapped_device *md) -{ - return 0; -} - -static inline void dm_destroy_inline_encryption(struct request_queue *q) -{ -} -#endif /* !CONFIG_BLK_INLINE_ENCRYPTION */ - /* * Setup the DM device's queue based on md's type */ @@ -2163,12 +2073,6 @@ int dm_setup_md_queue(struct mapped_device *md, struct dm_table *t) break; } - r = dm_init_inline_encryption(md); - if (r) { - DMERR("Cannot initialize inline encryption"); - return r; - } - return 0; } diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig index a2ec629bc466..e27b4d4e6ae2 100644 --- a/drivers/scsi/ufs/Kconfig +++ b/drivers/scsi/ufs/Kconfig @@ -100,12 +100,3 @@ config SCSI_UFS_QCOM Select this if you have UFS controller on QCOM chipset. If unsure, say N. - -config SCSI_UFS_CRYPTO - bool "UFS Crypto Engine Support" - depends on SCSI_UFSHCD && BLK_INLINE_ENCRYPTION - help - Enable Crypto Engine Support in UFS. - Enabling this makes it possible for the kernel to use the crypto - capabilities of the UFS device (if present) to perform crypto - operations on data being transferred to/from the device. diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile index 9e94ee6d5289..9310c6c83041 100644 --- a/drivers/scsi/ufs/Makefile +++ b/drivers/scsi/ufs/Makefile @@ -3,8 +3,6 @@ obj-$(CONFIG_SCSI_UFS_DWC_TC_PCI) += tc-dwc-g210-pci.o ufshcd-dwc.o tc-dwc-g210.o obj-$(CONFIG_SCSI_UFS_DWC_TC_PLATFORM) += tc-dwc-g210-pltfrm.o ufshcd-dwc.o tc-dwc-g210.o obj-$(CONFIG_SCSI_UFS_QCOM) += ufs-qcom.o -obj-$(CONFIG_SCSI_UFSHCD) += ufshcd-core.o -ufshcd-core-y := ufshcd.o +obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o -ufshcd-core-$(CONFIG_SCSI_UFS_CRYPTO) += ufshcd-crypto.o diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index 55463471651c..c87d770b519a 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -1103,13 +1103,6 @@ static void ufs_qcom_advertise_quirks(struct ufs_hba *hba) | UFSHCD_QUIRK_DME_PEER_ACCESS_AUTO_MODE | UFSHCD_QUIRK_BROKEN_PA_RXHSUNTERMCAP); } - - /* - * Inline crypto is currently broken with ufs-qcom at least because the - * device tree doesn't include the crypto registers. There are likely - * to be other issues that will need to be addressed too. - */ - hba->quirks |= UFSHCD_QUIRK_BROKEN_CRYPTO; } static void ufs_qcom_set_caps(struct ufs_hba *hba) diff --git a/drivers/scsi/ufs/ufshcd-crypto.c b/drivers/scsi/ufs/ufshcd-crypto.c deleted file mode 100644 index 276b49ad13be..000000000000 --- a/drivers/scsi/ufs/ufshcd-crypto.c +++ /dev/null @@ -1,499 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright 2019 Google LLC - */ - -#include -#include "ufshcd.h" -#include "ufshcd-crypto.h" - -static bool ufshcd_cap_idx_valid(struct ufs_hba *hba, unsigned int cap_idx) -{ - return cap_idx < hba->crypto_capabilities.num_crypto_cap; -} - -static u8 get_data_unit_size_mask(unsigned int data_unit_size) -{ - if (data_unit_size < 512 || data_unit_size > 65536 || - !is_power_of_2(data_unit_size)) - return 0; - - return data_unit_size / 512; -} - -static size_t get_keysize_bytes(enum ufs_crypto_key_size size) -{ - switch (size) { - case UFS_CRYPTO_KEY_SIZE_128: - return 16; - case UFS_CRYPTO_KEY_SIZE_192: - return 24; - case UFS_CRYPTO_KEY_SIZE_256: - return 32; - case UFS_CRYPTO_KEY_SIZE_512: - return 64; - default: - return 0; - } -} - -int ufshcd_crypto_cap_find(struct ufs_hba *hba, - enum blk_crypto_mode_num crypto_mode, - unsigned int data_unit_size) -{ - enum ufs_crypto_alg ufs_alg; - u8 data_unit_mask; - int cap_idx; - enum ufs_crypto_key_size ufs_key_size; - union ufs_crypto_cap_entry *ccap_array = hba->crypto_cap_array; - - if (!ufshcd_hba_is_crypto_supported(hba)) - return -EINVAL; - - switch (crypto_mode) { - case BLK_ENCRYPTION_MODE_AES_256_XTS: - ufs_alg = UFS_CRYPTO_ALG_AES_XTS; - ufs_key_size = UFS_CRYPTO_KEY_SIZE_256; - break; - default: - return -EINVAL; - } - - data_unit_mask = get_data_unit_size_mask(data_unit_size); - - for (cap_idx = 0; cap_idx < hba->crypto_capabilities.num_crypto_cap; - cap_idx++) { - if (ccap_array[cap_idx].algorithm_id == ufs_alg && - (ccap_array[cap_idx].sdus_mask & data_unit_mask) && - ccap_array[cap_idx].key_size == ufs_key_size) - return cap_idx; - } - - return -EINVAL; -} -EXPORT_SYMBOL(ufshcd_crypto_cap_find); - -/** - * ufshcd_crypto_cfg_entry_write_key - Write a key into a crypto_cfg_entry - * - * Writes the key with the appropriate format - for AES_XTS, - * the first half of the key is copied as is, the second half is - * copied with an offset halfway into the cfg->crypto_key array. - * For the other supported crypto algs, the key is just copied. - * - * @cfg: The crypto config to write to - * @key: The key to write - * @cap: The crypto capability (which specifies the crypto alg and key size) - * - * Returns 0 on success, or -EINVAL - */ -static int ufshcd_crypto_cfg_entry_write_key(union ufs_crypto_cfg_entry *cfg, - const u8 *key, - union ufs_crypto_cap_entry cap) -{ - size_t key_size_bytes = get_keysize_bytes(cap.key_size); - - if (key_size_bytes == 0) - return -EINVAL; - - switch (cap.algorithm_id) { - case UFS_CRYPTO_ALG_AES_XTS: - key_size_bytes *= 2; - if (key_size_bytes > UFS_CRYPTO_KEY_MAX_SIZE) - return -EINVAL; - - memcpy(cfg->crypto_key, key, key_size_bytes/2); - memcpy(cfg->crypto_key + UFS_CRYPTO_KEY_MAX_SIZE/2, - key + key_size_bytes/2, key_size_bytes/2); - return 0; - case UFS_CRYPTO_ALG_BITLOCKER_AES_CBC: - /* fall through */ - case UFS_CRYPTO_ALG_AES_ECB: - /* fall through */ - case UFS_CRYPTO_ALG_ESSIV_AES_CBC: - memcpy(cfg->crypto_key, key, key_size_bytes); - return 0; - } - - return -EINVAL; -} - -static int ufshcd_program_key(struct ufs_hba *hba, - const union ufs_crypto_cfg_entry *cfg, int slot) -{ - int i; - u32 slot_offset = hba->crypto_cfg_register + slot * sizeof(*cfg); - int err; - - pm_runtime_get_sync(hba->dev); - ufshcd_hold(hba, false); - - if (hba->vops->program_key) { - err = hba->vops->program_key(hba, cfg, slot); - goto out; - } - - /* Clear the dword 16 */ - ufshcd_writel(hba, 0, slot_offset + 16 * sizeof(cfg->reg_val[0])); - /* Ensure that CFGE is cleared before programming the key */ - wmb(); - for (i = 0; i < 16; i++) { - ufshcd_writel(hba, le32_to_cpu(cfg->reg_val[i]), - slot_offset + i * sizeof(cfg->reg_val[0])); - /* Spec says each dword in key must be written sequentially */ - wmb(); - } - /* Write dword 17 */ - ufshcd_writel(hba, le32_to_cpu(cfg->reg_val[17]), - slot_offset + 17 * sizeof(cfg->reg_val[0])); - /* Dword 16 must be written last */ - wmb(); - /* Write dword 16 */ - ufshcd_writel(hba, le32_to_cpu(cfg->reg_val[16]), - slot_offset + 16 * sizeof(cfg->reg_val[0])); - wmb(); - err = 0; -out: - ufshcd_release(hba); - pm_runtime_put_sync(hba->dev); - return err; -} - -static void ufshcd_clear_keyslot(struct ufs_hba *hba, int slot) -{ - union ufs_crypto_cfg_entry cfg = { 0 }; - int err; - - err = ufshcd_program_key(hba, &cfg, slot); - WARN_ON_ONCE(err); -} - -/* Clear all keyslots at driver init time */ -static void ufshcd_clear_all_keyslots(struct ufs_hba *hba) -{ - int slot; - - for (slot = 0; slot < ufshcd_num_keyslots(hba); slot++) - ufshcd_clear_keyslot(hba, slot); -} - -static int ufshcd_crypto_keyslot_program(struct keyslot_manager *ksm, - const struct blk_crypto_key *key, - unsigned int slot) -{ - struct ufs_hba *hba = keyslot_manager_private(ksm); - int err = 0; - u8 data_unit_mask; - union ufs_crypto_cfg_entry cfg; - int cap_idx; - - cap_idx = ufshcd_crypto_cap_find(hba, key->crypto_mode, - key->data_unit_size); - - if (!ufshcd_is_crypto_enabled(hba) || - !ufshcd_keyslot_valid(hba, slot) || - !ufshcd_cap_idx_valid(hba, cap_idx)) - return -EINVAL; - - data_unit_mask = get_data_unit_size_mask(key->data_unit_size); - - if (!(data_unit_mask & hba->crypto_cap_array[cap_idx].sdus_mask)) - return -EINVAL; - - memset(&cfg, 0, sizeof(cfg)); - cfg.data_unit_size = data_unit_mask; - cfg.crypto_cap_idx = cap_idx; - cfg.config_enable |= UFS_CRYPTO_CONFIGURATION_ENABLE; - - err = ufshcd_crypto_cfg_entry_write_key(&cfg, key->raw, - hba->crypto_cap_array[cap_idx]); - if (err) - return err; - - err = ufshcd_program_key(hba, &cfg, slot); - - memzero_explicit(&cfg, sizeof(cfg)); - - return err; -} - -static int ufshcd_crypto_keyslot_evict(struct keyslot_manager *ksm, - const struct blk_crypto_key *key, - unsigned int slot) -{ - struct ufs_hba *hba = keyslot_manager_private(ksm); - - if (!ufshcd_is_crypto_enabled(hba) || - !ufshcd_keyslot_valid(hba, slot)) - return -EINVAL; - - /* - * Clear the crypto cfg on the device. Clearing CFGE - * might not be sufficient, so just clear the entire cfg. - */ - ufshcd_clear_keyslot(hba, slot); - - return 0; -} - -/* Functions implementing UFSHCI v2.1 specification behaviour */ -void ufshcd_crypto_enable_spec(struct ufs_hba *hba) -{ - if (!ufshcd_hba_is_crypto_supported(hba)) - return; - - hba->caps |= UFSHCD_CAP_CRYPTO; - - /* Reset might clear all keys, so reprogram all the keys. */ - keyslot_manager_reprogram_all_keys(hba->ksm); -} -EXPORT_SYMBOL_GPL(ufshcd_crypto_enable_spec); - -void ufshcd_crypto_disable_spec(struct ufs_hba *hba) -{ - hba->caps &= ~UFSHCD_CAP_CRYPTO; -} -EXPORT_SYMBOL_GPL(ufshcd_crypto_disable_spec); - -static const struct keyslot_mgmt_ll_ops ufshcd_ksm_ops = { - .keyslot_program = ufshcd_crypto_keyslot_program, - .keyslot_evict = ufshcd_crypto_keyslot_evict, -}; - -enum blk_crypto_mode_num ufshcd_blk_crypto_mode_num_for_alg_dusize( - enum ufs_crypto_alg ufs_crypto_alg, - enum ufs_crypto_key_size key_size) -{ - /* - * This is currently the only mode that UFS and blk-crypto both support. - */ - if (ufs_crypto_alg == UFS_CRYPTO_ALG_AES_XTS && - key_size == UFS_CRYPTO_KEY_SIZE_256) - return BLK_ENCRYPTION_MODE_AES_256_XTS; - - return BLK_ENCRYPTION_MODE_INVALID; -} - -/** - * ufshcd_hba_init_crypto - Read crypto capabilities, init crypto fields in hba - * @hba: Per adapter instance - * - * Return: 0 if crypto was initialized or is not supported, else a -errno value. - */ -int ufshcd_hba_init_crypto_spec(struct ufs_hba *hba, - const struct keyslot_mgmt_ll_ops *ksm_ops) -{ - int cap_idx = 0; - int err = 0; - unsigned int crypto_modes_supported[BLK_ENCRYPTION_MODE_MAX]; - enum blk_crypto_mode_num blk_mode_num; - - /* Default to disabling crypto */ - hba->caps &= ~UFSHCD_CAP_CRYPTO; - - /* Return 0 if crypto support isn't present */ - if (!(hba->capabilities & MASK_CRYPTO_SUPPORT) || - (hba->quirks & UFSHCD_QUIRK_BROKEN_CRYPTO)) - goto out; - - /* - * Crypto Capabilities should never be 0, because the - * config_array_ptr > 04h. So we use a 0 value to indicate that - * crypto init failed, and can't be enabled. - */ - hba->crypto_capabilities.reg_val = - cpu_to_le32(ufshcd_readl(hba, REG_UFS_CCAP)); - hba->crypto_cfg_register = - (u32)hba->crypto_capabilities.config_array_ptr * 0x100; - hba->crypto_cap_array = - devm_kcalloc(hba->dev, - hba->crypto_capabilities.num_crypto_cap, - sizeof(hba->crypto_cap_array[0]), - GFP_KERNEL); - if (!hba->crypto_cap_array) { - err = -ENOMEM; - goto out; - } - - memset(crypto_modes_supported, 0, sizeof(crypto_modes_supported)); - /* - * Store all the capabilities now so that we don't need to repeatedly - * access the device each time we want to know its capabilities - */ - for (cap_idx = 0; cap_idx < hba->crypto_capabilities.num_crypto_cap; - cap_idx++) { - hba->crypto_cap_array[cap_idx].reg_val = - cpu_to_le32(ufshcd_readl(hba, - REG_UFS_CRYPTOCAP + - cap_idx * sizeof(__le32))); - blk_mode_num = ufshcd_blk_crypto_mode_num_for_alg_dusize( - hba->crypto_cap_array[cap_idx].algorithm_id, - hba->crypto_cap_array[cap_idx].key_size); - if (blk_mode_num == BLK_ENCRYPTION_MODE_INVALID) - continue; - crypto_modes_supported[blk_mode_num] |= - hba->crypto_cap_array[cap_idx].sdus_mask * 512; - } - - ufshcd_clear_all_keyslots(hba); - - hba->ksm = keyslot_manager_create(ufshcd_num_keyslots(hba), ksm_ops, - crypto_modes_supported, hba); - - if (!hba->ksm) { - err = -ENOMEM; - goto out_free_caps; - } - - return 0; - -out_free_caps: - devm_kfree(hba->dev, hba->crypto_cap_array); -out: - /* Indicate that init failed by setting crypto_capabilities to 0 */ - hba->crypto_capabilities.reg_val = 0; - return err; -} -EXPORT_SYMBOL_GPL(ufshcd_hba_init_crypto_spec); - -void ufshcd_crypto_setup_rq_keyslot_manager_spec(struct ufs_hba *hba, - struct request_queue *q) -{ - if (!ufshcd_hba_is_crypto_supported(hba) || !q) - return; - - q->ksm = hba->ksm; -} -EXPORT_SYMBOL_GPL(ufshcd_crypto_setup_rq_keyslot_manager_spec); - -void ufshcd_crypto_destroy_rq_keyslot_manager_spec(struct ufs_hba *hba, - struct request_queue *q) -{ - keyslot_manager_destroy(hba->ksm); -} -EXPORT_SYMBOL_GPL(ufshcd_crypto_destroy_rq_keyslot_manager_spec); - -int ufshcd_prepare_lrbp_crypto_spec(struct ufs_hba *hba, - struct scsi_cmnd *cmd, - struct ufshcd_lrb *lrbp) -{ - struct bio_crypt_ctx *bc; - - if (!bio_crypt_should_process(cmd->request)) { - lrbp->crypto_enable = false; - return 0; - } - bc = cmd->request->bio->bi_crypt_context; - - if (WARN_ON(!ufshcd_is_crypto_enabled(hba))) { - /* - * Upper layer asked us to do inline encryption - * but that isn't enabled, so we fail this request. - */ - return -EINVAL; - } - if (!ufshcd_keyslot_valid(hba, bc->bc_keyslot)) - return -EINVAL; - - lrbp->crypto_enable = true; - lrbp->crypto_key_slot = bc->bc_keyslot; - lrbp->data_unit_num = bc->bc_dun[0]; - - return 0; -} -EXPORT_SYMBOL_GPL(ufshcd_prepare_lrbp_crypto_spec); - -/* Crypto Variant Ops Support */ - -void ufshcd_crypto_enable(struct ufs_hba *hba) -{ - if (hba->crypto_vops && hba->crypto_vops->enable) - return hba->crypto_vops->enable(hba); - - return ufshcd_crypto_enable_spec(hba); -} - -void ufshcd_crypto_disable(struct ufs_hba *hba) -{ - if (hba->crypto_vops && hba->crypto_vops->disable) - return hba->crypto_vops->disable(hba); - - return ufshcd_crypto_disable_spec(hba); -} - -int ufshcd_hba_init_crypto(struct ufs_hba *hba) -{ - if (hba->crypto_vops && hba->crypto_vops->hba_init_crypto) - return hba->crypto_vops->hba_init_crypto(hba, - &ufshcd_ksm_ops); - - return ufshcd_hba_init_crypto_spec(hba, &ufshcd_ksm_ops); -} - -void ufshcd_crypto_setup_rq_keyslot_manager(struct ufs_hba *hba, - struct request_queue *q) -{ - if (hba->crypto_vops && hba->crypto_vops->setup_rq_keyslot_manager) - return hba->crypto_vops->setup_rq_keyslot_manager(hba, q); - - return ufshcd_crypto_setup_rq_keyslot_manager_spec(hba, q); -} - -void ufshcd_crypto_destroy_rq_keyslot_manager(struct ufs_hba *hba, - struct request_queue *q) -{ - if (hba->crypto_vops && hba->crypto_vops->destroy_rq_keyslot_manager) - return hba->crypto_vops->destroy_rq_keyslot_manager(hba, q); - - return ufshcd_crypto_destroy_rq_keyslot_manager_spec(hba, q); -} - -int ufshcd_prepare_lrbp_crypto(struct ufs_hba *hba, - struct scsi_cmnd *cmd, - struct ufshcd_lrb *lrbp) -{ - if (hba->crypto_vops && hba->crypto_vops->prepare_lrbp_crypto) - return hba->crypto_vops->prepare_lrbp_crypto(hba, cmd, lrbp); - - return ufshcd_prepare_lrbp_crypto_spec(hba, cmd, lrbp); -} - -int ufshcd_complete_lrbp_crypto(struct ufs_hba *hba, - struct scsi_cmnd *cmd, - struct ufshcd_lrb *lrbp) -{ - if (hba->crypto_vops && hba->crypto_vops->complete_lrbp_crypto) - return hba->crypto_vops->complete_lrbp_crypto(hba, cmd, lrbp); - - return 0; -} - -void ufshcd_crypto_debug(struct ufs_hba *hba) -{ - if (hba->crypto_vops && hba->crypto_vops->debug) - hba->crypto_vops->debug(hba); -} - -int ufshcd_crypto_suspend(struct ufs_hba *hba, - enum ufs_pm_op pm_op) -{ - if (hba->crypto_vops && hba->crypto_vops->suspend) - return hba->crypto_vops->suspend(hba, pm_op); - - return 0; -} - -int ufshcd_crypto_resume(struct ufs_hba *hba, - enum ufs_pm_op pm_op) -{ - if (hba->crypto_vops && hba->crypto_vops->resume) - return hba->crypto_vops->resume(hba, pm_op); - - return 0; -} - -void ufshcd_crypto_set_vops(struct ufs_hba *hba, - struct ufs_hba_crypto_variant_ops *crypto_vops) -{ - hba->crypto_vops = crypto_vops; -} diff --git a/drivers/scsi/ufs/ufshcd-crypto.h b/drivers/scsi/ufs/ufshcd-crypto.h deleted file mode 100644 index 95f37c9f7672..000000000000 --- a/drivers/scsi/ufs/ufshcd-crypto.h +++ /dev/null @@ -1,167 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright 2019 Google LLC - */ - -#ifndef _UFSHCD_CRYPTO_H -#define _UFSHCD_CRYPTO_H - -#ifdef CONFIG_SCSI_UFS_CRYPTO -#include -#include "ufshcd.h" -#include "ufshci.h" - -static inline int ufshcd_num_keyslots(struct ufs_hba *hba) -{ - return hba->crypto_capabilities.config_count + 1; -} - -static inline bool ufshcd_keyslot_valid(struct ufs_hba *hba, unsigned int slot) -{ - /* - * The actual number of configurations supported is (CFGC+1), so slot - * numbers range from 0 to config_count inclusive. - */ - return slot < ufshcd_num_keyslots(hba); -} - -static inline bool ufshcd_hba_is_crypto_supported(struct ufs_hba *hba) -{ - return hba->crypto_capabilities.reg_val != 0; -} - -static inline bool ufshcd_is_crypto_enabled(struct ufs_hba *hba) -{ - return hba->caps & UFSHCD_CAP_CRYPTO; -} - -/* Functions implementing UFSHCI v2.1 specification behaviour */ -int ufshcd_crypto_cap_find(struct ufs_hba *hba, - enum blk_crypto_mode_num crypto_mode, - unsigned int data_unit_size); - -int ufshcd_prepare_lrbp_crypto_spec(struct ufs_hba *hba, - struct scsi_cmnd *cmd, - struct ufshcd_lrb *lrbp); - -void ufshcd_crypto_enable_spec(struct ufs_hba *hba); - -void ufshcd_crypto_disable_spec(struct ufs_hba *hba); - -struct keyslot_mgmt_ll_ops; -int ufshcd_hba_init_crypto_spec(struct ufs_hba *hba, - const struct keyslot_mgmt_ll_ops *ksm_ops); - -void ufshcd_crypto_setup_rq_keyslot_manager_spec(struct ufs_hba *hba, - struct request_queue *q); - -void ufshcd_crypto_destroy_rq_keyslot_manager_spec(struct ufs_hba *hba, - struct request_queue *q); - -static inline bool ufshcd_lrbp_crypto_enabled(struct ufshcd_lrb *lrbp) -{ - return lrbp->crypto_enable; -} - -/* Crypto Variant Ops Support */ -void ufshcd_crypto_enable(struct ufs_hba *hba); - -void ufshcd_crypto_disable(struct ufs_hba *hba); - -int ufshcd_hba_init_crypto(struct ufs_hba *hba); - -void ufshcd_crypto_setup_rq_keyslot_manager(struct ufs_hba *hba, - struct request_queue *q); - -void ufshcd_crypto_destroy_rq_keyslot_manager(struct ufs_hba *hba, - struct request_queue *q); - -int ufshcd_prepare_lrbp_crypto(struct ufs_hba *hba, - struct scsi_cmnd *cmd, - struct ufshcd_lrb *lrbp); - -int ufshcd_complete_lrbp_crypto(struct ufs_hba *hba, - struct scsi_cmnd *cmd, - struct ufshcd_lrb *lrbp); - -void ufshcd_crypto_debug(struct ufs_hba *hba); - -int ufshcd_crypto_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op); - -int ufshcd_crypto_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op); - -void ufshcd_crypto_set_vops(struct ufs_hba *hba, - struct ufs_hba_crypto_variant_ops *crypto_vops); - -#else /* CONFIG_SCSI_UFS_CRYPTO */ - -static inline bool ufshcd_keyslot_valid(struct ufs_hba *hba, - unsigned int slot) -{ - return false; -} - -static inline bool ufshcd_hba_is_crypto_supported(struct ufs_hba *hba) -{ - return false; -} - -static inline bool ufshcd_is_crypto_enabled(struct ufs_hba *hba) -{ - return false; -} - -static inline void ufshcd_crypto_enable(struct ufs_hba *hba) { } - -static inline void ufshcd_crypto_disable(struct ufs_hba *hba) { } - -static inline int ufshcd_hba_init_crypto(struct ufs_hba *hba) -{ - return 0; -} - -static inline void ufshcd_crypto_setup_rq_keyslot_manager(struct ufs_hba *hba, - struct request_queue *q) { } - -static inline void ufshcd_crypto_destroy_rq_keyslot_manager(struct ufs_hba *hba, - struct request_queue *q) { } - -static inline int ufshcd_prepare_lrbp_crypto(struct ufs_hba *hba, - struct scsi_cmnd *cmd, - struct ufshcd_lrb *lrbp) -{ - return 0; -} - -static inline bool ufshcd_lrbp_crypto_enabled(struct ufshcd_lrb *lrbp) -{ - return false; -} - -static inline int ufshcd_complete_lrbp_crypto(struct ufs_hba *hba, - struct scsi_cmnd *cmd, - struct ufshcd_lrb *lrbp) -{ - return 0; -} - -static inline void ufshcd_crypto_debug(struct ufs_hba *hba) { } - -static inline int ufshcd_crypto_suspend(struct ufs_hba *hba, - enum ufs_pm_op pm_op) -{ - return 0; -} - -static inline int ufshcd_crypto_resume(struct ufs_hba *hba, - enum ufs_pm_op pm_op) -{ - return 0; -} - -static inline void ufshcd_crypto_set_vops(struct ufs_hba *hba, - struct ufs_hba_crypto_variant_ops *crypto_vops) { } - -#endif /* CONFIG_SCSI_UFS_CRYPTO */ - -#endif /* _UFSHCD_CRYPTO_H */ diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 862542aa5912..ce40de334f11 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -44,7 +44,6 @@ #include "ufshcd.h" #include "ufs_quirks.h" #include "unipro.h" -#include "ufshcd-crypto.h" #define CREATE_TRACE_POINTS #include @@ -372,8 +371,6 @@ static void ufshcd_print_host_regs(struct ufs_hba *hba) if (hba->vops && hba->vops->dbg_register_dump) hba->vops->dbg_register_dump(hba); - - ufshcd_crypto_debug(hba); } static @@ -799,14 +796,7 @@ static void ufshcd_enable_run_stop_reg(struct ufs_hba *hba) */ static inline void ufshcd_hba_start(struct ufs_hba *hba) { - u32 val = CONTROLLER_ENABLE; - - if (ufshcd_hba_is_crypto_supported(hba)) { - ufshcd_crypto_enable(hba); - val |= CRYPTO_GENERAL_ENABLE; - } - - ufshcd_writel(hba, val, REG_CONTROLLER_ENABLE); + ufshcd_writel(hba, CONTROLLER_ENABLE, REG_CONTROLLER_ENABLE); } /** @@ -2090,23 +2080,9 @@ static void ufshcd_prepare_req_desc_hdr(struct ufshcd_lrb *lrbp, dword_0 |= UTP_REQ_DESC_INT_CMD; /* Transfer request descriptor header fields */ - if (ufshcd_lrbp_crypto_enabled(lrbp)) { -#if IS_ENABLED(CONFIG_SCSI_UFS_CRYPTO) - dword_0 |= UTP_REQ_DESC_CRYPTO_ENABLE_CMD; - dword_0 |= lrbp->crypto_key_slot; - req_desc->header.dword_1 = - cpu_to_le32(lower_32_bits(lrbp->data_unit_num)); - req_desc->header.dword_3 = - cpu_to_le32(upper_32_bits(lrbp->data_unit_num)); -#endif /* CONFIG_SCSI_UFS_CRYPTO */ - } else { - /* dword_1 and dword_3 are reserved, hence they are set to 0 */ - req_desc->header.dword_1 = 0; - req_desc->header.dword_3 = 0; - } - req_desc->header.dword_0 = cpu_to_le32(dword_0); - + /* dword_1 is reserved, hence it is set to 0 */ + req_desc->header.dword_1 = 0; /* * assigning invalid value for command status. Controller * updates OCS on command completion, with the command @@ -2114,6 +2090,8 @@ static void ufshcd_prepare_req_desc_hdr(struct ufshcd_lrb *lrbp, */ req_desc->header.dword_2 = cpu_to_le32(OCS_INVALID_COMMAND_STATUS); + /* dword_3 is reserved, hence it is set to 0 */ + req_desc->header.dword_3 = 0; req_desc->prd_table_length = 0; } @@ -2376,13 +2354,6 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) lrbp->task_tag = tag; lrbp->lun = ufshcd_scsi_to_upiu_lun(cmd->device->lun); lrbp->intr_cmd = !ufshcd_is_intr_aggr_allowed(hba) ? true : false; - - err = ufshcd_prepare_lrbp_crypto(hba, cmd, lrbp); - if (err) { - lrbp->cmd = NULL; - clear_bit_unlock(tag, &hba->lrb_in_use); - goto out; - } lrbp->req_abort_skip = false; ufshcd_comp_scsi_upiu(hba, lrbp); @@ -2416,9 +2387,6 @@ static int ufshcd_compose_dev_cmd(struct ufs_hba *hba, lrbp->task_tag = tag; lrbp->lun = 0; /* device management cmd is not specific to any LUN */ lrbp->intr_cmd = true; /* No interrupt aggregation */ -#if IS_ENABLED(CONFIG_SCSI_UFS_CRYPTO) - lrbp->crypto_enable = false; /* No crypto operations */ -#endif hba->dev_cmd.type = cmd_type; return ufshcd_comp_devman_upiu(hba, lrbp); @@ -4056,8 +4024,6 @@ static inline void ufshcd_hba_stop(struct ufs_hba *hba, bool can_sleep) { int err; - ufshcd_crypto_disable(hba); - ufshcd_writel(hba, CONTROLLER_DISABLE, REG_CONTROLLER_ENABLE); err = ufshcd_wait_for_register(hba, REG_CONTROLLER_ENABLE, CONTROLLER_ENABLE, CONTROLLER_DISABLE, @@ -4425,14 +4391,11 @@ static int ufshcd_change_queue_depth(struct scsi_device *sdev, int depth) */ static int ufshcd_slave_configure(struct scsi_device *sdev) { - struct ufs_hba *hba = shost_priv(sdev->host); struct request_queue *q = sdev->request_queue; blk_queue_update_dma_pad(q, PRDT_DATA_BYTE_COUNT_PAD - 1); blk_queue_max_segment_size(q, PRDT_DATA_BYTE_COUNT_MAX); - ufshcd_crypto_setup_rq_keyslot_manager(hba, q); - return 0; } @@ -4443,7 +4406,6 @@ static int ufshcd_slave_configure(struct scsi_device *sdev) static void ufshcd_slave_destroy(struct scsi_device *sdev) { struct ufs_hba *hba; - struct request_queue *q = sdev->request_queue; hba = shost_priv(sdev->host); /* Drop the reference as it won't be needed anymore */ @@ -4454,8 +4416,6 @@ static void ufshcd_slave_destroy(struct scsi_device *sdev) hba->sdev_ufs_device = NULL; spin_unlock_irqrestore(hba->host->host_lock, flags); } - - ufshcd_crypto_destroy_rq_keyslot_manager(hba, q); } /** @@ -4610,8 +4570,6 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) case OCS_MISMATCH_RESP_UPIU_SIZE: case OCS_PEER_COMM_FAILURE: case OCS_FATAL_ERROR: - case OCS_INVALID_CRYPTO_CONFIG: - case OCS_GENERAL_CRYPTO_ERROR: default: result |= DID_ERROR << 16; dev_err(hba->dev, @@ -4667,7 +4625,6 @@ static void __ufshcd_transfer_req_compl(struct ufs_hba *hba, result = ufshcd_transfer_rsp_status(hba, lrbp); scsi_dma_unmap(cmd); cmd->result = result; - ufshcd_complete_lrbp_crypto(hba, cmd, lrbp); /* Mark completed command as NULL in LRB */ lrbp->cmd = NULL; clear_bit_unlock(index, &hba->lrb_in_use); @@ -7310,10 +7267,6 @@ static int ufshcd_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op) req_link_state = UIC_LINK_OFF_STATE; } - ret = ufshcd_crypto_suspend(hba, pm_op); - if (ret) - goto out; - /* * If we can't transition into any of the low power modes * just gate the clocks. @@ -7417,7 +7370,6 @@ enable_gating: ufshcd_resume_clkscaling(hba); hba->clk_gating.is_suspended = false; ufshcd_release(hba); - ufshcd_crypto_resume(hba, pm_op); out: hba->pm_op_in_progress = 0; return ret; @@ -7437,11 +7389,9 @@ static int ufshcd_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op) { int ret; enum uic_link_state old_link_state; - enum ufs_dev_pwr_mode old_pwr_mode; hba->pm_op_in_progress = 1; old_link_state = hba->uic_link_state; - old_pwr_mode = hba->curr_dev_pwr_mode; ufshcd_hba_vreg_set_hpm(hba); /* Make sure clocks are enabled before accessing controller */ @@ -7489,10 +7439,6 @@ static int ufshcd_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op) goto set_old_link_state; } - ret = ufshcd_crypto_resume(hba, pm_op); - if (ret) - goto set_old_dev_pwr_mode; - if (ufshcd_keep_autobkops_enabled_except_suspend(hba)) ufshcd_enable_auto_bkops(hba); else @@ -7511,9 +7457,6 @@ static int ufshcd_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op) ufshcd_release(hba); goto out; -set_old_dev_pwr_mode: - if (old_pwr_mode != hba->curr_dev_pwr_mode) - ufshcd_set_dev_pwr_mode(hba, old_pwr_mode); set_old_link_state: ufshcd_link_state_transition(hba, old_link_state, 0); vendor_suspend: @@ -8052,13 +7995,6 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) goto exit_gating; } - /* Init crypto */ - err = ufshcd_hba_init_crypto(hba); - if (err) { - dev_err(hba->dev, "crypto setup failed\n"); - goto out_remove_scsi_host; - } - /* Host controller enable */ err = ufshcd_hba_enable(hba); if (err) { diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 38381217762c..cdc8bd05f7df 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -166,9 +166,6 @@ struct ufs_pm_lvl_states { * @lun: LUN of the command * @intr_cmd: Interrupt command (doesn't participate in interrupt aggregation) * @issue_time_stamp: time stamp for debug purposes - * @crypto_enable: whether or not the request needs inline crypto operations - * @crypto_key_slot: the key slot to use for inline crypto - * @data_unit_num: the data unit number for the first block for inline crypto * @req_abort_skip: skip request abort task flag */ struct ufshcd_lrb { @@ -192,11 +189,6 @@ struct ufshcd_lrb { u8 lun; /* UPIU LUN id field is only 8-bit wide */ bool intr_cmd; ktime_t issue_time_stamp; -#if IS_ENABLED(CONFIG_SCSI_UFS_CRYPTO) - bool crypto_enable; - u8 crypto_key_slot; - u64 data_unit_num; -#endif /* CONFIG_SCSI_UFS_CRYPTO */ bool req_abort_skip; }; @@ -277,8 +269,6 @@ struct ufs_pwr_mode_info { struct ufs_pa_layer_attr info; }; -union ufs_crypto_cfg_entry; - /** * struct ufs_hba_variant_ops - variant specific callbacks * @name: variant name @@ -305,7 +295,6 @@ union ufs_crypto_cfg_entry; * @resume: called during host controller PM callback * @dbg_register_dump: used to dump controller debug information * @phy_initialization: used to initialize phys - * @program_key: program an inline encryption key into a keyslot */ struct ufs_hba_variant_ops { const char *name; @@ -334,30 +323,6 @@ struct ufs_hba_variant_ops { int (*resume)(struct ufs_hba *, enum ufs_pm_op); void (*dbg_register_dump)(struct ufs_hba *hba); int (*phy_initialization)(struct ufs_hba *); - int (*program_key)(struct ufs_hba *hba, - const union ufs_crypto_cfg_entry *cfg, int slot); -}; - -struct keyslot_mgmt_ll_ops; -struct ufs_hba_crypto_variant_ops { - void (*setup_rq_keyslot_manager)(struct ufs_hba *hba, - struct request_queue *q); - void (*destroy_rq_keyslot_manager)(struct ufs_hba *hba, - struct request_queue *q); - int (*hba_init_crypto)(struct ufs_hba *hba, - const struct keyslot_mgmt_ll_ops *ksm_ops); - void (*enable)(struct ufs_hba *hba); - void (*disable)(struct ufs_hba *hba); - int (*suspend)(struct ufs_hba *hba, enum ufs_pm_op pm_op); - int (*resume)(struct ufs_hba *hba, enum ufs_pm_op pm_op); - int (*debug)(struct ufs_hba *hba); - int (*prepare_lrbp_crypto)(struct ufs_hba *hba, - struct scsi_cmnd *cmd, - struct ufshcd_lrb *lrbp); - int (*complete_lrbp_crypto)(struct ufs_hba *hba, - struct scsi_cmnd *cmd, - struct ufshcd_lrb *lrbp); - void *priv; }; /* clock gating state */ @@ -531,10 +496,6 @@ struct ufs_stats { * @urgent_bkops_lvl: keeps track of urgent bkops level for device * @is_urgent_bkops_lvl_checked: keeps track if the urgent bkops level for * device is known or not. - * @crypto_capabilities: Content of crypto capabilities register (0x100) - * @crypto_cap_array: Array of crypto capabilities - * @crypto_cfg_register: Start of the crypto cfg array - * @ksm: the keyslot manager tied to this hba */ struct ufs_hba { void __iomem *mmio_base; @@ -579,7 +540,6 @@ struct ufs_hba { u32 ufs_version; struct ufs_hba_variant_ops *vops; void *priv; - const struct ufs_hba_crypto_variant_ops *crypto_vops; unsigned int irq; bool is_irq_enabled; @@ -629,12 +589,6 @@ struct ufs_hba { */ #define UFSHCD_QUIRK_PRDT_BYTE_GRAN UFS_BIT(7) - /* - * This quirk needs to be enabled if the host controller advertises - * inline encryption support but it doesn't work correctly. - */ - #define UFSHCD_QUIRK_BROKEN_CRYPTO UFS_BIT(11) - unsigned int quirks; /* Deviations from standard UFSHCI spec. */ /* Device deviations from standard UFS device spec. */ @@ -713,11 +667,6 @@ struct ufs_hba { * the performance of ongoing read/write operations. */ #define UFSHCD_CAP_KEEP_AUTO_BKOPS_ENABLED_EXCEPT_SUSPEND (1 << 5) - /* - * This capability allows the host controller driver to use the - * inline crypto engine, if it is present - */ -#define UFSHCD_CAP_CRYPTO (1 << 7) struct devfreq *devfreq; struct ufs_clk_scaling clk_scaling; @@ -728,14 +677,6 @@ struct ufs_hba { struct rw_semaphore clk_scaling_lock; struct ufs_desc_size desc_size; - -#ifdef CONFIG_SCSI_UFS_CRYPTO - /* crypto */ - union ufs_crypto_capabilities crypto_capabilities; - union ufs_crypto_cap_entry *crypto_cap_array; - u32 crypto_cfg_register; - struct keyslot_manager *ksm; -#endif /* CONFIG_SCSI_UFS_CRYPTO */ }; /* Returns true if clocks can be gated. Otherwise false */ diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h index 97006b324ee7..f60145d4a66e 100644 --- a/drivers/scsi/ufs/ufshci.h +++ b/drivers/scsi/ufs/ufshci.h @@ -89,7 +89,6 @@ enum { MASK_64_ADDRESSING_SUPPORT = 0x01000000, MASK_OUT_OF_ORDER_DATA_DELIVERY_SUPPORT = 0x02000000, MASK_UIC_DME_TEST_MODE_SUPPORT = 0x04000000, - MASK_CRYPTO_SUPPORT = 0x10000000, }; #define UFS_MASK(mask, offset) ((mask) << (offset)) @@ -136,7 +135,6 @@ enum { #define DEVICE_FATAL_ERROR UFS_BIT(11) #define CONTROLLER_FATAL_ERROR UFS_BIT(16) #define SYSTEM_BUS_FATAL_ERROR UFS_BIT(17) -#define CRYPTO_ENGINE_FATAL_ERROR UFS_BIT(18) #define UFSHCD_UIC_PWR_MASK (UIC_HIBERNATE_ENTER |\ UIC_HIBERNATE_EXIT |\ @@ -147,13 +145,11 @@ enum { #define UFSHCD_ERROR_MASK (UIC_ERROR |\ DEVICE_FATAL_ERROR |\ CONTROLLER_FATAL_ERROR |\ - SYSTEM_BUS_FATAL_ERROR |\ - CRYPTO_ENGINE_FATAL_ERROR) + SYSTEM_BUS_FATAL_ERROR) #define INT_FATAL_ERRORS (DEVICE_FATAL_ERROR |\ CONTROLLER_FATAL_ERROR |\ - SYSTEM_BUS_FATAL_ERROR |\ - CRYPTO_ENGINE_FATAL_ERROR) + SYSTEM_BUS_FATAL_ERROR) /* HCS - Host Controller Status 30h */ #define DEVICE_PRESENT UFS_BIT(0) @@ -297,61 +293,6 @@ enum { INTERRUPT_MASK_ALL_VER_21 = 0x71FFF, }; -/* CCAP - Crypto Capability 100h */ -union ufs_crypto_capabilities { - __le32 reg_val; - struct { - u8 num_crypto_cap; - u8 config_count; - u8 reserved; - u8 config_array_ptr; - }; -}; - -enum ufs_crypto_key_size { - UFS_CRYPTO_KEY_SIZE_INVALID = 0x0, - UFS_CRYPTO_KEY_SIZE_128 = 0x1, - UFS_CRYPTO_KEY_SIZE_192 = 0x2, - UFS_CRYPTO_KEY_SIZE_256 = 0x3, - UFS_CRYPTO_KEY_SIZE_512 = 0x4, -}; - -enum ufs_crypto_alg { - UFS_CRYPTO_ALG_AES_XTS = 0x0, - UFS_CRYPTO_ALG_BITLOCKER_AES_CBC = 0x1, - UFS_CRYPTO_ALG_AES_ECB = 0x2, - UFS_CRYPTO_ALG_ESSIV_AES_CBC = 0x3, -}; - -/* x-CRYPTOCAP - Crypto Capability X */ -union ufs_crypto_cap_entry { - __le32 reg_val; - struct { - u8 algorithm_id; - u8 sdus_mask; /* Supported data unit size mask */ - u8 key_size; - u8 reserved; - }; -}; - -#define UFS_CRYPTO_CONFIGURATION_ENABLE (1 << 7) -#define UFS_CRYPTO_KEY_MAX_SIZE 64 -/* x-CRYPTOCFG - Crypto Configuration X */ -union ufs_crypto_cfg_entry { - __le32 reg_val[32]; - struct { - u8 crypto_key[UFS_CRYPTO_KEY_MAX_SIZE]; - u8 data_unit_size; - u8 crypto_cap_idx; - u8 reserved_1; - u8 config_enable; - u8 reserved_multi_host; - u8 reserved_2; - u8 vsb[2]; - u8 reserved_3[56]; - }; -}; - /* * Request Descriptor Definitions */ @@ -373,7 +314,6 @@ enum { UTP_NATIVE_UFS_COMMAND = 0x10000000, UTP_DEVICE_MANAGEMENT_FUNCTION = 0x20000000, UTP_REQ_DESC_INT_CMD = 0x01000000, - UTP_REQ_DESC_CRYPTO_ENABLE_CMD = 0x00800000, }; /* UTP Transfer Request Data Direction (DD) */ @@ -393,9 +333,6 @@ enum { OCS_PEER_COMM_FAILURE = 0x5, OCS_ABORTED = 0x6, OCS_FATAL_ERROR = 0x7, - OCS_DEVICE_FATAL_ERROR = 0x8, - OCS_INVALID_CRYPTO_CONFIG = 0x9, - OCS_GENERAL_CRYPTO_ERROR = 0xA, OCS_INVALID_COMMAND_STATUS = 0x0F, MASK_OCS = 0x0F, }; diff --git a/fs/buffer.c b/fs/buffer.c index fff033d48f45..bdca7b10e239 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -46,7 +46,6 @@ #include #include #include -#include static int fsync_buffers_list(spinlock_t *lock, struct list_head *list); static int submit_bh_wbc(int op, int op_flags, struct buffer_head *bh, @@ -3126,8 +3125,6 @@ static int submit_bh_wbc(int op, int op_flags, struct buffer_head *bh, */ bio = bio_alloc(GFP_NOIO, 1); - fscrypt_set_bio_crypt_ctx_bh(bio, bh, GFP_NOIO); - if (wbc) { wbc_init_bio(wbc, bio); wbc_account_io(wbc, bh->b_page, bh->b_size); diff --git a/fs/crypto/Kconfig b/fs/crypto/Kconfig index 0701bb90f99c..4bc66f2c571e 100644 --- a/fs/crypto/Kconfig +++ b/fs/crypto/Kconfig @@ -15,9 +15,3 @@ config FS_ENCRYPTION efficient since it avoids caching the encrypted and decrypted pages in the page cache. Currently Ext4, F2FS and UBIFS make use of this feature. - -config FS_ENCRYPTION_INLINE_CRYPT - bool "Enable fscrypt to use inline crypto" - depends on FS_ENCRYPTION && BLK_INLINE_ENCRYPTION - help - Enable fscrypt to use inline encryption hardware if available. diff --git a/fs/crypto/Makefile b/fs/crypto/Makefile index 1a6b0774f3ff..0a78543f6cec 100644 --- a/fs/crypto/Makefile +++ b/fs/crypto/Makefile @@ -10,4 +10,3 @@ fscrypto-y := crypto.o \ policy.o fscrypto-$(CONFIG_BLOCK) += bio.o -fscrypto-$(CONFIG_FS_ENCRYPTION_INLINE_CRYPT) += inline_crypt.o diff --git a/fs/crypto/bio.c b/fs/crypto/bio.c index f62375d39b0f..4a7f4d78ef90 100644 --- a/fs/crypto/bio.c +++ b/fs/crypto/bio.c @@ -46,35 +46,26 @@ int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk, { const unsigned int blockbits = inode->i_blkbits; const unsigned int blocksize = 1 << blockbits; - const bool inlinecrypt = fscrypt_inode_uses_inline_crypto(inode); struct page *ciphertext_page; struct bio *bio; int ret, err = 0; - if (inlinecrypt) { - ciphertext_page = ZERO_PAGE(0); - } else { - ciphertext_page = fscrypt_alloc_bounce_page(GFP_NOWAIT); - if (!ciphertext_page) - return -ENOMEM; - } + ciphertext_page = fscrypt_alloc_bounce_page(GFP_NOWAIT); + if (!ciphertext_page) + return -ENOMEM; while (len--) { - if (!inlinecrypt) { - err = fscrypt_crypt_block(inode, FS_ENCRYPT, lblk, - ZERO_PAGE(0), ciphertext_page, - blocksize, 0, GFP_NOFS); - if (err) - goto errout; - } + err = fscrypt_crypt_block(inode, FS_ENCRYPT, lblk, + ZERO_PAGE(0), ciphertext_page, + blocksize, 0, GFP_NOFS); + if (err) + goto errout; bio = bio_alloc(GFP_NOWAIT, 1); if (!bio) { err = -ENOMEM; goto errout; } - fscrypt_set_bio_crypt_ctx(bio, inode, lblk, GFP_NOIO); - bio_set_dev(bio, inode->i_sb->s_bdev); bio->bi_iter.bi_sector = pblk << (blockbits - 9); bio_set_op_attrs(bio, REQ_OP_WRITE, 0); @@ -96,8 +87,7 @@ int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk, } err = 0; errout: - if (!inlinecrypt) - fscrypt_free_bounce_page(ciphertext_page); + fscrypt_free_bounce_page(ciphertext_page); return err; } EXPORT_SYMBOL(fscrypt_zeroout_range); diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c index 41b4fe15b4b6..6e6f39ea18a7 100644 --- a/fs/crypto/crypto.c +++ b/fs/crypto/crypto.c @@ -96,7 +96,7 @@ int fscrypt_crypt_block(const struct inode *inode, fscrypt_direction_t rw, DECLARE_CRYPTO_WAIT(wait); struct scatterlist dst, src; struct fscrypt_info *ci = inode->i_crypt_info; - struct crypto_skcipher *tfm = ci->ci_key.tfm; + struct crypto_skcipher *tfm = ci->ci_ctfm; int res = 0; if (WARN_ON_ONCE(len <= 0)) diff --git a/fs/crypto/fname.c b/fs/crypto/fname.c index 3aafddaab703..3da3707c10e3 100644 --- a/fs/crypto/fname.c +++ b/fs/crypto/fname.c @@ -40,7 +40,7 @@ int fname_encrypt(struct inode *inode, const struct qstr *iname, struct skcipher_request *req = NULL; DECLARE_CRYPTO_WAIT(wait); struct fscrypt_info *ci = inode->i_crypt_info; - struct crypto_skcipher *tfm = ci->ci_key.tfm; + struct crypto_skcipher *tfm = ci->ci_ctfm; union fscrypt_iv iv; struct scatterlist sg; int res; @@ -93,7 +93,7 @@ static int fname_decrypt(struct inode *inode, DECLARE_CRYPTO_WAIT(wait); struct scatterlist src_sg, dst_sg; struct fscrypt_info *ci = inode->i_crypt_info; - struct crypto_skcipher *tfm = ci->ci_key.tfm; + struct crypto_skcipher *tfm = ci->ci_ctfm; union fscrypt_iv iv; int res; diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index 5d7b20fead86..130b50e5a011 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -13,14 +13,12 @@ #include #include -#include #define CONST_STRLEN(str) (sizeof(str) - 1) #define FS_KEY_DERIVATION_NONCE_SIZE 16 #define FSCRYPT_MIN_KEY_SIZE 16 -#define FSCRYPT_MAX_HW_WRAPPED_KEY_SIZE 128 #define FSCRYPT_CONTEXT_V1 1 #define FSCRYPT_CONTEXT_V2 2 @@ -153,20 +151,6 @@ struct fscrypt_symlink_data { char encrypted_path[1]; } __packed; -/** - * struct fscrypt_prepared_key - a key prepared for actual encryption/decryption - * @tfm: crypto API transform object - * @blk_key: key for blk-crypto - * - * Normally only one of the fields will be non-NULL. - */ -struct fscrypt_prepared_key { - struct crypto_skcipher *tfm; -#ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT - struct fscrypt_blk_crypto_key *blk_key; -#endif -}; - /* * fscrypt_info - the "encryption key" for an inode * @@ -176,20 +160,12 @@ struct fscrypt_prepared_key { */ struct fscrypt_info { - /* The key in a form prepared for actual encryption/decryption */ - struct fscrypt_prepared_key ci_key; + /* The actual crypto transform used for encryption and decryption */ + struct crypto_skcipher *ci_ctfm; /* True if the key should be freed when this fscrypt_info is freed */ bool ci_owns_key; -#ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT - /* - * True if this inode will use inline encryption (blk-crypto) instead of - * the traditional filesystem-layer encryption. - */ - bool ci_inlinecrypt; -#endif - /* * Encryption mode used for this inode. It corresponds to either the * contents or filenames encryption mode, depending on the inode type. @@ -214,7 +190,7 @@ struct fscrypt_info { /* * If non-NULL, then encryption is done using the master key directly - * and ci_key will equal ci_direct_key->dk_key. + * and ci_ctfm will equal ci_direct_key->dk_ctfm. */ struct fscrypt_direct_key *ci_direct_key; @@ -278,7 +254,6 @@ union fscrypt_iv { u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE]; }; u8 raw[FSCRYPT_MAX_IV_SIZE]; - __le64 dun[FSCRYPT_MAX_IV_SIZE / sizeof(__le64)]; }; void fscrypt_generate_iv(union fscrypt_iv *iv, u64 lblk_num, @@ -318,94 +293,6 @@ extern int fscrypt_hkdf_expand(struct fscrypt_hkdf *hkdf, u8 context, extern void fscrypt_destroy_hkdf(struct fscrypt_hkdf *hkdf); -/* inline_crypt.c */ -#ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT -extern void fscrypt_select_encryption_impl(struct fscrypt_info *ci); - -static inline bool -fscrypt_using_inline_encryption(const struct fscrypt_info *ci) -{ - return ci->ci_inlinecrypt; -} - -extern int fscrypt_prepare_inline_crypt_key( - struct fscrypt_prepared_key *prep_key, - const u8 *raw_key, - unsigned int raw_key_size, - const struct fscrypt_info *ci); - -extern void fscrypt_destroy_inline_crypt_key( - struct fscrypt_prepared_key *prep_key); - -extern int fscrypt_derive_raw_secret(struct super_block *sb, - const u8 *wrapped_key, - unsigned int wrapped_key_size, - u8 *raw_secret, - unsigned int raw_secret_size); - -/* - * Check whether the crypto transform or blk-crypto key has been allocated in - * @prep_key, depending on which encryption implementation the file will use. - */ -static inline bool -fscrypt_is_key_prepared(struct fscrypt_prepared_key *prep_key, - const struct fscrypt_info *ci) -{ - /* - * The READ_ONCE() here pairs with the smp_store_release() in - * fscrypt_prepare_key(). (This only matters for the per-mode keys, - * which are shared by multiple inodes.) - */ - if (fscrypt_using_inline_encryption(ci)) - return READ_ONCE(prep_key->blk_key) != NULL; - return READ_ONCE(prep_key->tfm) != NULL; -} - -#else /* CONFIG_FS_ENCRYPTION_INLINE_CRYPT */ - -static inline void fscrypt_select_encryption_impl(struct fscrypt_info *ci) -{ -} - -static inline bool fscrypt_using_inline_encryption( - const struct fscrypt_info *ci) -{ - return false; -} - -static inline int -fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key, - const u8 *raw_key, unsigned int raw_key_size, - const struct fscrypt_info *ci) -{ - WARN_ON(1); - return -EOPNOTSUPP; -} - -static inline void -fscrypt_destroy_inline_crypt_key(struct fscrypt_prepared_key *prep_key) -{ -} - -static inline int fscrypt_derive_raw_secret(struct super_block *sb, - const u8 *wrapped_key, - unsigned int wrapped_key_size, - u8 *raw_secret, - unsigned int raw_secret_size) -{ - fscrypt_warn(NULL, - "kernel built without support for hardware-wrapped keys"); - return -EOPNOTSUPP; -} - -static inline bool -fscrypt_is_key_prepared(struct fscrypt_prepared_key *prep_key, - const struct fscrypt_info *ci) -{ - return READ_ONCE(prep_key->tfm) != NULL; -} -#endif /* !CONFIG_FS_ENCRYPTION_INLINE_CRYPT */ - /* keyring.c */ /* @@ -422,15 +309,8 @@ struct fscrypt_master_key_secret { /* Size of the raw key in bytes. Set even if ->raw isn't set. */ u32 size; - /* True if the key in ->raw is a hardware-wrapped key. */ - bool is_hw_wrapped; - - /* - * For v1 policy keys: the raw key. Wiped for v2 policy keys, unless - * ->is_hw_wrapped is true, in which case this contains the wrapped key - * rather than the key with which 'hkdf' was keyed. - */ - u8 raw[FSCRYPT_MAX_HW_WRAPPED_KEY_SIZE]; + /* For v1 policy keys: the raw key. Wiped for v2 policy keys. */ + u8 raw[FSCRYPT_MAX_KEY_SIZE]; } __randomize_layout; @@ -502,11 +382,14 @@ struct fscrypt_master_key { struct list_head mk_decrypted_inodes; spinlock_t mk_decrypted_inodes_lock; - /* Per-mode keys for DIRECT_KEY policies, allocated on-demand */ - struct fscrypt_prepared_key mk_direct_keys[__FSCRYPT_MODE_MAX + 1]; + /* Crypto API transforms for DIRECT_KEY policies, allocated on-demand */ + struct crypto_skcipher *mk_direct_tfms[__FSCRYPT_MODE_MAX + 1]; - /* Per-mode keys for IV_INO_LBLK_64 policies, allocated on-demand */ - struct fscrypt_prepared_key mk_iv_ino_lblk_64_keys[__FSCRYPT_MODE_MAX + 1]; + /* + * Crypto API transforms for filesystem-layer implementation of + * IV_INO_LBLK_64 policies, allocated on-demand. + */ + struct crypto_skcipher *mk_iv_ino_lblk_64_tfms[__FSCRYPT_MODE_MAX + 1]; } __randomize_layout; @@ -563,22 +446,17 @@ struct fscrypt_mode { int keysize; int ivsize; int logged_impl_name; - enum blk_crypto_mode_num blk_crypto_mode; }; -extern struct fscrypt_mode fscrypt_modes[]; - static inline bool fscrypt_mode_supports_direct_key(const struct fscrypt_mode *mode) { return mode->ivsize >= offsetofend(union fscrypt_iv, nonce); } -extern int fscrypt_prepare_key(struct fscrypt_prepared_key *prep_key, - const u8 *raw_key, unsigned int raw_key_size, - const struct fscrypt_info *ci); - -extern void fscrypt_destroy_prepared_key(struct fscrypt_prepared_key *prep_key); +extern struct crypto_skcipher * +fscrypt_allocate_skcipher(struct fscrypt_mode *mode, const u8 *raw_key, + const struct inode *inode); extern int fscrypt_set_derived_key(struct fscrypt_info *ci, const u8 *derived_key); diff --git a/fs/crypto/inline_crypt.c b/fs/crypto/inline_crypt.c deleted file mode 100644 index 92c471d3db73..000000000000 --- a/fs/crypto/inline_crypt.c +++ /dev/null @@ -1,353 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Inline encryption support for fscrypt - * - * Copyright 2019 Google LLC - */ - -/* - * With "inline encryption", the block layer handles the decryption/encryption - * as part of the bio, instead of the filesystem doing the crypto itself via - * crypto API. See Documentation/block/inline-encryption.rst. fscrypt still - * provides the key and IV to use. - */ - -#include -#include -#include -#include -#include - -#include "fscrypt_private.h" - -struct fscrypt_blk_crypto_key { - struct blk_crypto_key base; - int num_devs; - struct request_queue *devs[]; -}; - -/* Enable inline encryption for this file if supported. */ -void fscrypt_select_encryption_impl(struct fscrypt_info *ci) -{ - const struct inode *inode = ci->ci_inode; - struct super_block *sb = inode->i_sb; - - /* The file must need contents encryption, not filenames encryption */ - if (!S_ISREG(inode->i_mode)) - return; - - /* blk-crypto must implement the needed encryption algorithm */ - if (ci->ci_mode->blk_crypto_mode == BLK_ENCRYPTION_MODE_INVALID) - return; - - /* The filesystem must be mounted with -o inlinecrypt */ - if (!sb->s_cop->inline_crypt_enabled || - !sb->s_cop->inline_crypt_enabled(sb)) - return; - - ci->ci_inlinecrypt = true; -} - -int fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key, - const u8 *raw_key, - unsigned int raw_key_size, - const struct fscrypt_info *ci) -{ - const struct inode *inode = ci->ci_inode; - struct super_block *sb = inode->i_sb; - enum blk_crypto_mode_num crypto_mode = ci->ci_mode->blk_crypto_mode; - int num_devs = 1; - int queue_refs = 0; - struct fscrypt_blk_crypto_key *blk_key; - int err; - int i; - - if (sb->s_cop->get_num_devices) - num_devs = sb->s_cop->get_num_devices(sb); - if (WARN_ON(num_devs < 1)) - return -EINVAL; - - blk_key = kzalloc(struct_size(blk_key, devs, num_devs), GFP_NOFS); - if (!blk_key) - return -ENOMEM; - - blk_key->num_devs = num_devs; - if (num_devs == 1) - blk_key->devs[0] = bdev_get_queue(sb->s_bdev); - else - sb->s_cop->get_devices(sb, blk_key->devs); - - BUILD_BUG_ON(FSCRYPT_MAX_HW_WRAPPED_KEY_SIZE > - BLK_CRYPTO_MAX_WRAPPED_KEY_SIZE); - - err = blk_crypto_init_key(&blk_key->base, raw_key, raw_key_size, - crypto_mode, sb->s_blocksize); - if (err) { - fscrypt_err(inode, "error %d initializing blk-crypto key", err); - goto fail; - } - - /* - * We have to start using blk-crypto on all the filesystem's devices. - * We also have to save all the request_queue's for later so that the - * key can be evicted from them. This is needed because some keys - * aren't destroyed until after the filesystem was already unmounted - * (namely, the per-mode keys in struct fscrypt_master_key). - */ - for (i = 0; i < num_devs; i++) { - if (!blk_get_queue(blk_key->devs[i])) { - fscrypt_err(inode, "couldn't get request_queue"); - err = -EAGAIN; - goto fail; - } - queue_refs++; - - err = blk_crypto_start_using_mode(crypto_mode, sb->s_blocksize, - blk_key->devs[i]); - if (err) { - fscrypt_err(inode, - "error %d starting to use blk-crypto", err); - goto fail; - } - } - /* - * Pairs with READ_ONCE() in fscrypt_is_key_prepared(). (Only matters - * for the per-mode keys, which are shared by multiple inodes.) - */ - smp_store_release(&prep_key->blk_key, blk_key); - return 0; - -fail: - for (i = 0; i < queue_refs; i++) - blk_put_queue(blk_key->devs[i]); - kzfree(blk_key); - return err; -} - -void fscrypt_destroy_inline_crypt_key(struct fscrypt_prepared_key *prep_key) -{ - struct fscrypt_blk_crypto_key *blk_key = prep_key->blk_key; - int i; - - if (blk_key) { - for (i = 0; i < blk_key->num_devs; i++) { - blk_crypto_evict_key(blk_key->devs[i], &blk_key->base); - blk_put_queue(blk_key->devs[i]); - } - kzfree(blk_key); - } -} - -int fscrypt_derive_raw_secret(struct super_block *sb, - const u8 *wrapped_key, - unsigned int wrapped_key_size, - u8 *raw_secret, unsigned int raw_secret_size) -{ - struct request_queue *q; - - q = sb->s_bdev->bd_queue; - if (!q->ksm) - return -EOPNOTSUPP; - - return keyslot_manager_derive_raw_secret(q->ksm, - wrapped_key, wrapped_key_size, - raw_secret, raw_secret_size); -} - -/** - * fscrypt_inode_uses_inline_crypto - test whether an inode uses inline - * encryption - * @inode: an inode - * - * Return: true if the inode requires file contents encryption and if the - * encryption should be done in the block layer via blk-crypto rather - * than in the filesystem layer. - */ -bool fscrypt_inode_uses_inline_crypto(const struct inode *inode) -{ - return IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode) && - inode->i_crypt_info->ci_inlinecrypt; -} -EXPORT_SYMBOL_GPL(fscrypt_inode_uses_inline_crypto); - -/** - * fscrypt_inode_uses_fs_layer_crypto - test whether an inode uses fs-layer - * encryption - * @inode: an inode - * - * Return: true if the inode requires file contents encryption and if the - * encryption should be done in the filesystem layer rather than in the - * block layer via blk-crypto. - */ -bool fscrypt_inode_uses_fs_layer_crypto(const struct inode *inode) -{ - return IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode) && - !inode->i_crypt_info->ci_inlinecrypt; -} -EXPORT_SYMBOL_GPL(fscrypt_inode_uses_fs_layer_crypto); - -static void fscrypt_generate_dun(const struct fscrypt_info *ci, u64 lblk_num, - u64 dun[BLK_CRYPTO_DUN_ARRAY_SIZE]) -{ - union fscrypt_iv iv; - int i; - - fscrypt_generate_iv(&iv, lblk_num, ci); - - BUILD_BUG_ON(FSCRYPT_MAX_IV_SIZE > BLK_CRYPTO_MAX_IV_SIZE); - memset(dun, 0, BLK_CRYPTO_MAX_IV_SIZE); - for (i = 0; i < ci->ci_mode->ivsize/sizeof(dun[0]); i++) - dun[i] = le64_to_cpu(iv.dun[i]); -} - -/** - * fscrypt_set_bio_crypt_ctx - prepare a file contents bio for inline encryption - * @bio: a bio which will eventually be submitted to the file - * @inode: the file's inode - * @first_lblk: the first file logical block number in the I/O - * @gfp_mask: memory allocation flags - these must be a waiting mask so that - * bio_crypt_set_ctx can't fail. - * - * If the contents of the file should be encrypted (or decrypted) with inline - * encryption, then assign the appropriate encryption context to the bio. - * - * Normally the bio should be newly allocated (i.e. no pages added yet), as - * otherwise fscrypt_mergeable_bio() won't work as intended. - * - * The encryption context will be freed automatically when the bio is freed. - * - * This function also handles setting bi_skip_dm_default_key when needed. - */ -void fscrypt_set_bio_crypt_ctx(struct bio *bio, const struct inode *inode, - u64 first_lblk, gfp_t gfp_mask) -{ - const struct fscrypt_info *ci = inode->i_crypt_info; - u64 dun[BLK_CRYPTO_DUN_ARRAY_SIZE]; - - if (fscrypt_inode_should_skip_dm_default_key(inode)) - bio_set_skip_dm_default_key(bio); - - if (!fscrypt_inode_uses_inline_crypto(inode)) - return; - - fscrypt_generate_dun(ci, first_lblk, dun); - bio_crypt_set_ctx(bio, &ci->ci_key.blk_key->base, dun, gfp_mask); -} -EXPORT_SYMBOL_GPL(fscrypt_set_bio_crypt_ctx); - -/* Extract the inode and logical block number from a buffer_head. */ -static bool bh_get_inode_and_lblk_num(const struct buffer_head *bh, - const struct inode **inode_ret, - u64 *lblk_num_ret) -{ - struct page *page = bh->b_page; - const struct address_space *mapping; - const struct inode *inode; - - /* - * The ext4 journal (jbd2) can submit a buffer_head it directly created - * for a non-pagecache page. fscrypt doesn't care about these. - */ - mapping = page_mapping(page); - if (!mapping) - return false; - inode = mapping->host; - - *inode_ret = inode; - *lblk_num_ret = ((u64)page->index << (PAGE_SHIFT - inode->i_blkbits)) + - (bh_offset(bh) >> inode->i_blkbits); - return true; -} - -/** - * fscrypt_set_bio_crypt_ctx_bh - prepare a file contents bio for inline - * encryption - * @bio: a bio which will eventually be submitted to the file - * @first_bh: the first buffer_head for which I/O will be submitted - * @gfp_mask: memory allocation flags - * - * Same as fscrypt_set_bio_crypt_ctx(), except this takes a buffer_head instead - * of an inode and block number directly. - */ -void fscrypt_set_bio_crypt_ctx_bh(struct bio *bio, - const struct buffer_head *first_bh, - gfp_t gfp_mask) -{ - const struct inode *inode; - u64 first_lblk; - - if (bh_get_inode_and_lblk_num(first_bh, &inode, &first_lblk)) - fscrypt_set_bio_crypt_ctx(bio, inode, first_lblk, gfp_mask); -} -EXPORT_SYMBOL_GPL(fscrypt_set_bio_crypt_ctx_bh); - -/** - * fscrypt_mergeable_bio - test whether data can be added to a bio - * @bio: the bio being built up - * @inode: the inode for the next part of the I/O - * @next_lblk: the next file logical block number in the I/O - * - * When building a bio which may contain data which should undergo inline - * encryption (or decryption) via fscrypt, filesystems should call this function - * to ensure that the resulting bio contains only logically contiguous data. - * This will return false if the next part of the I/O cannot be merged with the - * bio because either the encryption key would be different or the encryption - * data unit numbers would be discontiguous. - * - * fscrypt_set_bio_crypt_ctx() must have already been called on the bio. - * - * This function also returns false if the next part of the I/O would need to - * have a different value for the bi_skip_dm_default_key flag. - * - * Return: true iff the I/O is mergeable - */ -bool fscrypt_mergeable_bio(struct bio *bio, const struct inode *inode, - u64 next_lblk) -{ - const struct bio_crypt_ctx *bc = bio->bi_crypt_context; - u64 next_dun[BLK_CRYPTO_DUN_ARRAY_SIZE]; - - if (!!bc != fscrypt_inode_uses_inline_crypto(inode)) - return false; - if (bio_should_skip_dm_default_key(bio) != - fscrypt_inode_should_skip_dm_default_key(inode)) - return false; - if (!bc) - return true; - - /* - * Comparing the key pointers is good enough, as all I/O for each key - * uses the same pointer. I.e., there's currently no need to support - * merging requests where the keys are the same but the pointers differ. - */ - if (bc->bc_key != &inode->i_crypt_info->ci_key.blk_key->base) - return false; - - fscrypt_generate_dun(inode->i_crypt_info, next_lblk, next_dun); - return bio_crypt_dun_is_contiguous(bc, bio->bi_iter.bi_size, next_dun); -} -EXPORT_SYMBOL_GPL(fscrypt_mergeable_bio); - -/** - * fscrypt_mergeable_bio_bh - test whether data can be added to a bio - * @bio: the bio being built up - * @next_bh: the next buffer_head for which I/O will be submitted - * - * Same as fscrypt_mergeable_bio(), except this takes a buffer_head instead of - * an inode and block number directly. - * - * Return: true iff the I/O is mergeable - */ -bool fscrypt_mergeable_bio_bh(struct bio *bio, - const struct buffer_head *next_bh) -{ - const struct inode *inode; - u64 next_lblk; - - if (!bh_get_inode_and_lblk_num(next_bh, &inode, &next_lblk)) - return !bio->bi_crypt_context && - !bio_should_skip_dm_default_key(bio); - - return fscrypt_mergeable_bio(bio, inode, next_lblk); -} -EXPORT_SYMBOL_GPL(fscrypt_mergeable_bio_bh); diff --git a/fs/crypto/keyring.c b/fs/crypto/keyring.c index 7facb5993b03..cdc9c0c74878 100644 --- a/fs/crypto/keyring.c +++ b/fs/crypto/keyring.c @@ -44,8 +44,8 @@ static void free_master_key(struct fscrypt_master_key *mk) wipe_master_key_secret(&mk->mk_secret); for (i = 0; i <= __FSCRYPT_MODE_MAX; i++) { - fscrypt_destroy_prepared_key(&mk->mk_direct_keys[i]); - fscrypt_destroy_prepared_key(&mk->mk_iv_ino_lblk_64_keys[i]); + crypto_free_skcipher(mk->mk_direct_tfms[i]); + crypto_free_skcipher(mk->mk_iv_ino_lblk_64_tfms[i]); } key_put(mk->mk_users); @@ -465,9 +465,6 @@ out_unlock: return err; } -/* Size of software "secret" derived from hardware-wrapped key */ -#define RAW_SECRET_SIZE 32 - /* * Add a master encryption key to the filesystem, causing all files which were * encrypted with it to appear "unlocked" (decrypted) when accessed. @@ -498,9 +495,6 @@ int fscrypt_ioctl_add_key(struct file *filp, void __user *_uarg) struct fscrypt_add_key_arg __user *uarg = _uarg; struct fscrypt_add_key_arg arg; struct fscrypt_master_key_secret secret; - u8 _kdf_key[RAW_SECRET_SIZE]; - u8 *kdf_key; - unsigned int kdf_key_size; int err; if (copy_from_user(&arg, uarg, sizeof(arg))) @@ -509,16 +503,11 @@ int fscrypt_ioctl_add_key(struct file *filp, void __user *_uarg) if (!valid_key_spec(&arg.key_spec)) return -EINVAL; - if (memchr_inv(arg.__reserved, 0, sizeof(arg.__reserved))) + if (arg.raw_size < FSCRYPT_MIN_KEY_SIZE || + arg.raw_size > FSCRYPT_MAX_KEY_SIZE) return -EINVAL; - BUILD_BUG_ON(FSCRYPT_MAX_HW_WRAPPED_KEY_SIZE < - FSCRYPT_MAX_KEY_SIZE); - - if (arg.raw_size < FSCRYPT_MIN_KEY_SIZE || - arg.raw_size > - ((arg.__flags & __FSCRYPT_ADD_KEY_FLAG_HW_WRAPPED) ? - FSCRYPT_MAX_HW_WRAPPED_KEY_SIZE : FSCRYPT_MAX_KEY_SIZE)) + if (memchr_inv(arg.__reserved, 0, sizeof(arg.__reserved))) return -EINVAL; memset(&secret, 0, sizeof(secret)); @@ -537,37 +526,18 @@ int fscrypt_ioctl_add_key(struct file *filp, void __user *_uarg) err = -EACCES; if (!capable(CAP_SYS_ADMIN)) goto out_wipe_secret; - - err = -EINVAL; - if (arg.__flags) - goto out_wipe_secret; break; case FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER: - err = -EINVAL; - if (arg.__flags & ~__FSCRYPT_ADD_KEY_FLAG_HW_WRAPPED) - goto out_wipe_secret; - if (arg.__flags & __FSCRYPT_ADD_KEY_FLAG_HW_WRAPPED) { - kdf_key = _kdf_key; - kdf_key_size = RAW_SECRET_SIZE; - err = fscrypt_derive_raw_secret(sb, secret.raw, - secret.size, - kdf_key, kdf_key_size); - if (err) - goto out_wipe_secret; - secret.is_hw_wrapped = true; - } else { - kdf_key = secret.raw; - kdf_key_size = secret.size; - } - err = fscrypt_init_hkdf(&secret.hkdf, kdf_key, kdf_key_size); - /* - * Now that the HKDF context is initialized, the raw HKDF - * key is no longer needed. - */ - memzero_explicit(kdf_key, kdf_key_size); + err = fscrypt_init_hkdf(&secret.hkdf, secret.raw, secret.size); if (err) goto out_wipe_secret; + /* + * Now that the HKDF context is initialized, the raw key is no + * longer needed. + */ + memzero_explicit(secret.raw, secret.size); + /* Calculate the key identifier and return it to userspace. */ err = fscrypt_hkdf_expand(&secret.hkdf, HKDF_CONTEXT_KEY_IDENTIFIER, diff --git a/fs/crypto/keysetup.c b/fs/crypto/keysetup.c index f87daf215ac9..2f926d3e6b5d 100644 --- a/fs/crypto/keysetup.c +++ b/fs/crypto/keysetup.c @@ -13,13 +13,12 @@ #include "fscrypt_private.h" -struct fscrypt_mode fscrypt_modes[] = { +static struct fscrypt_mode available_modes[] = { [FSCRYPT_MODE_AES_256_XTS] = { .friendly_name = "AES-256-XTS", .cipher_str = "xts(aes)", .keysize = 64, .ivsize = 16, - .blk_crypto_mode = BLK_ENCRYPTION_MODE_AES_256_XTS, }, [FSCRYPT_MODE_AES_256_CTS] = { .friendly_name = "AES-256-CTS-CBC", @@ -32,7 +31,6 @@ struct fscrypt_mode fscrypt_modes[] = { .cipher_str = "essiv(cbc(aes),sha256)", .keysize = 16, .ivsize = 16, - .blk_crypto_mode = BLK_ENCRYPTION_MODE_AES_128_CBC_ESSIV, }, [FSCRYPT_MODE_AES_128_CTS] = { .friendly_name = "AES-128-CTS-CBC", @@ -45,7 +43,6 @@ struct fscrypt_mode fscrypt_modes[] = { .cipher_str = "adiantum(xchacha12,aes)", .keysize = 32, .ivsize = 32, - .blk_crypto_mode = BLK_ENCRYPTION_MODE_ADIANTUM, }, }; @@ -54,10 +51,10 @@ select_encryption_mode(const union fscrypt_policy *policy, const struct inode *inode) { if (S_ISREG(inode->i_mode)) - return &fscrypt_modes[fscrypt_policy_contents_mode(policy)]; + return &available_modes[fscrypt_policy_contents_mode(policy)]; if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) - return &fscrypt_modes[fscrypt_policy_fnames_mode(policy)]; + return &available_modes[fscrypt_policy_fnames_mode(policy)]; WARN_ONCE(1, "fscrypt: filesystem tried to load encryption info for inode %lu, which is not encryptable (file type %d)\n", inode->i_ino, (inode->i_mode & S_IFMT)); @@ -65,9 +62,9 @@ select_encryption_mode(const union fscrypt_policy *policy, } /* Create a symmetric cipher object for the given encryption mode and key */ -static struct crypto_skcipher * -fscrypt_allocate_skcipher(struct fscrypt_mode *mode, const u8 *raw_key, - const struct inode *inode) +struct crypto_skcipher *fscrypt_allocate_skcipher(struct fscrypt_mode *mode, + const u8 *raw_key, + const struct inode *inode) { struct crypto_skcipher *tfm; int err; @@ -107,61 +104,30 @@ err_free_tfm: return ERR_PTR(err); } -/* - * Prepare the crypto transform object or blk-crypto key in @prep_key, given the - * raw key, encryption mode, and flag indicating which encryption implementation - * (fs-layer or blk-crypto) will be used. - */ -int fscrypt_prepare_key(struct fscrypt_prepared_key *prep_key, - const u8 *raw_key, unsigned int raw_key_size, - const struct fscrypt_info *ci) -{ - struct crypto_skcipher *tfm; - - if (fscrypt_using_inline_encryption(ci)) - return fscrypt_prepare_inline_crypt_key(prep_key, - raw_key, raw_key_size, ci); - - if (WARN_ON(raw_key_size != ci->ci_mode->keysize)) - return -EINVAL; - - tfm = fscrypt_allocate_skcipher(ci->ci_mode, raw_key, ci->ci_inode); - if (IS_ERR(tfm)) - return PTR_ERR(tfm); - /* - * Pairs with READ_ONCE() in fscrypt_is_key_prepared(). (Only matters - * for the per-mode keys, which are shared by multiple inodes.) - */ - smp_store_release(&prep_key->tfm, tfm); - return 0; -} - -/* Destroy a crypto transform object and/or blk-crypto key. */ -void fscrypt_destroy_prepared_key(struct fscrypt_prepared_key *prep_key) -{ - crypto_free_skcipher(prep_key->tfm); - fscrypt_destroy_inline_crypt_key(prep_key); -} - /* Given the per-file key, set up the file's crypto transform object */ int fscrypt_set_derived_key(struct fscrypt_info *ci, const u8 *derived_key) { + struct crypto_skcipher *tfm; + + tfm = fscrypt_allocate_skcipher(ci->ci_mode, derived_key, ci->ci_inode); + if (IS_ERR(tfm)) + return PTR_ERR(tfm); + + ci->ci_ctfm = tfm; ci->ci_owns_key = true; - return fscrypt_prepare_key(&ci->ci_key, derived_key, - ci->ci_mode->keysize, ci); + return 0; } static int setup_per_mode_key(struct fscrypt_info *ci, struct fscrypt_master_key *mk, - struct fscrypt_prepared_key *keys, + struct crypto_skcipher **tfms, u8 hkdf_context, bool include_fs_uuid) { - static DEFINE_MUTEX(mode_key_setup_mutex); const struct inode *inode = ci->ci_inode; const struct super_block *sb = inode->i_sb; struct fscrypt_mode *mode = ci->ci_mode; - const u8 mode_num = mode - fscrypt_modes; - struct fscrypt_prepared_key *prep_key; + u8 mode_num = mode - available_modes; + struct crypto_skcipher *tfm, *prev_tfm; u8 mode_key[FSCRYPT_MAX_KEY_SIZE]; u8 hkdf_info[sizeof(mode_num) + sizeof(sb->s_uuid)]; unsigned int hkdf_infolen = 0; @@ -170,65 +136,39 @@ static int setup_per_mode_key(struct fscrypt_info *ci, if (WARN_ON(mode_num > __FSCRYPT_MODE_MAX)) return -EINVAL; - prep_key = &keys[mode_num]; - if (fscrypt_is_key_prepared(prep_key, ci)) { - ci->ci_key = *prep_key; - return 0; + /* pairs with cmpxchg() below */ + tfm = READ_ONCE(tfms[mode_num]); + if (likely(tfm != NULL)) + goto done; + + BUILD_BUG_ON(sizeof(mode_num) != 1); + BUILD_BUG_ON(sizeof(sb->s_uuid) != 16); + BUILD_BUG_ON(sizeof(hkdf_info) != 17); + hkdf_info[hkdf_infolen++] = mode_num; + if (include_fs_uuid) { + memcpy(&hkdf_info[hkdf_infolen], &sb->s_uuid, + sizeof(sb->s_uuid)); + hkdf_infolen += sizeof(sb->s_uuid); } + err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf, + hkdf_context, hkdf_info, hkdf_infolen, + mode_key, mode->keysize); + if (err) + return err; + tfm = fscrypt_allocate_skcipher(mode, mode_key, inode); + memzero_explicit(mode_key, mode->keysize); + if (IS_ERR(tfm)) + return PTR_ERR(tfm); - mutex_lock(&mode_key_setup_mutex); - - if (fscrypt_is_key_prepared(prep_key, ci)) - goto done_unlock; - - if (mk->mk_secret.is_hw_wrapped && S_ISREG(inode->i_mode)) { - int i; - - if (!fscrypt_using_inline_encryption(ci)) { - fscrypt_warn(ci->ci_inode, - "Hardware-wrapped keys require inline encryption (-o inlinecrypt)"); - err = -EINVAL; - goto out_unlock; - } - for (i = 0; i <= __FSCRYPT_MODE_MAX; i++) { - if (fscrypt_is_key_prepared(&keys[i], ci)) { - fscrypt_warn(ci->ci_inode, - "Each hardware-wrapped key can only be used with one encryption mode"); - err = -EINVAL; - goto out_unlock; - } - } - err = fscrypt_prepare_key(prep_key, mk->mk_secret.raw, - mk->mk_secret.size, ci); - if (err) - goto out_unlock; - } else { - BUILD_BUG_ON(sizeof(mode_num) != 1); - BUILD_BUG_ON(sizeof(sb->s_uuid) != 16); - BUILD_BUG_ON(sizeof(hkdf_info) != 17); - hkdf_info[hkdf_infolen++] = mode_num; - if (include_fs_uuid) { - memcpy(&hkdf_info[hkdf_infolen], &sb->s_uuid, - sizeof(sb->s_uuid)); - hkdf_infolen += sizeof(sb->s_uuid); - } - err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf, - hkdf_context, hkdf_info, hkdf_infolen, - mode_key, mode->keysize); - if (err) - goto out_unlock; - err = fscrypt_prepare_key(prep_key, mode_key, mode->keysize, - ci); - memzero_explicit(mode_key, mode->keysize); - if (err) - goto out_unlock; + /* pairs with READ_ONCE() above */ + prev_tfm = cmpxchg(&tfms[mode_num], NULL, tfm); + if (prev_tfm != NULL) { + crypto_free_skcipher(tfm); + tfm = prev_tfm; } -done_unlock: - ci->ci_key = *prep_key; - err = 0; -out_unlock: - mutex_unlock(&mode_key_setup_mutex); - return err; +done: + ci->ci_ctfm = tfm; + return 0; } static int fscrypt_setup_v2_file_key(struct fscrypt_info *ci, @@ -237,13 +177,6 @@ static int fscrypt_setup_v2_file_key(struct fscrypt_info *ci, u8 derived_key[FSCRYPT_MAX_KEY_SIZE]; int err; - if (mk->mk_secret.is_hw_wrapped && - !(ci->ci_policy.v2.flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64)) { - fscrypt_warn(ci->ci_inode, - "Hardware-wrapped keys are only supported with IV_INO_LBLK_64 policies"); - return -EINVAL; - } - if (ci->ci_policy.v2.flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) { /* * DIRECT_KEY: instead of deriving per-file keys, the per-file @@ -259,7 +192,7 @@ static int fscrypt_setup_v2_file_key(struct fscrypt_info *ci, ci->ci_mode->friendly_name); return -EINVAL; } - return setup_per_mode_key(ci, mk, mk->mk_direct_keys, + return setup_per_mode_key(ci, mk, mk->mk_direct_tfms, HKDF_CONTEXT_DIRECT_KEY, false); } else if (ci->ci_policy.v2.flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64) { @@ -269,7 +202,7 @@ static int fscrypt_setup_v2_file_key(struct fscrypt_info *ci, * the IVs. This format is optimized for use with inline * encryption hardware compliant with the UFS or eMMC standards. */ - return setup_per_mode_key(ci, mk, mk->mk_iv_ino_lblk_64_keys, + return setup_per_mode_key(ci, mk, mk->mk_iv_ino_lblk_64_tfms, HKDF_CONTEXT_IV_INO_LBLK_64_KEY, true); } @@ -304,8 +237,6 @@ static int setup_file_encryption_key(struct fscrypt_info *ci, struct fscrypt_key_specifier mk_spec; int err; - fscrypt_select_encryption_impl(ci); - switch (ci->ci_policy.version) { case FSCRYPT_POLICY_V1: mk_spec.type = FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR; @@ -398,7 +329,7 @@ static void put_crypt_info(struct fscrypt_info *ci) if (ci->ci_direct_key) fscrypt_put_direct_key(ci->ci_direct_key); else if (ci->ci_owns_key) - fscrypt_destroy_prepared_key(&ci->ci_key); + crypto_free_skcipher(ci->ci_ctfm); key = ci->ci_master_key; if (key) { diff --git a/fs/crypto/keysetup_v1.c b/fs/crypto/keysetup_v1.c index 47591c54dc3d..454fb03fc30e 100644 --- a/fs/crypto/keysetup_v1.c +++ b/fs/crypto/keysetup_v1.c @@ -146,7 +146,7 @@ struct fscrypt_direct_key { struct hlist_node dk_node; refcount_t dk_refcount; const struct fscrypt_mode *dk_mode; - struct fscrypt_prepared_key dk_key; + struct crypto_skcipher *dk_ctfm; u8 dk_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE]; u8 dk_raw[FSCRYPT_MAX_KEY_SIZE]; }; @@ -154,7 +154,7 @@ struct fscrypt_direct_key { static void free_direct_key(struct fscrypt_direct_key *dk) { if (dk) { - fscrypt_destroy_prepared_key(&dk->dk_key); + crypto_free_skcipher(dk->dk_ctfm); kzfree(dk); } } @@ -199,8 +199,6 @@ find_or_insert_direct_key(struct fscrypt_direct_key *to_insert, continue; if (ci->ci_mode != dk->dk_mode) continue; - if (!fscrypt_is_key_prepared(&dk->dk_key, ci)) - continue; if (crypto_memneq(raw_key, dk->dk_raw, ci->ci_mode->keysize)) continue; /* using existing tfm with same (descriptor, mode, raw_key) */ @@ -233,10 +231,13 @@ fscrypt_get_direct_key(const struct fscrypt_info *ci, const u8 *raw_key) return ERR_PTR(-ENOMEM); refcount_set(&dk->dk_refcount, 1); dk->dk_mode = ci->ci_mode; - err = fscrypt_prepare_key(&dk->dk_key, raw_key, ci->ci_mode->keysize, - ci); - if (err) + dk->dk_ctfm = fscrypt_allocate_skcipher(ci->ci_mode, raw_key, + ci->ci_inode); + if (IS_ERR(dk->dk_ctfm)) { + err = PTR_ERR(dk->dk_ctfm); + dk->dk_ctfm = NULL; goto err_free_dk; + } memcpy(dk->dk_descriptor, ci->ci_policy.v1.master_key_descriptor, FSCRYPT_KEY_DESCRIPTOR_SIZE); memcpy(dk->dk_raw, raw_key, ci->ci_mode->keysize); @@ -273,7 +274,7 @@ static int setup_v1_file_key_direct(struct fscrypt_info *ci, if (IS_ERR(dk)) return PTR_ERR(dk); ci->ci_direct_key = dk; - ci->ci_key = dk->dk_key; + ci->ci_ctfm = dk->dk_ctfm; return 0; } diff --git a/fs/direct-io.c b/fs/direct-io.c index 729c59213d2e..30bf22c989de 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -432,7 +431,6 @@ dio_bio_alloc(struct dio *dio, struct dio_submit *sdio, sector_t first_sector, int nr_vecs) { struct bio *bio; - struct inode *inode = dio->inode; /* * bio_alloc() is guaranteed to return a bio when called with @@ -440,9 +438,6 @@ dio_bio_alloc(struct dio *dio, struct dio_submit *sdio, */ bio = bio_alloc(GFP_KERNEL, nr_vecs); - fscrypt_set_bio_crypt_ctx(bio, inode, - sdio->cur_page_fs_offset >> inode->i_blkbits, - GFP_KERNEL); bio_set_dev(bio, bdev); bio->bi_iter.bi_sector = first_sector; bio_set_op_attrs(bio, dio->op, dio->op_flags); diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 9decc3e73ca4..b993e4df016a 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -1155,7 +1155,6 @@ struct ext4_inode_info { #define EXT4_MOUNT_DIOREAD_NOLOCK 0x400000 /* Enable support for dio read nolocking */ #define EXT4_MOUNT_JOURNAL_CHECKSUM 0x800000 /* Journal checksums */ #define EXT4_MOUNT_JOURNAL_ASYNC_COMMIT 0x1000000 /* Journal Async Commit */ -#define EXT4_MOUNT_INLINECRYPT 0x4000000 /* Inline encryption support */ #define EXT4_MOUNT_DELALLOC 0x8000000 /* Delalloc support */ #define EXT4_MOUNT_DATA_ERR_ABORT 0x10000000 /* Abort on file data write */ #define EXT4_MOUNT_BLOCK_VALIDITY 0x20000000 /* Block validity checking */ diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 638151a97bfd..e2b466fd7f3a 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -1232,7 +1232,7 @@ static int ext4_block_write_begin(struct page *page, loff_t pos, unsigned len, (block_start < from || block_end > to)) { ll_rw_block(REQ_OP_READ, 0, 1, &bh); *wait_bh++ = bh; - decrypt = fscrypt_inode_uses_fs_layer_crypto(inode); + decrypt = IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode); } } /* @@ -3850,12 +3850,10 @@ static ssize_t ext4_direct_IO(struct kiocb *iocb, struct iov_iter *iter) ssize_t ret; int rw = iov_iter_rw(iter); - if (IS_ENABLED(CONFIG_FS_ENCRYPTION) && IS_ENCRYPTED(inode)) { - if (!fscrypt_inode_uses_inline_crypto(inode) || - !IS_ALIGNED(iocb->ki_pos | iov_iter_alignment(iter), - i_blocksize(inode))) - return 0; - } +#ifdef CONFIG_FS_ENCRYPTION + if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode)) + return 0; +#endif if (fsverity_active(inode)) return 0; @@ -4063,7 +4061,7 @@ static int __ext4_block_zero_page_range(handle_t *handle, /* Uhhuh. Read error. Complain and punt. */ if (!buffer_uptodate(bh)) goto unlock; - if (fscrypt_inode_uses_fs_layer_crypto(inode)) { + if (S_ISREG(inode->i_mode) && IS_ENCRYPTED(inode)) { /* We expect the key to be set. */ BUG_ON(!fscrypt_has_encryption_key(inode)); BUG_ON(blocksize != PAGE_SIZE); diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c index e2fad25e3913..6e00666feb4e 100644 --- a/fs/ext4/page-io.c +++ b/fs/ext4/page-io.c @@ -366,7 +366,6 @@ static int io_submit_init_bio(struct ext4_io_submit *io, bio = bio_alloc(GFP_NOIO, BIO_MAX_PAGES); if (!bio) return -ENOMEM; - fscrypt_set_bio_crypt_ctx_bh(bio, bh, GFP_NOIO); wbc_init_bio(io->io_wbc, bio); bio->bi_iter.bi_sector = bh->b_blocknr * (bh->b_size >> 9); bio_set_dev(bio, bh->b_bdev); @@ -384,8 +383,7 @@ static int io_submit_add_bh(struct ext4_io_submit *io, { int ret; - if (io->io_bio && (bh->b_blocknr != io->io_next_block || - !fscrypt_mergeable_bio_bh(io->io_bio, bh))) { + if (io->io_bio && bh->b_blocknr != io->io_next_block) { submit_and_retry: ext4_io_submit(io); } @@ -471,7 +469,7 @@ int ext4_bio_write_page(struct ext4_io_submit *io, bh = head = page_buffers(page); - if (fscrypt_inode_uses_fs_layer_crypto(inode) && nr_to_submit) { + if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode) && nr_to_submit) { gfp_t gfp_flags = GFP_NOFS; /* diff --git a/fs/ext4/readpage.c b/fs/ext4/readpage.c index 405b91f258a4..f74dead3fcc0 100644 --- a/fs/ext4/readpage.c +++ b/fs/ext4/readpage.c @@ -198,7 +198,7 @@ static struct bio_post_read_ctx *get_bio_post_read_ctx(struct inode *inode, unsigned int post_read_steps = 0; struct bio_post_read_ctx *ctx = NULL; - if (fscrypt_inode_uses_fs_layer_crypto(inode)) + if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode)) post_read_steps |= 1 << STEP_DECRYPT; if (ext4_need_verity(inode, first_idx)) @@ -259,7 +259,6 @@ int ext4_mpage_readpages(struct address_space *mapping, const unsigned blkbits = inode->i_blkbits; const unsigned blocks_per_page = PAGE_SIZE >> blkbits; const unsigned blocksize = 1 << blkbits; - sector_t next_block; sector_t block_in_file; sector_t last_block; sector_t last_block_in_file; @@ -291,8 +290,7 @@ int ext4_mpage_readpages(struct address_space *mapping, if (page_has_buffers(page)) goto confused; - block_in_file = next_block = - (sector_t)page->index << (PAGE_SHIFT - blkbits); + block_in_file = (sector_t)page->index << (PAGE_SHIFT - blkbits); last_block = block_in_file + nr_pages * blocks_per_page; last_block_in_file = (ext4_readpage_limit(inode) + blocksize - 1) >> blkbits; @@ -392,8 +390,7 @@ int ext4_mpage_readpages(struct address_space *mapping, * This page will go to BIO. Do we need to send this * BIO off first? */ - if (bio && (last_block_in_bio != blocks[0] - 1 || - !fscrypt_mergeable_bio(bio, inode, next_block))) { + if (bio && (last_block_in_bio != blocks[0] - 1)) { submit_and_realloc: ext4_submit_bio_read(bio); bio = NULL; @@ -405,8 +402,6 @@ int ext4_mpage_readpages(struct address_space *mapping, min_t(int, nr_pages, BIO_MAX_PAGES)); if (!bio) goto set_error_page; - fscrypt_set_bio_crypt_ctx(bio, inode, next_block, - GFP_KERNEL); ctx = get_bio_post_read_ctx(inode, bio, page->index); if (IS_ERR(ctx)) { bio_put(bio); diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 25fe536638d0..96235d0cc01c 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -1297,11 +1297,6 @@ static void ext4_get_ino_and_lblk_bits(struct super_block *sb, *lblk_bits_ret = 8 * sizeof(ext4_lblk_t); } -static bool ext4_inline_crypt_enabled(struct super_block *sb) -{ - return test_opt(sb, INLINECRYPT); -} - static const struct fscrypt_operations ext4_cryptops = { .key_prefix = "ext4:", .get_context = ext4_get_context, @@ -1311,7 +1306,6 @@ static const struct fscrypt_operations ext4_cryptops = { .max_namelen = EXT4_NAME_LEN, .has_stable_inodes = ext4_has_stable_inodes, .get_ino_and_lblk_bits = ext4_get_ino_and_lblk_bits, - .inline_crypt_enabled = ext4_inline_crypt_enabled, }; #endif @@ -1406,7 +1400,6 @@ enum { Opt_journal_path, Opt_journal_checksum, Opt_journal_async_commit, Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback, Opt_data_err_abort, Opt_data_err_ignore, Opt_test_dummy_encryption, - Opt_inlinecrypt, Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota, Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_jqfmt_vfsv1, Opt_quota, Opt_noquota, Opt_barrier, Opt_nobarrier, Opt_err, @@ -1500,7 +1493,6 @@ static const match_table_t tokens = { {Opt_noinit_itable, "noinit_itable"}, {Opt_max_dir_size_kb, "max_dir_size_kb=%u"}, {Opt_test_dummy_encryption, "test_dummy_encryption"}, - {Opt_inlinecrypt, "inlinecrypt"}, {Opt_nombcache, "nombcache"}, {Opt_nombcache, "no_mbcache"}, /* for backward compatibility */ {Opt_removed, "check=none"}, /* mount option from ext2/3 */ @@ -1710,11 +1702,6 @@ static const struct mount_opts { {Opt_jqfmt_vfsv1, QFMT_VFS_V1, MOPT_QFMT}, {Opt_max_dir_size_kb, 0, MOPT_GTE0}, {Opt_test_dummy_encryption, 0, MOPT_GTE0}, -#ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT - {Opt_inlinecrypt, EXT4_MOUNT_INLINECRYPT, MOPT_SET}, -#else - {Opt_inlinecrypt, EXT4_MOUNT_INLINECRYPT, MOPT_NOSUPPORT}, -#endif {Opt_nombcache, EXT4_MOUNT_NO_MBCACHE, MOPT_SET}, {Opt_err, 0, 0} }; diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 9fc829dd532c..689c8cd6d6a5 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -446,37 +446,6 @@ static struct bio *__bio_alloc(struct f2fs_io_info *fio, int npages) return bio; } -static void f2fs_set_bio_crypt_ctx(struct bio *bio, const struct inode *inode, - pgoff_t first_idx, - const struct f2fs_io_info *fio, - gfp_t gfp_mask) -{ - /* - * The f2fs garbage collector sets ->encrypted_page when it wants to - * read/write raw data without encryption. - */ - if (!fio || !fio->encrypted_page) - fscrypt_set_bio_crypt_ctx(bio, inode, first_idx, gfp_mask); - else if (fscrypt_inode_should_skip_dm_default_key(inode)) - bio_set_skip_dm_default_key(bio); -} - -static bool f2fs_crypt_mergeable_bio(struct bio *bio, const struct inode *inode, - pgoff_t next_idx, - const struct f2fs_io_info *fio) -{ - /* - * The f2fs garbage collector sets ->encrypted_page when it wants to - * read/write raw data without encryption. - */ - if (fio && fio->encrypted_page) - return !bio_has_crypt_ctx(bio) && - (bio_should_skip_dm_default_key(bio) == - fscrypt_inode_should_skip_dm_default_key(inode)); - - return fscrypt_mergeable_bio(bio, inode, next_idx); -} - static inline void __submit_bio(struct f2fs_sb_info *sbi, struct bio *bio, enum page_type type) { @@ -699,9 +668,6 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio) /* Allocate a new bio */ bio = __bio_alloc(fio, 1); - f2fs_set_bio_crypt_ctx(bio, fio->page->mapping->host, - fio->page->index, fio, GFP_NOIO); - if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) { bio_put(bio); return -EFAULT; @@ -893,17 +859,12 @@ int f2fs_merge_page_bio(struct f2fs_io_info *fio) trace_f2fs_submit_page_bio(page, fio); f2fs_trace_ios(fio, 0); - if (bio && (!page_is_mergeable(fio->sbi, bio, *fio->last_block, - fio->new_blkaddr) || - !f2fs_crypt_mergeable_bio(bio, fio->page->mapping->host, - fio->page->index, fio))) + if (bio && !page_is_mergeable(fio->sbi, bio, *fio->last_block, + fio->new_blkaddr)) f2fs_submit_merged_ipu_write(fio->sbi, &bio, NULL); alloc_new: if (!bio) { bio = __bio_alloc(fio, BIO_MAX_PAGES); - f2fs_set_bio_crypt_ctx(bio, fio->page->mapping->host, - fio->page->index, fio, - GFP_NOIO); bio_set_op_attrs(bio, fio->op, fio->op_flags); add_bio_entry(fio->sbi, bio, page, fio->temp); @@ -960,11 +921,8 @@ next: inc_page_count(sbi, WB_DATA_TYPE(bio_page)); - if (io->bio && - (!io_is_mergeable(sbi, io->bio, io, fio, io->last_block_in_bio, - fio->new_blkaddr) || - !f2fs_crypt_mergeable_bio(io->bio, fio->page->mapping->host, - fio->page->index, fio))) + if (io->bio && !io_is_mergeable(sbi, io->bio, io, fio, + io->last_block_in_bio, fio->new_blkaddr)) __submit_merged_bio(io); alloc_new: if (io->bio == NULL) { @@ -976,9 +934,6 @@ alloc_new: goto skip; } io->bio = __bio_alloc(fio, BIO_MAX_PAGES); - f2fs_set_bio_crypt_ctx(io->bio, fio->page->mapping->host, - fio->page->index, fio, - GFP_NOIO); io->fio = *fio; } @@ -1022,14 +977,11 @@ static struct bio *f2fs_grab_read_bio(struct inode *inode, block_t blkaddr, bio = f2fs_bio_alloc(sbi, min_t(int, nr_pages, BIO_MAX_PAGES), false); if (!bio) return ERR_PTR(-ENOMEM); - - f2fs_set_bio_crypt_ctx(bio, inode, first_idx, NULL, GFP_NOFS); - f2fs_target_device(sbi, blkaddr, bio); bio->bi_end_io = f2fs_read_end_io; bio_set_op_attrs(bio, REQ_OP_READ, op_flag); - if (fscrypt_inode_uses_fs_layer_crypto(inode)) + if (f2fs_encrypted_file(inode)) post_read_steps |= 1 << STEP_DECRYPT; if (f2fs_compressed_file(inode)) post_read_steps |= 1 << STEP_DECOMPRESS; @@ -2059,9 +2011,8 @@ zero_out: * This page will go to BIO. Do we need to send this * BIO off first? */ - if (bio && (!page_is_mergeable(F2FS_I_SB(inode), bio, - *last_block_in_bio, block_nr) || - !f2fs_crypt_mergeable_bio(bio, inode, page->index, NULL))) { + if (bio && !page_is_mergeable(F2FS_I_SB(inode), bio, + *last_block_in_bio, block_nr)) { submit_and_realloc: __f2fs_submit_read_bio(F2FS_I_SB(inode), bio, DATA); bio = NULL; @@ -2408,9 +2359,6 @@ int f2fs_encrypt_one_page(struct f2fs_io_info *fio) /* wait for GCed page writeback via META_MAPPING */ f2fs_wait_on_block_writeback(inode, fio->old_blkaddr); - if (fscrypt_inode_uses_inline_crypto(inode)) - return 0; - retry_encrypt: fio->encrypted_page = fscrypt_encrypt_pagecache_blocks(page, PAGE_SIZE, 0, gfp_flags); @@ -2584,7 +2532,7 @@ got_it: f2fs_unlock_op(fio->sbi); err = f2fs_inplace_write_data(fio); if (err) { - if (fscrypt_inode_uses_fs_layer_crypto(inode)) + if (f2fs_encrypted_file(inode)) fscrypt_finalize_bounce_page(&fio->encrypted_page); if (PageWriteback(page)) end_page_writeback(page); diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 57475e687e2f..720f2f44ed66 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -140,9 +140,6 @@ struct f2fs_mount_info { int alloc_mode; /* segment allocation policy */ int fsync_mode; /* fsync policy */ bool test_dummy_encryption; /* test dummy encryption */ -#ifdef CONFIG_FS_ENCRYPTION - bool inlinecrypt; /* inline encryption enabled */ -#endif block_t unusable_cap; /* Amount of space allowed to be * unusable when disabling checkpoint */ @@ -3980,13 +3977,7 @@ static inline bool f2fs_force_buffered_io(struct inode *inode, struct f2fs_sb_info *sbi = F2FS_I_SB(inode); int rw = iov_iter_rw(iter); - if (IS_ENABLED(CONFIG_FS_ENCRYPTION) && f2fs_encrypted_file(inode)) { - if (!fscrypt_inode_uses_inline_crypto(inode) || - !IS_ALIGNED(iocb->ki_pos | iov_iter_alignment(iter), - F2FS_BLKSIZE)) - return true; - } - if (fsverity_active(inode)) + if (f2fs_post_read_required(inode)) return true; if (f2fs_is_multi_device(sbi)) return true; diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 705bd7a5abe1..1ee49e33f480 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -137,7 +137,6 @@ enum { Opt_alloc, Opt_fsync, Opt_test_dummy_encryption, - Opt_inlinecrypt, Opt_checkpoint_disable, Opt_checkpoint_disable_cap, Opt_checkpoint_disable_cap_perc, @@ -203,7 +202,6 @@ static match_table_t f2fs_tokens = { {Opt_alloc, "alloc_mode=%s"}, {Opt_fsync, "fsync_mode=%s"}, {Opt_test_dummy_encryption, "test_dummy_encryption"}, - {Opt_inlinecrypt, "inlinecrypt"}, {Opt_checkpoint_disable, "checkpoint=disable"}, {Opt_checkpoint_disable_cap, "checkpoint=disable:%u"}, {Opt_checkpoint_disable_cap_perc, "checkpoint=disable:%u%%"}, @@ -792,13 +790,6 @@ static int parse_options(struct super_block *sb, char *options) f2fs_info(sbi, "Test dummy encryption mode enabled"); #else f2fs_info(sbi, "Test dummy encryption mount option ignored"); -#endif - break; - case Opt_inlinecrypt: -#ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT - F2FS_OPTION(sbi).inlinecrypt = true; -#else - f2fs_info(sbi, "inline encryption not supported"); #endif break; case Opt_checkpoint_disable_cap_perc: @@ -1555,8 +1546,6 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root) #ifdef CONFIG_FS_ENCRYPTION if (F2FS_OPTION(sbi).test_dummy_encryption) seq_puts(seq, ",test_dummy_encryption"); - if (F2FS_OPTION(sbi).inlinecrypt) - seq_puts(seq, ",inlinecrypt"); #endif if (F2FS_OPTION(sbi).alloc_mode == ALLOC_MODE_DEFAULT) @@ -1587,9 +1576,6 @@ static void default_options(struct f2fs_sb_info *sbi) F2FS_OPTION(sbi).alloc_mode = ALLOC_MODE_DEFAULT; F2FS_OPTION(sbi).fsync_mode = FSYNC_MODE_POSIX; F2FS_OPTION(sbi).test_dummy_encryption = false; -#ifdef CONFIG_FS_ENCRYPTION - F2FS_OPTION(sbi).inlinecrypt = false; -#endif F2FS_OPTION(sbi).s_resuid = make_kuid(&init_user_ns, F2FS_DEF_RESUID); F2FS_OPTION(sbi).s_resgid = make_kgid(&init_user_ns, F2FS_DEF_RESGID); F2FS_OPTION(sbi).compress_algorithm = COMPRESS_LZO; @@ -2437,30 +2423,6 @@ static void f2fs_get_ino_and_lblk_bits(struct super_block *sb, *lblk_bits_ret = 8 * sizeof(block_t); } -static bool f2fs_inline_crypt_enabled(struct super_block *sb) -{ - return F2FS_OPTION(F2FS_SB(sb)).inlinecrypt; -} - -static int f2fs_get_num_devices(struct super_block *sb) -{ - struct f2fs_sb_info *sbi = F2FS_SB(sb); - - if (f2fs_is_multi_device(sbi)) - return sbi->s_ndevs; - return 1; -} - -static void f2fs_get_devices(struct super_block *sb, - struct request_queue **devs) -{ - struct f2fs_sb_info *sbi = F2FS_SB(sb); - int i; - - for (i = 0; i < sbi->s_ndevs; i++) - devs[i] = bdev_get_queue(FDEV(i).bdev); -} - static const struct fscrypt_operations f2fs_cryptops = { .key_prefix = "f2fs:", .get_context = f2fs_get_context, @@ -2470,9 +2432,6 @@ static const struct fscrypt_operations f2fs_cryptops = { .max_namelen = F2FS_NAME_LEN, .has_stable_inodes = f2fs_has_stable_inodes, .get_ino_and_lblk_bits = f2fs_get_ino_and_lblk_bits, - .inline_crypt_enabled = f2fs_inline_crypt_enabled, - .get_num_devices = f2fs_get_num_devices, - .get_devices = f2fs_get_devices, }; #endif diff --git a/fs/incfs/data_mgmt.c b/fs/incfs/data_mgmt.c index 4698f14bbdf7..109329e0a180 100644 --- a/fs/incfs/data_mgmt.c +++ b/fs/incfs/data_mgmt.c @@ -85,11 +85,11 @@ static void data_file_segment_destroy(struct data_file_segment *segment) struct data_file *incfs_open_data_file(struct mount_info *mi, struct file *bf) { - struct data_file *df; - struct backing_file_context *bfc; + struct data_file *df = NULL; + struct backing_file_context *bfc = NULL; int md_records; u64 size; - int error; + int error = 0; int i; if (!bf || !mi) @@ -160,7 +160,7 @@ int make_inode_ready_for_data_ops(struct mount_info *mi, struct file *backing_file) { struct inode_info *node = get_incfs_node(inode); - struct data_file *df; + struct data_file *df = NULL; int err = 0; inode_lock(inode); @@ -181,7 +181,7 @@ int make_inode_ready_for_data_ops(struct mount_info *mi, struct dir_file *incfs_open_dir_file(struct mount_info *mi, struct file *bf) { - struct dir_file *dir; + struct dir_file *dir = NULL; if (!S_ISDIR(bf->f_inode->i_mode)) return ERR_PTR(-EBADF); @@ -222,12 +222,11 @@ static void log_block_read(struct mount_info *mi, incfs_uuid_t *id, s64 now_us = ktime_to_us(ktime_get()); struct read_log_record record = { .file_id = *id, + .block_index = block_index, + .timed_out = timed_out, .timestamp_us = now_us }; - set_block_index(&record, block_index); - set_timed_out(&record, timed_out); - if (log->rl_size == 0) return; @@ -1063,7 +1062,7 @@ static void fill_pending_read_from_log_record( struct read_log_state *state, u64 log_size) { dest->file_id = src->file_id; - dest->block_index = get_block_index(src); + dest->block_index = src->block_index; dest->serial_number = state->current_pass_no * log_size + state->next_index; dest->timestamp_us = src->timestamp_us; diff --git a/fs/incfs/data_mgmt.h b/fs/incfs/data_mgmt.h index 6722cef1608c..82ccab3be4bb 100644 --- a/fs/incfs/data_mgmt.h +++ b/fs/incfs/data_mgmt.h @@ -21,41 +21,15 @@ #define SEGMENTS_PER_FILE 3 struct read_log_record { - u32 bitfield; + u32 block_index : 31; + + u32 timed_out : 1; u64 timestamp_us; incfs_uuid_t file_id; } __packed; -#define RLR_BLOCK_INDEX_MASK 0x7fff -#define RLR_TIMED_OUT_MASK 0x8000 - -static inline u32 get_block_index(const struct read_log_record *rlr) -{ - return rlr->bitfield & RLR_BLOCK_INDEX_MASK; -} - -static inline void set_block_index(struct read_log_record *rlr, - u32 block_index) -{ - rlr->bitfield = (rlr->bitfield & ~RLR_BLOCK_INDEX_MASK) - | (block_index & RLR_BLOCK_INDEX_MASK); -} - -static inline bool get_timed_out(const struct read_log_record *rlr) -{ - return (rlr->bitfield & RLR_TIMED_OUT_MASK) == RLR_TIMED_OUT_MASK; -} - -static inline void set_timed_out(struct read_log_record *rlr, bool timed_out) -{ - if (timed_out) - rlr->bitfield |= RLR_TIMED_OUT_MASK; - else - rlr->bitfield &= ~RLR_TIMED_OUT_MASK; -} - struct read_log_state { /* Next slot in rl_ring_buf to write to. */ u32 next_index; @@ -297,7 +271,7 @@ static inline struct inode_info *get_incfs_node(struct inode *inode) static inline struct data_file *get_incfs_data_file(struct file *f) { - struct inode_info *node; + struct inode_info *node = NULL; if (!f) return NULL; diff --git a/fs/incfs/vfs.c b/fs/incfs/vfs.c index aebd2b02bd83..e4790189abd3 100644 --- a/fs/incfs/vfs.c +++ b/fs/incfs/vfs.c @@ -350,6 +350,7 @@ static int inode_set(struct inode *inode, void *opaque) struct dentry *backing_dentry = search->backing_dentry; struct inode *backing_inode = d_inode(backing_dentry); + inode_init_owner(inode, NULL, backing_inode->i_mode); fsstack_copy_attr_all(inode, backing_inode); if (S_ISREG(inode->i_mode)) { u64 size = read_size_attr(backing_dentry); @@ -381,7 +382,6 @@ static int inode_set(struct inode *inode, void *opaque) pr_warn("incfs: ino conflict with backing FS %ld\n", backing_inode->i_ino); } - return 0; } else if (search->ino == INCFS_PENDING_READS_INODE) { /* It's an inode for .pending_reads pseudo file. */ @@ -868,10 +868,9 @@ static struct signature_info *incfs_copy_signature_info_from_user( goto err; } - /* TODO this sets the root_hash length to MAX_HASH_SIZE not - * the actual size. Fix, then set INCFS_MAX_HASH_SIZE back - * to 64 - */ + // TODO this sets the root_hash length to MAX_HASH_SIZE not + // the actual size. Fix, then set INCFS_MAX_HASH_SIZE back + // to 64 result->root_hash = range(p, INCFS_MAX_HASH_SIZE); if (copy_from_user(p, u64_to_user_ptr(usr_si.root_hash), result->root_hash.len) > 0) { @@ -1006,9 +1005,8 @@ static int init_new_file(struct mount_info *mi, struct dentry *dentry, goto out; } - /* TODO This code seems wrong when len is zero - we - * should error out?? - */ + // TODO This code seems wrong when len is zero - we + // should error out?? if (si->signature.len > 0) error = incfs_validate_pkcs7_signature( si->signature, @@ -1116,6 +1114,8 @@ static int dir_relative_path_resolve( LOOKUP_FOLLOW | LOOKUP_DIRECTORY, result_path, NULL); out: + // TODO sys_close should be replaced with ksys_close on later kernel + // Add to compat or some such? sys_close(dir_fd); if (error) pr_debug("incfs: %s %d\n", __func__, error); @@ -1140,27 +1140,6 @@ static int validate_name(char *file_name) return 0; } -static int chmod(struct dentry *dentry, umode_t mode) -{ - struct inode *inode = dentry->d_inode; - struct inode *delegated_inode = NULL; - struct iattr newattrs; - int error; - -retry_deleg: - inode_lock(inode); - newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); - newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; - error = notify_change(dentry, &newattrs, &delegated_inode); - inode_unlock(inode); - if (delegated_inode) { - error = break_deleg_wait(&delegated_inode); - if (!error) - goto retry_deleg; - } - return error; -} - static long ioctl_create_file(struct mount_info *mi, struct incfs_new_file_args __user *usr_args) { @@ -1261,8 +1240,8 @@ static long ioctl_create_file(struct mount_info *mi, /* Creating a file in the .index dir. */ index_dir_inode = d_inode(mi->mi_index_dir); inode_lock_nested(index_dir_inode, I_MUTEX_PARENT); - error = vfs_create(index_dir_inode, index_file_dentry, args.mode | 0222, - true); + error = vfs_create(index_dir_inode, index_file_dentry, + args.mode, true); inode_unlock(index_dir_inode); if (error) @@ -1272,12 +1251,6 @@ static long ioctl_create_file(struct mount_info *mi, goto out; } - error = chmod(index_file_dentry, args.mode | 0222); - if (error) { - pr_debug("incfs: chmod err: %d\n", error); - goto delete_index_file; - } - /* Save the file's ID as an xattr for easy fetching in future. */ error = vfs_setxattr(index_file_dentry, INCFS_XATTR_ID_NAME, file_id_str, strlen(file_id_str), XATTR_CREATE); @@ -1484,7 +1457,6 @@ static struct dentry *dir_lookup(struct inode *dir_inode, struct dentry *dentry, err = IS_ERR(backing_dentry) ? PTR_ERR(backing_dentry) : -EFAULT; - backing_dentry = NULL; goto out; } else { struct inode *inode = NULL; @@ -1568,7 +1540,7 @@ static int dir_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) } inode_lock_nested(dir_node->n_backing_inode, I_MUTEX_PARENT); - err = vfs_mkdir(dir_node->n_backing_inode, backing_dentry, mode | 0222); + err = vfs_mkdir(dir_node->n_backing_inode, backing_dentry, mode); inode_unlock(dir_node->n_backing_inode); if (!err) { struct inode *inode = NULL; diff --git a/fs/iomap.c b/fs/iomap.c index 1e573a59ea71..3f5b1655cfce 100644 --- a/fs/iomap.c +++ b/fs/iomap.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -826,13 +825,10 @@ static blk_qc_t iomap_dio_zero(struct iomap_dio *dio, struct iomap *iomap, loff_t pos, unsigned len) { - struct inode *inode = file_inode(dio->iocb->ki_filp); struct page *page = ZERO_PAGE(0); struct bio *bio; bio = bio_alloc(GFP_KERNEL, 1); - fscrypt_set_bio_crypt_ctx(bio, inode, pos >> inode->i_blkbits, - GFP_KERNEL); bio_set_dev(bio, iomap->bdev); bio->bi_iter.bi_sector = iomap->blkno + ((pos - iomap->offset) >> 9); @@ -912,8 +908,6 @@ iomap_dio_actor(struct inode *inode, loff_t pos, loff_t length, return 0; bio = bio_alloc(GFP_KERNEL, nr_pages); - fscrypt_set_bio_crypt_ctx(bio, inode, pos >> inode->i_blkbits, - GFP_KERNEL); bio_set_dev(bio, iomap->bdev); bio->bi_iter.bi_sector = iomap->blkno + ((pos - iomap->offset) >> 9); diff --git a/include/linux/bio-crypt-ctx.h b/include/linux/bio-crypt-ctx.h deleted file mode 100644 index ab22dbe7b880..000000000000 --- a/include/linux/bio-crypt-ctx.h +++ /dev/null @@ -1,226 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright 2019 Google LLC - */ -#ifndef __LINUX_BIO_CRYPT_CTX_H -#define __LINUX_BIO_CRYPT_CTX_H - -enum blk_crypto_mode_num { - BLK_ENCRYPTION_MODE_INVALID, - BLK_ENCRYPTION_MODE_AES_256_XTS, - BLK_ENCRYPTION_MODE_AES_128_CBC_ESSIV, - BLK_ENCRYPTION_MODE_ADIANTUM, - BLK_ENCRYPTION_MODE_MAX, -}; - -#ifdef CONFIG_BLOCK -#include - -#ifdef CONFIG_BLK_INLINE_ENCRYPTION - -#define BLK_CRYPTO_MAX_KEY_SIZE 64 -#define BLK_CRYPTO_MAX_WRAPPED_KEY_SIZE 128 - -/** - * struct blk_crypto_key - an inline encryption key - * @crypto_mode: encryption algorithm this key is for - * @data_unit_size: the data unit size for all encryption/decryptions with this - * key. This is the size in bytes of each individual plaintext and - * ciphertext. This is always a power of 2. It might be e.g. the - * filesystem block size or the disk sector size. - * @data_unit_size_bits: log2 of data_unit_size - * @size: size of this key in bytes (determined by @crypto_mode) - * @hash: hash of this key, for keyslot manager use only - * @raw: the raw bytes of this key. Only the first @size bytes are used. - * - * A blk_crypto_key is immutable once created, and many bios can reference it at - * the same time. It must not be freed until all bios using it have completed. - */ -struct blk_crypto_key { - enum blk_crypto_mode_num crypto_mode; - unsigned int data_unit_size; - unsigned int data_unit_size_bits; - unsigned int size; - unsigned int hash; - u8 raw[BLK_CRYPTO_MAX_WRAPPED_KEY_SIZE]; -}; - -#define BLK_CRYPTO_MAX_IV_SIZE 32 -#define BLK_CRYPTO_DUN_ARRAY_SIZE (BLK_CRYPTO_MAX_IV_SIZE/sizeof(u64)) - -/** - * struct bio_crypt_ctx - an inline encryption context - * @bc_key: the key, algorithm, and data unit size to use - * @bc_keyslot: the keyslot that has been assigned for this key in @bc_ksm, - * or -1 if no keyslot has been assigned yet. - * @bc_dun: the data unit number (starting IV) to use - * @bc_ksm: the keyslot manager into which the key has been programmed with - * @bc_keyslot, or NULL if this key hasn't yet been programmed. - * - * A bio_crypt_ctx specifies that the contents of the bio will be encrypted (for - * write requests) or decrypted (for read requests) inline by the storage device - * or controller, or by the crypto API fallback. - */ -struct bio_crypt_ctx { - const struct blk_crypto_key *bc_key; - int bc_keyslot; - - /* Data unit number */ - u64 bc_dun[BLK_CRYPTO_DUN_ARRAY_SIZE]; - - /* - * The keyslot manager where the key has been programmed - * with keyslot. - */ - struct keyslot_manager *bc_ksm; -}; - -int bio_crypt_ctx_init(void); - -struct bio_crypt_ctx *bio_crypt_alloc_ctx(gfp_t gfp_mask); - -void bio_crypt_free_ctx(struct bio *bio); - -static inline bool bio_has_crypt_ctx(struct bio *bio) -{ - return bio->bi_crypt_context; -} - -void bio_crypt_clone(struct bio *dst, struct bio *src, gfp_t gfp_mask); - -static inline void bio_crypt_set_ctx(struct bio *bio, - const struct blk_crypto_key *key, - u64 dun[BLK_CRYPTO_DUN_ARRAY_SIZE], - gfp_t gfp_mask) -{ - struct bio_crypt_ctx *bc = bio_crypt_alloc_ctx(gfp_mask); - - bc->bc_key = key; - memcpy(bc->bc_dun, dun, sizeof(bc->bc_dun)); - bc->bc_ksm = NULL; - bc->bc_keyslot = -1; - - bio->bi_crypt_context = bc; -} - -void bio_crypt_ctx_release_keyslot(struct bio_crypt_ctx *bc); - -int bio_crypt_ctx_acquire_keyslot(struct bio_crypt_ctx *bc, - struct keyslot_manager *ksm); - -struct request; -bool bio_crypt_should_process(struct request *rq); - -static inline bool bio_crypt_dun_is_contiguous(const struct bio_crypt_ctx *bc, - unsigned int bytes, - u64 next_dun[BLK_CRYPTO_DUN_ARRAY_SIZE]) -{ - int i = 0; - unsigned int inc = bytes >> bc->bc_key->data_unit_size_bits; - - while (i < BLK_CRYPTO_DUN_ARRAY_SIZE) { - if (bc->bc_dun[i] + inc != next_dun[i]) - return false; - inc = ((bc->bc_dun[i] + inc) < inc); - i++; - } - - return true; -} - - -static inline void bio_crypt_dun_increment(u64 dun[BLK_CRYPTO_DUN_ARRAY_SIZE], - unsigned int inc) -{ - int i = 0; - - while (inc && i < BLK_CRYPTO_DUN_ARRAY_SIZE) { - dun[i] += inc; - inc = (dun[i] < inc); - i++; - } -} - -static inline void bio_crypt_advance(struct bio *bio, unsigned int bytes) -{ - struct bio_crypt_ctx *bc = bio->bi_crypt_context; - - if (!bc) - return; - - bio_crypt_dun_increment(bc->bc_dun, - bytes >> bc->bc_key->data_unit_size_bits); -} - -bool bio_crypt_ctx_compatible(struct bio *b_1, struct bio *b_2); - -bool bio_crypt_ctx_mergeable(struct bio *b_1, unsigned int b1_bytes, - struct bio *b_2); - -#else /* CONFIG_BLK_INLINE_ENCRYPTION */ -static inline int bio_crypt_ctx_init(void) -{ - return 0; -} - -static inline bool bio_has_crypt_ctx(struct bio *bio) -{ - return false; -} - -static inline void bio_crypt_clone(struct bio *dst, struct bio *src, - gfp_t gfp_mask) { } - -static inline void bio_crypt_free_ctx(struct bio *bio) { } - -static inline void bio_crypt_advance(struct bio *bio, unsigned int bytes) { } - -static inline bool bio_crypt_ctx_compatible(struct bio *b_1, struct bio *b_2) -{ - return true; -} - -static inline bool bio_crypt_ctx_mergeable(struct bio *b_1, - unsigned int b1_bytes, - struct bio *b_2) -{ - return true; -} - -#endif /* CONFIG_BLK_INLINE_ENCRYPTION */ - -#if IS_ENABLED(CONFIG_DM_DEFAULT_KEY) -static inline void bio_set_skip_dm_default_key(struct bio *bio) -{ - bio->bi_skip_dm_default_key = true; -} - -static inline bool bio_should_skip_dm_default_key(const struct bio *bio) -{ - return bio->bi_skip_dm_default_key; -} - -static inline void bio_clone_skip_dm_default_key(struct bio *dst, - const struct bio *src) -{ - dst->bi_skip_dm_default_key = src->bi_skip_dm_default_key; -} -#else /* CONFIG_DM_DEFAULT_KEY */ -static inline void bio_set_skip_dm_default_key(struct bio *bio) -{ -} - -static inline bool bio_should_skip_dm_default_key(const struct bio *bio) -{ - return false; -} - -static inline void bio_clone_skip_dm_default_key(struct bio *dst, - const struct bio *src) -{ -} -#endif /* !CONFIG_DM_DEFAULT_KEY */ - -#endif /* CONFIG_BLOCK */ - -#endif /* __LINUX_BIO_CRYPT_CTX_H */ diff --git a/include/linux/bio.h b/include/linux/bio.h index 2e08e3731376..e260f000b9ac 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -22,7 +22,6 @@ #include #include #include -#include #ifdef CONFIG_BLOCK diff --git a/include/linux/blk-crypto.h b/include/linux/blk-crypto.h deleted file mode 100644 index 485cee0b92dd..000000000000 --- a/include/linux/blk-crypto.h +++ /dev/null @@ -1,66 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright 2019 Google LLC - */ - -#ifndef __LINUX_BLK_CRYPTO_H -#define __LINUX_BLK_CRYPTO_H - -#include - -#define SECTOR_SHIFT 9 - -#ifdef CONFIG_BLK_INLINE_ENCRYPTION - -int blk_crypto_submit_bio(struct bio **bio_ptr); - -bool blk_crypto_endio(struct bio *bio); - -int blk_crypto_init_key(struct blk_crypto_key *blk_key, - const u8 *raw_key, unsigned int raw_key_size, - enum blk_crypto_mode_num crypto_mode, - unsigned int data_unit_size); - -int blk_crypto_evict_key(struct request_queue *q, - const struct blk_crypto_key *key); - -#else /* CONFIG_BLK_INLINE_ENCRYPTION */ - -static inline int blk_crypto_submit_bio(struct bio **bio_ptr) -{ - return 0; -} - -static inline bool blk_crypto_endio(struct bio *bio) -{ - return true; -} - -#endif /* CONFIG_BLK_INLINE_ENCRYPTION */ - -#ifdef CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK - -int blk_crypto_start_using_mode(enum blk_crypto_mode_num mode_num, - unsigned int data_unit_size, - struct request_queue *q); - -int blk_crypto_fallback_init(void); - -#else /* CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK */ - -static inline int -blk_crypto_start_using_mode(enum blk_crypto_mode_num mode_num, - unsigned int data_unit_size, - struct request_queue *q) -{ - return 0; -} - -static inline int blk_crypto_fallback_init(void) -{ - return 0; -} - -#endif /* CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK */ - -#endif /* __LINUX_BLK_CRYPTO_H */ diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index 736dc8c10f61..1cc3d4d3bc43 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h @@ -17,7 +17,6 @@ struct block_device; struct io_context; struct cgroup_subsys_state; typedef void (bio_end_io_t) (struct bio *); -struct bio_crypt_ctx; /* * Block error status values. See block/blk-core:blk_errors for the details. @@ -96,14 +95,6 @@ struct bio { struct blk_issue_stat bi_issue_stat; #endif #endif - -#ifdef CONFIG_BLK_INLINE_ENCRYPTION - struct bio_crypt_ctx *bi_crypt_context; -#if IS_ENABLED(CONFIG_DM_DEFAULT_KEY) - bool bi_skip_dm_default_key; -#endif -#endif - union { #if defined(CONFIG_BLK_DEV_INTEGRITY) struct bio_integrity_payload *bi_integrity; /* data integrity */ diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 909af748ea1a..ad940102451c 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -43,7 +43,6 @@ struct pr_ops; struct rq_wb; struct blk_queue_stats; struct blk_stat_callback; -struct keyslot_manager; #define BLKDEV_MIN_RQ 4 #define BLKDEV_MAX_RQ 128 /* Default maximum */ @@ -543,11 +542,6 @@ struct request_queue { */ unsigned int request_fn_active; -#ifdef CONFIG_BLK_INLINE_ENCRYPTION - /* Inline crypto capabilities */ - struct keyslot_manager *ksm; -#endif - unsigned int rq_timeout; int poll_nsec; diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h index 248e6ecea471..91a063a1f3b3 100644 --- a/include/linux/device-mapper.h +++ b/include/linux/device-mapper.h @@ -321,12 +321,6 @@ struct dm_target { * on max_io_len boundary. */ bool split_discard_bios:1; - - /* - * Set if inline crypto capabilities from this target's underlying - * device(s) can be exposed via the device-mapper device. - */ - bool may_passthrough_inline_crypto:1; }; /* Each target can link one of these into the table */ diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h index 6ac092cc4067..81ec35256aed 100644 --- a/include/linux/fscrypt.h +++ b/include/linux/fscrypt.h @@ -64,10 +64,6 @@ struct fscrypt_operations { bool (*has_stable_inodes)(struct super_block *sb); void (*get_ino_and_lblk_bits)(struct super_block *sb, int *ino_bits_ret, int *lblk_bits_ret); - bool (*inline_crypt_enabled)(struct super_block *sb); - int (*get_num_devices)(struct super_block *sb); - void (*get_devices)(struct super_block *sb, - struct request_queue **devs); }; static inline bool fscrypt_has_encryption_key(const struct inode *inode) @@ -536,74 +532,6 @@ static inline const char *fscrypt_get_symlink(struct inode *inode, } #endif /* !CONFIG_FS_ENCRYPTION */ -/* inline_crypt.c */ -#ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT -extern bool fscrypt_inode_uses_inline_crypto(const struct inode *inode); - -extern bool fscrypt_inode_uses_fs_layer_crypto(const struct inode *inode); - -extern void fscrypt_set_bio_crypt_ctx(struct bio *bio, - const struct inode *inode, - u64 first_lblk, gfp_t gfp_mask); - -extern void fscrypt_set_bio_crypt_ctx_bh(struct bio *bio, - const struct buffer_head *first_bh, - gfp_t gfp_mask); - -extern bool fscrypt_mergeable_bio(struct bio *bio, const struct inode *inode, - u64 next_lblk); - -extern bool fscrypt_mergeable_bio_bh(struct bio *bio, - const struct buffer_head *next_bh); - -#else /* CONFIG_FS_ENCRYPTION_INLINE_CRYPT */ -static inline bool fscrypt_inode_uses_inline_crypto(const struct inode *inode) -{ - return false; -} - -static inline bool fscrypt_inode_uses_fs_layer_crypto(const struct inode *inode) -{ - return IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode); -} - -static inline void fscrypt_set_bio_crypt_ctx(struct bio *bio, - const struct inode *inode, - u64 first_lblk, gfp_t gfp_mask) { } - -static inline void fscrypt_set_bio_crypt_ctx_bh( - struct bio *bio, - const struct buffer_head *first_bh, - gfp_t gfp_mask) { } - -static inline bool fscrypt_mergeable_bio(struct bio *bio, - const struct inode *inode, - u64 next_lblk) -{ - return true; -} - -static inline bool fscrypt_mergeable_bio_bh(struct bio *bio, - const struct buffer_head *next_bh) -{ - return true; -} -#endif /* !CONFIG_FS_ENCRYPTION_INLINE_CRYPT */ - -#if IS_ENABLED(CONFIG_FS_ENCRYPTION) && IS_ENABLED(CONFIG_DM_DEFAULT_KEY) -static inline bool -fscrypt_inode_should_skip_dm_default_key(const struct inode *inode) -{ - return IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode); -} -#else -static inline bool -fscrypt_inode_should_skip_dm_default_key(const struct inode *inode) -{ - return false; -} -#endif - /** * fscrypt_require_key - require an inode's encryption key * @inode: the inode we need the key for diff --git a/include/linux/keyslot-manager.h b/include/linux/keyslot-manager.h deleted file mode 100644 index 6d32a031218e..000000000000 --- a/include/linux/keyslot-manager.h +++ /dev/null @@ -1,84 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright 2019 Google LLC - */ - -#ifndef __LINUX_KEYSLOT_MANAGER_H -#define __LINUX_KEYSLOT_MANAGER_H - -#include - -#ifdef CONFIG_BLK_INLINE_ENCRYPTION - -struct keyslot_manager; - -/** - * struct keyslot_mgmt_ll_ops - functions to manage keyslots in hardware - * @keyslot_program: Program the specified key into the specified slot in the - * inline encryption hardware. - * @keyslot_evict: Evict key from the specified keyslot in the hardware. - * The key is provided so that e.g. dm layers can evict - * keys from the devices that they map over. - * Returns 0 on success, -errno otherwise. - * @derive_raw_secret: (Optional) Derive a software secret from a - * hardware-wrapped key. Returns 0 on success, -EOPNOTSUPP - * if unsupported on the hardware, or another -errno code. - * - * This structure should be provided by storage device drivers when they set up - * a keyslot manager - this structure holds the function ptrs that the keyslot - * manager will use to manipulate keyslots in the hardware. - */ -struct keyslot_mgmt_ll_ops { - int (*keyslot_program)(struct keyslot_manager *ksm, - const struct blk_crypto_key *key, - unsigned int slot); - int (*keyslot_evict)(struct keyslot_manager *ksm, - const struct blk_crypto_key *key, - unsigned int slot); - int (*derive_raw_secret)(struct keyslot_manager *ksm, - const u8 *wrapped_key, - unsigned int wrapped_key_size, - u8 *secret, unsigned int secret_size); -}; - -struct keyslot_manager *keyslot_manager_create(unsigned int num_slots, - const struct keyslot_mgmt_ll_ops *ksm_ops, - const unsigned int crypto_mode_supported[BLK_ENCRYPTION_MODE_MAX], - void *ll_priv_data); - -int keyslot_manager_get_slot_for_key(struct keyslot_manager *ksm, - const struct blk_crypto_key *key); - -void keyslot_manager_get_slot(struct keyslot_manager *ksm, unsigned int slot); - -void keyslot_manager_put_slot(struct keyslot_manager *ksm, unsigned int slot); - -bool keyslot_manager_crypto_mode_supported(struct keyslot_manager *ksm, - enum blk_crypto_mode_num crypto_mode, - unsigned int data_unit_size); - -int keyslot_manager_evict_key(struct keyslot_manager *ksm, - const struct blk_crypto_key *key); - -void keyslot_manager_reprogram_all_keys(struct keyslot_manager *ksm); - -void *keyslot_manager_private(struct keyslot_manager *ksm); - -void keyslot_manager_destroy(struct keyslot_manager *ksm); - -struct keyslot_manager *keyslot_manager_create_passthrough( - const struct keyslot_mgmt_ll_ops *ksm_ops, - const unsigned int crypto_mode_supported[BLK_ENCRYPTION_MODE_MAX], - void *ll_priv_data); - -void keyslot_manager_intersect_modes(struct keyslot_manager *parent, - const struct keyslot_manager *child); - -int keyslot_manager_derive_raw_secret(struct keyslot_manager *ksm, - const u8 *wrapped_key, - unsigned int wrapped_key_size, - u8 *secret, unsigned int secret_size); - -#endif /* CONFIG_BLK_INLINE_ENCRYPTION */ - -#endif /* __LINUX_KEYSLOT_MANAGER_H */ diff --git a/include/uapi/linux/fscrypt.h b/include/uapi/linux/fscrypt.h index 7d150d800abc..1beb174ad950 100644 --- a/include/uapi/linux/fscrypt.h +++ b/include/uapi/linux/fscrypt.h @@ -113,10 +113,7 @@ struct fscrypt_key_specifier { struct fscrypt_add_key_arg { struct fscrypt_key_specifier key_spec; __u32 raw_size; - __u32 __reserved[8]; - /* N.B.: "temporary" flag, not reserved upstream */ -#define __FSCRYPT_ADD_KEY_FLAG_HW_WRAPPED 0x00000001 - __u32 __flags; + __u32 __reserved[9]; __u8 raw[]; }; diff --git a/include/uapi/linux/incrementalfs.h b/include/uapi/linux/incrementalfs.h index 787049031cca..8a06e2e48fc4 100644 --- a/include/uapi/linux/incrementalfs.h +++ b/include/uapi/linux/incrementalfs.h @@ -22,9 +22,8 @@ #define INCFS_DATA_FILE_BLOCK_SIZE 4096 #define INCFS_HEADER_VER 1 -/* TODO: This value is assumed in incfs_copy_signature_info_from_user to be the - * actual signature length. Set back to 64 when fixed. - */ +// TODO: This value is assumed in incfs_copy_signature_info_from_user to be the +// actual signature length. Set back to 64 when fixed. #define INCFS_MAX_HASH_SIZE 32 #define INCFS_MAX_FILE_ATTR_SIZE 512 @@ -107,13 +106,10 @@ struct incfs_new_data_block { /* Values from enum incfs_block_flags */ __u8 flags; - /* Reserved - must be 0 */ __u16 reserved1; - /* Reserved - must be 0 */ __u32 reserved2; - /* Reserved - must be 0 */ __aligned_u64 reserved3; }; @@ -143,7 +139,6 @@ struct incfs_file_signature_info { /* Size of additional data. */ __u32 additional_data_size; - /* Reserved - must be 0 */ __u32 reserved1; /* @@ -157,7 +152,6 @@ struct incfs_file_signature_info { /* Size of pkcs7 signature DER blob */ __u32 signature_size; - /* Reserved - must be 0 */ __u32 reserved2; /* Value from incfs_hash_tree_algorithm */ @@ -181,10 +175,8 @@ struct incfs_new_file_args { */ __u16 mode; - /* Reserved - must be 0 */ __u16 reserved1; - /* Reserved - must be 0 */ __u32 reserved2; /* @@ -217,16 +209,13 @@ struct incfs_new_file_args { */ __u32 file_attr_len; - /* Reserved - must be 0 */ __u32 reserved4; /* struct incfs_file_signature_info *signature_info; */ __aligned_u64 signature_info; - /* Reserved - must be 0 */ __aligned_u64 reserved5; - /* Reserved - must be 0 */ __aligned_u64 reserved6; }; From 4d1b4d58d5b6db96088c1e10e93557ff9cf602f9 Mon Sep 17 00:00:00 2001 From: Shreyas K K Date: Mon, 20 Jul 2020 11:23:41 +0530 Subject: [PATCH 253/592] drivers: soc: sdx_ext_ipc: Fix devm_request_threaded_irq call Run sdx_ext_ipc_wakeup_irq in isr context and not in thread context. Change-Id: Ida0c6653c20ea20077881b30552f68929fdf1241 Signed-off-by: Shreyas K K --- drivers/soc/qcom/sdx_ext_ipc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/soc/qcom/sdx_ext_ipc.c b/drivers/soc/qcom/sdx_ext_ipc.c index c7a250ac9cf7..a4d0c35f9353 100644 --- a/drivers/soc/qcom/sdx_ext_ipc.c +++ b/drivers/soc/qcom/sdx_ext_ipc.c @@ -347,7 +347,7 @@ static int sdx_ext_ipc_probe(struct platform_device *pdev) if (mdm->gpios[WAKEUP_IN] >= 0) { ret = devm_request_threaded_irq(mdm->dev, mdm->wakeup_irq, - NULL, sdx_ext_ipc_wakeup_irq, + sdx_ext_ipc_wakeup_irq, NULL, IRQF_TRIGGER_FALLING, "sdx_ext_ipc_wakeup", mdm); if (ret < 0) { @@ -356,7 +356,6 @@ static int sdx_ext_ipc_probe(struct platform_device *pdev) __func__, mdm->wakeup_irq); goto irq_fail; } - disable_irq(mdm->wakeup_irq); } if (mdm->gpios[WAKEUP_OUT] >= 0) { From 975fd0628f2dc323f4ac0108526f8eb5f2deaeb4 Mon Sep 17 00:00:00 2001 From: Srinivasarao P Date: Mon, 27 Jul 2020 11:36:52 +0530 Subject: [PATCH 254/592] Reverting incremental fs changes e282124 ANDROID: Incremental fs: Fix issues with very large files b564958 ANDROID: Incremental fs: Add setattr call fdd560e ANDROID: Incremental fs: Use simple compression in log buffer 4f81903 ANDROID: Incremental fs: Fix create_file performance 3c76e8d ANDROID: Incremental fs: Fix compound page usercopy crash 3aee2b9 ANDROID: Incremental fs: Clean up incfs_test build process e158e20 ANDROID: Incremental fs: make remount log buffer change atomic 467d1f6 ANDROID: Incremental fs: Optimize get_filled_block 91ef6b6 ANDROID: Incremental fs: Fix mislabeled __user ptrs 1b7e2d0 ANDROID: Incremental fs: Use 64-bit int for file_size when writing hash blocks df76f38 Revert "ANDROID: Incremental fs: Fix initialization, use of bitfields" d73d0b4 ANDROID: Incremental fs: Fix remount ecd6f86 ANDROID: Incremental fs: Protect get_fill_block, and add a field 1a00062 ANDROID: Incremental fs: Fix crash polling 0 size read_log df5824e ANDROID: Incremental fs: get_filled_blocks: better index_out a4cad4e ANDROID: Incremental fs: Fix four resource bugs 76f5f1c ANDROID: Incremental fs: Add INCFS_IOC_GET_FILLED_BLOCKS 2d41ac8 ANDROID: Incremental fs: Fix two typos cb94ec7 ANDROID: Incremental fs: Add INCFS_IOC_PERMIT_FILL 758073b ANDROID: Incremental fs: Remove signature checks from kernel 8118f34 ANDROID: Incremental fs: Pad hash blocks dd3909c ANDROID: Incremental fs: Make fill block an ioctl 89e0905 ANDROID: Incremental fs: Remove all access_ok checks ee1d24d ANDROID: Incremental fs: Support xattrs Change-Id: Ib455db0ab788d08e968dcc665e2c9bd98c701b91 Signed-off-by: Srinivasarao P --- fs/incfs/data_mgmt.c | 688 ++++------- fs/incfs/data_mgmt.h | 126 +- fs/incfs/format.c | 126 +- fs/incfs/format.h | 67 +- fs/incfs/integrity.c | 183 ++- fs/incfs/integrity.h | 20 +- fs/incfs/vfs.c | 607 ++++------ include/uapi/linux/incrementalfs.h | 191 +-- .../selftests/filesystems/incfs/Makefile | 17 +- .../selftests/filesystems/incfs/config | 1 + .../selftests/filesystems/incfs/incfs_test.c | 1063 ++++++----------- .../selftests/filesystems/incfs/utils.c | 264 ++-- .../selftests/filesystems/incfs/utils.h | 36 +- 13 files changed, 1356 insertions(+), 2033 deletions(-) create mode 100644 tools/testing/selftests/filesystems/incfs/config diff --git a/fs/incfs/data_mgmt.c b/fs/incfs/data_mgmt.c index d9c43d5cca19..4698f14bbdf7 100644 --- a/fs/incfs/data_mgmt.c +++ b/fs/incfs/data_mgmt.c @@ -27,19 +27,28 @@ struct mount_info *incfs_alloc_mount_info(struct super_block *sb, return ERR_PTR(-ENOMEM); mi->mi_sb = sb; + mi->mi_options = *options; mi->mi_backing_dir_path = *backing_dir_path; mi->mi_owner = get_current_cred(); path_get(&mi->mi_backing_dir_path); mutex_init(&mi->mi_dir_struct_mutex); mutex_init(&mi->mi_pending_reads_mutex); init_waitqueue_head(&mi->mi_pending_reads_notif_wq); - init_waitqueue_head(&mi->mi_log.ml_notif_wq); - spin_lock_init(&mi->mi_log.rl_lock); INIT_LIST_HEAD(&mi->mi_reads_list_head); - error = incfs_realloc_mount_info(mi, options); - if (error) - goto err; + if (options->read_log_pages != 0) { + size_t buf_size = PAGE_SIZE * options->read_log_pages; + + spin_lock_init(&mi->mi_log.rl_writer_lock); + init_waitqueue_head(&mi->mi_log.ml_notif_wq); + + mi->mi_log.rl_size = buf_size / sizeof(*mi->mi_log.rl_ring_buf); + mi->mi_log.rl_ring_buf = kzalloc(buf_size, GFP_NOFS); + if (!mi->mi_log.rl_ring_buf) { + error = -ENOMEM; + goto err; + } + } return mi; @@ -48,47 +57,6 @@ err: return ERR_PTR(error); } -int incfs_realloc_mount_info(struct mount_info *mi, - struct mount_options *options) -{ - void *new_buffer = NULL; - void *old_buffer; - size_t new_buffer_size = 0; - - if (options->read_log_pages != mi->mi_options.read_log_pages) { - struct read_log_state log_state; - /* - * Even though having two buffers allocated at once isn't - * usually good, allocating a multipage buffer under a spinlock - * is even worse, so let's optimize for the shorter lock - * duration. It's not end of the world if we fail to increase - * the buffer size anyway. - */ - if (options->read_log_pages > 0) { - new_buffer_size = PAGE_SIZE * options->read_log_pages; - new_buffer = kzalloc(new_buffer_size, GFP_NOFS); - if (!new_buffer) - return -ENOMEM; - } - - spin_lock(&mi->mi_log.rl_lock); - old_buffer = mi->mi_log.rl_ring_buf; - mi->mi_log.rl_ring_buf = new_buffer; - mi->mi_log.rl_size = new_buffer_size; - log_state = (struct read_log_state){ - .generation_id = mi->mi_log.rl_head.generation_id + 1, - }; - mi->mi_log.rl_head = log_state; - mi->mi_log.rl_tail = log_state; - spin_unlock(&mi->mi_log.rl_lock); - - kfree(old_buffer); - } - - mi->mi_options = *options; - return 0; -} - void incfs_free_mount_info(struct mount_info *mi) { if (!mi) @@ -100,8 +68,6 @@ void incfs_free_mount_info(struct mount_info *mi) mutex_destroy(&mi->mi_pending_reads_mutex); put_cred(mi->mi_owner); kfree(mi->mi_log.rl_ring_buf); - kfree(mi->log_xattr); - kfree(mi->pending_read_xattr); kfree(mi); } @@ -119,11 +85,11 @@ static void data_file_segment_destroy(struct data_file_segment *segment) struct data_file *incfs_open_data_file(struct mount_info *mi, struct file *bf) { - struct data_file *df = NULL; - struct backing_file_context *bfc = NULL; + struct data_file *df; + struct backing_file_context *bfc; int md_records; u64 size; - int error = 0; + int error; int i; if (!bf || !mi) @@ -150,8 +116,8 @@ struct data_file *incfs_open_data_file(struct mount_info *mi, struct file *bf) error = mutex_lock_interruptible(&bfc->bc_mutex); if (error) goto out; - error = incfs_read_file_header(bfc, &df->df_metadata_off, &df->df_id, - &size, &df->df_header_flags); + error = incfs_read_file_header(bfc, &df->df_metadata_off, + &df->df_id, &size); mutex_unlock(&bfc->bc_mutex); if (error) @@ -159,7 +125,7 @@ struct data_file *incfs_open_data_file(struct mount_info *mi, struct file *bf) df->df_size = size; if (size > 0) - df->df_data_block_count = get_blocks_count_for_size(size); + df->df_block_count = get_blocks_count_for_size(size); md_records = incfs_scan_metadata_chain(df); if (md_records < 0) @@ -194,7 +160,7 @@ int make_inode_ready_for_data_ops(struct mount_info *mi, struct file *backing_file) { struct inode_info *node = get_incfs_node(inode); - struct data_file *df = NULL; + struct data_file *df; int err = 0; inode_lock(inode); @@ -215,7 +181,7 @@ int make_inode_ready_for_data_ops(struct mount_info *mi, struct dir_file *incfs_open_dir_file(struct mount_info *mi, struct file *bf) { - struct dir_file *dir = NULL; + struct dir_file *dir; if (!S_ISDIR(bf->f_inode->i_mode)) return ERR_PTR(-EBADF); @@ -248,120 +214,33 @@ static ssize_t decompress(struct mem_range src, struct mem_range dst) return result; } -static void log_read_one_record(struct read_log *rl, struct read_log_state *rs) -{ - union log_record *record = - (union log_record *)((u8 *)rl->rl_ring_buf + rs->next_offset); - size_t record_size; - - switch (record->full_record.type) { - case FULL: - rs->base_record = record->full_record; - record_size = sizeof(record->full_record); - break; - - case SAME_FILE: - rs->base_record.block_index = - record->same_file_record.block_index; - rs->base_record.absolute_ts_us += - record->same_file_record.relative_ts_us; - record_size = sizeof(record->same_file_record); - break; - - case SAME_FILE_NEXT_BLOCK: - ++rs->base_record.block_index; - rs->base_record.absolute_ts_us += - record->same_file_next_block.relative_ts_us; - record_size = sizeof(record->same_file_next_block); - break; - - case SAME_FILE_NEXT_BLOCK_SHORT: - ++rs->base_record.block_index; - rs->base_record.absolute_ts_us += - record->same_file_next_block_short.relative_ts_us; - record_size = sizeof(record->same_file_next_block_short); - break; - } - - rs->next_offset += record_size; - if (rs->next_offset > rl->rl_size - sizeof(*record)) { - rs->next_offset = 0; - ++rs->current_pass_no; - } - ++rs->current_record_no; -} - static void log_block_read(struct mount_info *mi, incfs_uuid_t *id, - int block_index) + int block_index, bool timed_out) { struct read_log *log = &mi->mi_log; - struct read_log_state *head, *tail; + struct read_log_state state; s64 now_us = ktime_to_us(ktime_get()); - s64 relative_us; - union log_record record; - size_t record_size; + struct read_log_record record = { + .file_id = *id, + .timestamp_us = now_us + }; - spin_lock(&log->rl_lock); - if (log->rl_size == 0) { - spin_unlock(&log->rl_lock); + set_block_index(&record, block_index); + set_timed_out(&record, timed_out); + + if (log->rl_size == 0) return; + + spin_lock(&log->rl_writer_lock); + state = READ_ONCE(log->rl_state); + log->rl_ring_buf[state.next_index] = record; + if (++state.next_index == log->rl_size) { + state.next_index = 0; + ++state.current_pass_no; } + WRITE_ONCE(log->rl_state, state); + spin_unlock(&log->rl_writer_lock); - head = &log->rl_head; - tail = &log->rl_tail; - relative_us = now_us - head->base_record.absolute_ts_us; - - if (memcmp(id, &head->base_record.file_id, sizeof(incfs_uuid_t)) || - relative_us >= 1ll << 32) { - record.full_record = (struct full_record){ - .type = FULL, - .block_index = block_index, - .file_id = *id, - .absolute_ts_us = now_us, - }; - record_size = sizeof(struct full_record); - } else if (block_index != head->base_record.block_index + 1 || - relative_us >= 1 << 30) { - record.same_file_record = (struct same_file_record){ - .type = SAME_FILE, - .block_index = block_index, - .relative_ts_us = relative_us, - }; - record_size = sizeof(struct same_file_record); - } else if (relative_us >= 1 << 14) { - record.same_file_next_block = (struct same_file_next_block){ - .type = SAME_FILE_NEXT_BLOCK, - .relative_ts_us = relative_us, - }; - record_size = sizeof(struct same_file_next_block); - } else { - record.same_file_next_block_short = - (struct same_file_next_block_short){ - .type = SAME_FILE_NEXT_BLOCK_SHORT, - .relative_ts_us = relative_us, - }; - record_size = sizeof(struct same_file_next_block_short); - } - - head->base_record.file_id = *id; - head->base_record.block_index = block_index; - head->base_record.absolute_ts_us = now_us; - - /* Advance tail beyond area we are going to overwrite */ - while (tail->current_pass_no < head->current_pass_no && - tail->next_offset < head->next_offset + record_size) - log_read_one_record(log, tail); - - memcpy(((u8 *)log->rl_ring_buf) + head->next_offset, &record, - record_size); - head->next_offset += record_size; - if (head->next_offset > log->rl_size - sizeof(record)) { - head->next_offset = 0; - ++head->current_pass_no; - } - ++head->current_record_no; - - spin_unlock(&log->rl_lock); wake_up_all(&log->ml_notif_wq); } @@ -370,7 +249,7 @@ static int validate_hash_tree(struct file *bf, struct data_file *df, { u8 digest[INCFS_MAX_HASH_SIZE] = {}; struct mtree *tree = NULL; - struct incfs_df_signature *sig = NULL; + struct ondisk_signature *sig = NULL; struct mem_range calc_digest_rng; struct mem_range saved_digest_rng; struct mem_range root_hash_rng; @@ -393,8 +272,8 @@ static int validate_hash_tree(struct file *bf, struct data_file *df, return res; for (lvl = 0; lvl < tree->depth; lvl++) { - loff_t lvl_off = - tree->hash_level_suboffset[lvl] + sig->hash_offset; + loff_t lvl_off = tree->hash_level_suboffset[lvl] + + sig->mtree_offset; loff_t hash_block_off = lvl_off + round_down(hash_block_index * digest_size, INCFS_DATA_FILE_BLOCK_SIZE); @@ -442,6 +321,72 @@ static int validate_hash_tree(struct file *bf, struct data_file *df, return 0; } +static int revalidate_signature(struct file *bf, struct data_file *df) +{ + struct ondisk_signature *sig = df->df_signature; + struct mem_range root_hash = {}; + int result = 0; + u8 *sig_buf = NULL; + u8 *add_data_buf = NULL; + ssize_t read_res; + + /* File has no signature. */ + if (!sig || !df->df_hash_tree || sig->sig_size == 0) + return 0; + + /* Signature has already been validated. */ + if (df->df_signature_validated) + return 0; + + add_data_buf = kzalloc(sig->add_data_size, GFP_NOFS); + if (!add_data_buf) { + result = -ENOMEM; + goto out; + } + + read_res = incfs_kread(bf, add_data_buf, sig->add_data_size, + sig->add_data_offset); + if (read_res < 0) { + result = read_res; + goto out; + } + if (read_res != sig->add_data_size) { + result = -EIO; + goto out; + } + + sig_buf = kzalloc(sig->sig_size, GFP_NOFS); + if (!sig_buf) { + result = -ENOMEM; + goto out; + } + + read_res = incfs_kread(bf, sig_buf, sig->sig_size, sig->sig_offset); + if (read_res < 0) { + result = read_res; + goto out; + } + if (read_res != sig->sig_size) { + result = -EIO; + goto out; + } + + root_hash = range(df->df_hash_tree->root_hash, + df->df_hash_tree->alg->digest_size); + + result = incfs_validate_pkcs7_signature( + range(sig_buf, sig->sig_size), + root_hash, + range(add_data_buf, sig->add_data_size)); + + if (result == 0) + df->df_signature_validated = true; +out: + kfree(sig_buf); + kfree(add_data_buf); + return result; +} + static struct data_file_segment *get_file_segment(struct data_file *df, int block_index) { @@ -456,28 +401,13 @@ static bool is_data_block_present(struct data_file_block *block) (block->db_stored_size != 0); } -static void convert_data_file_block(struct incfs_blockmap_entry *bme, - struct data_file_block *res_block) -{ - u16 flags = le16_to_cpu(bme->me_flags); - - res_block->db_backing_file_data_offset = - le16_to_cpu(bme->me_data_offset_hi); - res_block->db_backing_file_data_offset <<= 32; - res_block->db_backing_file_data_offset |= - le32_to_cpu(bme->me_data_offset_lo); - res_block->db_stored_size = le16_to_cpu(bme->me_data_size); - res_block->db_comp_alg = (flags & INCFS_BLOCK_COMPRESSED_LZ4) ? - COMPRESSION_LZ4 : - COMPRESSION_NONE; -} - static int get_data_file_block(struct data_file *df, int index, struct data_file_block *res_block) { struct incfs_blockmap_entry bme = {}; struct backing_file_context *bfc = NULL; loff_t blockmap_off = 0; + u16 flags = 0; int error = 0; if (!df || !res_block) @@ -486,184 +416,26 @@ static int get_data_file_block(struct data_file *df, int index, blockmap_off = df->df_blockmap_off; bfc = df->df_backing_file_context; - if (index < 0 || blockmap_off == 0) + if (index < 0 || index >= df->df_block_count || blockmap_off == 0) return -EINVAL; error = incfs_read_blockmap_entry(bfc, index, blockmap_off, &bme); if (error) return error; - convert_data_file_block(&bme, res_block); + flags = le16_to_cpu(bme.me_flags); + res_block->db_backing_file_data_offset = + le16_to_cpu(bme.me_data_offset_hi); + res_block->db_backing_file_data_offset <<= 32; + res_block->db_backing_file_data_offset |= + le32_to_cpu(bme.me_data_offset_lo); + res_block->db_stored_size = le16_to_cpu(bme.me_data_size); + res_block->db_comp_alg = (flags & INCFS_BLOCK_COMPRESSED_LZ4) ? + COMPRESSION_LZ4 : + COMPRESSION_NONE; return 0; } -static int check_room_for_one_range(u32 size, u32 size_out) -{ - if (size_out + sizeof(struct incfs_filled_range) > size) - return -ERANGE; - return 0; -} - -static int copy_one_range(struct incfs_filled_range *range, void __user *buffer, - u32 size, u32 *size_out) -{ - int error = check_room_for_one_range(size, *size_out); - if (error) - return error; - - if (copy_to_user(((char __user *)buffer) + *size_out, range, - sizeof(*range))) - return -EFAULT; - - *size_out += sizeof(*range); - return 0; -} - -static int update_file_header_flags(struct data_file *df, u32 bits_to_reset, - u32 bits_to_set) -{ - int result; - u32 new_flags; - struct backing_file_context *bfc; - - if (!df) - return -EFAULT; - bfc = df->df_backing_file_context; - if (!bfc) - return -EFAULT; - - result = mutex_lock_interruptible(&bfc->bc_mutex); - if (result) - return result; - - new_flags = (df->df_header_flags & ~bits_to_reset) | bits_to_set; - if (new_flags != df->df_header_flags) { - df->df_header_flags = new_flags; - result = incfs_write_file_header_flags(bfc, new_flags); - } - - mutex_unlock(&bfc->bc_mutex); - - return result; -} - -#define READ_BLOCKMAP_ENTRIES 512 -int incfs_get_filled_blocks(struct data_file *df, - struct incfs_get_filled_blocks_args *arg) -{ - int error = 0; - bool in_range = false; - struct incfs_filled_range range; - void __user *buffer = u64_to_user_ptr(arg->range_buffer); - u32 size = arg->range_buffer_size; - u32 end_index = - arg->end_index ? arg->end_index : df->df_total_block_count; - u32 *size_out = &arg->range_buffer_size_out; - int i = READ_BLOCKMAP_ENTRIES - 1; - int entries_read = 0; - struct incfs_blockmap_entry *bme; - - *size_out = 0; - if (end_index > df->df_total_block_count) - end_index = df->df_total_block_count; - arg->total_blocks_out = df->df_total_block_count; - arg->data_blocks_out = df->df_data_block_count; - - if (df->df_header_flags & INCFS_FILE_COMPLETE) { - pr_debug("File marked full, fast get_filled_blocks"); - if (arg->start_index > end_index) { - arg->index_out = arg->start_index; - return 0; - } - arg->index_out = arg->start_index; - - error = check_room_for_one_range(size, *size_out); - if (error) - return error; - - range = (struct incfs_filled_range){ - .begin = arg->start_index, - .end = end_index, - }; - - error = copy_one_range(&range, buffer, size, size_out); - if (error) - return error; - arg->index_out = end_index; - return 0; - } - - bme = kzalloc(sizeof(*bme) * READ_BLOCKMAP_ENTRIES, - GFP_NOFS | __GFP_COMP); - if (!bme) - return -ENOMEM; - - for (arg->index_out = arg->start_index; arg->index_out < end_index; - ++arg->index_out) { - struct data_file_block dfb; - - if (++i == READ_BLOCKMAP_ENTRIES) { - entries_read = incfs_read_blockmap_entries( - df->df_backing_file_context, bme, - arg->index_out, READ_BLOCKMAP_ENTRIES, - df->df_blockmap_off); - if (entries_read < 0) { - error = entries_read; - break; - } - - i = 0; - } - - if (i >= entries_read) { - error = -EIO; - break; - } - - convert_data_file_block(bme + i, &dfb); - - if (is_data_block_present(&dfb) == in_range) - continue; - - if (!in_range) { - error = check_room_for_one_range(size, *size_out); - if (error) - break; - in_range = true; - range.begin = arg->index_out; - } else { - range.end = arg->index_out; - error = copy_one_range(&range, buffer, size, size_out); - if (error) { - /* there will be another try out of the loop, - * it will reset the index_out if it fails too - */ - break; - } - in_range = false; - } - } - - if (in_range) { - range.end = arg->index_out; - error = copy_one_range(&range, buffer, size, size_out); - if (error) - arg->index_out = range.begin; - } - - if (!error && in_range && arg->start_index == 0 && - end_index == df->df_total_block_count && - *size_out == sizeof(struct incfs_filled_range)) { - int result = - update_file_header_flags(df, 0, INCFS_FILE_COMPLETE); - /* Log failure only, since it's just a failed optimization */ - pr_debug("Marked file full with result %d", result); - } - - kfree(bme); - return error; -} - static bool is_read_done(struct pending_read *read) { return atomic_read_acquire(&read->done) != 0; @@ -763,7 +535,7 @@ static int wait_for_data_block(struct data_file *df, int block_index, if (!df || !res_block) return -EFAULT; - if (block_index < 0 || block_index >= df->df_data_block_count) + if (block_index < 0 || block_index >= df->df_block_count) return -EINVAL; if (df->df_blockmap_off <= 0) @@ -794,7 +566,8 @@ static int wait_for_data_block(struct data_file *df, int block_index, mi = df->df_mount_info; if (timeout_ms == 0) { - log_block_read(mi, &df->df_id, block_index); + log_block_read(mi, &df->df_id, block_index, + true /*timed out*/); return -ETIME; } @@ -813,7 +586,8 @@ static int wait_for_data_block(struct data_file *df, int block_index, if (wait_res == 0) { /* Wait has timed out */ - log_block_read(mi, &df->df_id, block_index); + log_block_read(mi, &df->df_id, block_index, + true /*timed out*/); return -ETIME; } if (wait_res < 0) { @@ -908,15 +682,22 @@ ssize_t incfs_read_data_file_block(struct mem_range dst, struct data_file *df, result = err; } + if (result > 0) { + int err = revalidate_signature(bf, df); + + if (err < 0) + result = err; + } + if (result >= 0) - log_block_read(mi, &df->df_id, index); + log_block_read(mi, &df->df_id, index, false /*timed out*/); out: return result; } int incfs_process_new_data_block(struct data_file *df, - struct incfs_fill_block *block, u8 *data) + struct incfs_new_data_block *block, u8 *data) { struct mount_info *mi = NULL; struct backing_file_context *bfc = NULL; @@ -931,7 +712,7 @@ int incfs_process_new_data_block(struct data_file *df, bfc = df->df_backing_file_context; mi = df->df_mount_info; - if (block->block_index >= df->df_data_block_count) + if (block->block_index >= df->df_block_count) return -ERANGE; segment = get_file_segment(df, block->block_index); @@ -973,7 +754,7 @@ unlock: int incfs_read_file_signature(struct data_file *df, struct mem_range dst) { struct file *bf = df->df_backing_file_context->bc_file; - struct incfs_df_signature *sig; + struct ondisk_signature *sig; int read_res = 0; if (!dst.data) @@ -998,12 +779,12 @@ int incfs_read_file_signature(struct data_file *df, struct mem_range dst) } int incfs_process_new_hash_block(struct data_file *df, - struct incfs_fill_block *block, u8 *data) + struct incfs_new_data_block *block, u8 *data) { struct backing_file_context *bfc = NULL; struct mount_info *mi = NULL; struct mtree *hash_tree = NULL; - struct incfs_df_signature *sig = NULL; + struct ondisk_signature *sig = NULL; loff_t hash_area_base = 0; loff_t hash_area_size = 0; int error = 0; @@ -1022,11 +803,11 @@ int incfs_process_new_hash_block(struct data_file *df, hash_tree = df->df_hash_tree; sig = df->df_signature; - if (!hash_tree || !sig || sig->hash_offset == 0) + if (!hash_tree || !sig || sig->mtree_offset == 0) return -ENOTSUPP; - hash_area_base = sig->hash_offset; - hash_area_size = sig->hash_size; + hash_area_base = sig->mtree_offset; + hash_area_size = sig->mtree_size; if (hash_area_size < block->block_index * INCFS_DATA_FILE_BLOCK_SIZE + block->data_len) { /* Hash block goes beyond dedicated hash area of this file. */ @@ -1037,7 +818,7 @@ int incfs_process_new_hash_block(struct data_file *df, if (!error) error = incfs_write_hash_block_to_backing_file( bfc, range(data, block->data_len), block->block_index, - hash_area_base, df->df_blockmap_off, df->df_size); + hash_area_base); mutex_unlock(&bfc->bc_mutex); return error; } @@ -1053,10 +834,9 @@ static int process_blockmap_md(struct incfs_blockmap *bm, if (!df) return -EFAULT; - if (df->df_data_block_count > block_count) + if (df->df_block_count != block_count) return -EBADMSG; - df->df_total_block_count = block_count; df->df_blockmap_off = base_off; return error; } @@ -1085,69 +865,58 @@ static int process_file_signature_md(struct incfs_file_signature *sg, { struct data_file *df = handler->context; struct mtree *hash_tree = NULL; + struct ondisk_signature *signature = NULL; int error = 0; - struct incfs_df_signature *signature = - kzalloc(sizeof(*signature), GFP_NOFS); - void *buf = NULL; - ssize_t read; + loff_t base_tree_off = le64_to_cpu(sg->sg_hash_tree_offset); + u32 tree_size = le32_to_cpu(sg->sg_hash_tree_size); + loff_t sig_off = le64_to_cpu(sg->sg_sig_offset); + u32 sig_size = le32_to_cpu(sg->sg_sig_size); + loff_t add_data_off = le64_to_cpu(sg->sg_add_data_offset); + u32 add_data_size = le32_to_cpu(sg->sg_add_data_size); - if (!df || !df->df_backing_file_context || - !df->df_backing_file_context->bc_file) { - error = -ENOENT; - goto out; - } + if (!df) + return -ENOENT; - signature->hash_offset = le64_to_cpu(sg->sg_hash_tree_offset); - signature->hash_size = le32_to_cpu(sg->sg_hash_tree_size); - signature->sig_offset = le64_to_cpu(sg->sg_sig_offset); - signature->sig_size = le32_to_cpu(sg->sg_sig_size); - - buf = kzalloc(signature->sig_size, GFP_NOFS); - if (!buf) { + signature = kzalloc(sizeof(*signature), GFP_NOFS); + if (!signature) { error = -ENOMEM; goto out; } - read = incfs_kread(df->df_backing_file_context->bc_file, buf, - signature->sig_size, signature->sig_offset); - if (read < 0) { - error = read; - goto out; - } + signature->add_data_offset = add_data_off; + signature->add_data_size = add_data_size; + signature->sig_offset = sig_off; + signature->sig_size = sig_size; + signature->mtree_offset = base_tree_off; + signature->mtree_size = tree_size; - if (read != signature->sig_size) { - error = -EINVAL; - goto out; - } - - hash_tree = incfs_alloc_mtree(range(buf, signature->sig_size), - df->df_data_block_count); + hash_tree = incfs_alloc_mtree(sg->sg_hash_alg, df->df_block_count, + range(sg->sg_root_hash, sizeof(sg->sg_root_hash))); if (IS_ERR(hash_tree)) { error = PTR_ERR(hash_tree); hash_tree = NULL; goto out; } - if (hash_tree->hash_tree_area_size != signature->hash_size) { + if (hash_tree->hash_tree_area_size != tree_size) { error = -EINVAL; goto out; } - if (signature->hash_size > 0 && - handler->md_record_offset <= signature->hash_offset) { + if (tree_size > 0 && handler->md_record_offset <= base_tree_off) { error = -EINVAL; goto out; } - if (handler->md_record_offset <= signature->sig_offset) { + if (handler->md_record_offset <= signature->add_data_offset || + handler->md_record_offset <= signature->sig_offset) { error = -EINVAL; goto out; } df->df_hash_tree = hash_tree; - hash_tree = NULL; df->df_signature = signature; - signature = NULL; out: - incfs_free_mtree(hash_tree); - kfree(signature); - kfree(buf); + if (error) { + incfs_free_mtree(hash_tree); + kfree(signature); + } return error; } @@ -1203,17 +972,6 @@ int incfs_scan_metadata_chain(struct data_file *df) result = records_count; } mutex_unlock(&bfc->bc_mutex); - - if (df->df_hash_tree) { - int hash_block_count = get_blocks_count_for_size( - df->df_hash_tree->hash_tree_area_size); - - if (df->df_data_block_count + hash_block_count != - df->df_total_block_count) - result = -EINVAL; - } else if (df->df_data_block_count != df->df_total_block_count) - result = -EINVAL; - out: kfree(handler); return result; @@ -1279,29 +1037,36 @@ struct read_log_state incfs_get_log_state(struct mount_info *mi) struct read_log *log = &mi->mi_log; struct read_log_state result; - spin_lock(&log->rl_lock); - result = log->rl_head; - spin_unlock(&log->rl_lock); + spin_lock(&log->rl_writer_lock); + result = READ_ONCE(log->rl_state); + spin_unlock(&log->rl_writer_lock); return result; } +static u64 calc_record_count(const struct read_log_state *state, int rl_size) +{ + return state->current_pass_no * (u64)rl_size + state->next_index; +} + int incfs_get_uncollected_logs_count(struct mount_info *mi, - const struct read_log_state *state) + struct read_log_state state) { struct read_log *log = &mi->mi_log; - u32 generation; - u64 head_no, tail_no; - spin_lock(&log->rl_lock); - tail_no = log->rl_tail.current_record_no; - head_no = log->rl_head.current_record_no; - generation = log->rl_head.generation_id; - spin_unlock(&log->rl_lock); + u64 count = calc_record_count(&log->rl_state, log->rl_size) - + calc_record_count(&state, log->rl_size); + return min_t(int, count, log->rl_size); +} - if (generation != state->generation_id) - return head_no - tail_no; - else - return head_no - max_t(u64, tail_no, state->current_record_no); +static void fill_pending_read_from_log_record( + struct incfs_pending_read_info *dest, const struct read_log_record *src, + struct read_log_state *state, u64 log_size) +{ + dest->file_id = src->file_id; + dest->block_index = get_block_index(src); + dest->serial_number = + state->current_pass_no * log_size + state->next_index; + dest->timestamp_us = src->timestamp_us; } int incfs_collect_logged_reads(struct mount_info *mi, @@ -1309,47 +1074,58 @@ int incfs_collect_logged_reads(struct mount_info *mi, struct incfs_pending_read_info *reads, int reads_size) { - int dst_idx; struct read_log *log = &mi->mi_log; - struct read_log_state *head, *tail; + struct read_log_state live_state = incfs_get_log_state(mi); + u64 read_count = calc_record_count(reader_state, log->rl_size); + u64 written_count = calc_record_count(&live_state, log->rl_size); + int dst_idx; - spin_lock(&log->rl_lock); - head = &log->rl_head; - tail = &log->rl_tail; + if (reader_state->next_index >= log->rl_size || + read_count > written_count) + return -ERANGE; - if (reader_state->generation_id != head->generation_id) { - pr_debug("read ptr is wrong generation: %u/%u", - reader_state->generation_id, head->generation_id); + if (read_count == written_count) + return 0; - *reader_state = (struct read_log_state){ - .generation_id = head->generation_id, - }; + if (read_count > written_count) { + /* This reader is somehow ahead of the writer. */ + pr_debug("incfs: Log reader is ahead of writer\n"); + *reader_state = live_state; } - if (reader_state->current_record_no < tail->current_record_no) { - pr_debug("read ptr is behind, moving: %u/%u -> %u/%u\n", - (u32)reader_state->next_offset, - (u32)reader_state->current_pass_no, - (u32)tail->next_offset, (u32)tail->current_pass_no); + if (written_count - read_count > log->rl_size) { + /* + * Reading pointer is too far behind, + * start from the record following the write pointer. + */ + pr_debug("incfs: read pointer is behind, moving: %u/%u -> %u/%u / %u\n", + (u32)reader_state->next_index, + (u32)reader_state->current_pass_no, + (u32)live_state.next_index, + (u32)live_state.current_pass_no - 1, (u32)log->rl_size); - *reader_state = *tail; + *reader_state = (struct read_log_state){ + .next_index = live_state.next_index, + .current_pass_no = live_state.current_pass_no - 1, + }; } for (dst_idx = 0; dst_idx < reads_size; dst_idx++) { - if (reader_state->current_record_no == head->current_record_no) + if (reader_state->next_index == live_state.next_index && + reader_state->current_pass_no == live_state.current_pass_no) break; - log_read_one_record(log, reader_state); + fill_pending_read_from_log_record( + &reads[dst_idx], + &log->rl_ring_buf[reader_state->next_index], + reader_state, log->rl_size); - reads[dst_idx] = (struct incfs_pending_read_info){ - .file_id = reader_state->base_record.file_id, - .block_index = reader_state->base_record.block_index, - .serial_number = reader_state->current_record_no, - .timestamp_us = reader_state->base_record.absolute_ts_us - }; + reader_state->next_index++; + if (reader_state->next_index == log->rl_size) { + reader_state->next_index = 0; + reader_state->current_pass_no++; + } } - - spin_unlock(&log->rl_lock); return dst_idx; } diff --git a/fs/incfs/data_mgmt.h b/fs/incfs/data_mgmt.h index b7aecdd5bf4a..6722cef1608c 100644 --- a/fs/incfs/data_mgmt.h +++ b/fs/incfs/data_mgmt.h @@ -20,74 +20,63 @@ #define SEGMENTS_PER_FILE 3 -enum LOG_RECORD_TYPE { - FULL, - SAME_FILE, - SAME_FILE_NEXT_BLOCK, - SAME_FILE_NEXT_BLOCK_SHORT, -}; +struct read_log_record { + u32 bitfield; + + u64 timestamp_us; -struct full_record { - enum LOG_RECORD_TYPE type : 2; /* FULL */ - u32 block_index : 30; incfs_uuid_t file_id; - u64 absolute_ts_us; -} __packed; /* 28 bytes */ +} __packed; -struct same_file_record { - enum LOG_RECORD_TYPE type : 2; /* SAME_FILE */ - u32 block_index : 30; - u32 relative_ts_us; /* max 2^32 us ~= 1 hour (1:11:30) */ -} __packed; /* 12 bytes */ +#define RLR_BLOCK_INDEX_MASK 0x7fff +#define RLR_TIMED_OUT_MASK 0x8000 -struct same_file_next_block { - enum LOG_RECORD_TYPE type : 2; /* SAME_FILE_NEXT_BLOCK */ - u32 relative_ts_us : 30; /* max 2^30 us ~= 15 min (17:50) */ -} __packed; /* 4 bytes */ +static inline u32 get_block_index(const struct read_log_record *rlr) +{ + return rlr->bitfield & RLR_BLOCK_INDEX_MASK; +} -struct same_file_next_block_short { - enum LOG_RECORD_TYPE type : 2; /* SAME_FILE_NEXT_BLOCK_SHORT */ - u16 relative_ts_us : 14; /* max 2^14 us ~= 16 ms */ -} __packed; /* 2 bytes */ +static inline void set_block_index(struct read_log_record *rlr, + u32 block_index) +{ + rlr->bitfield = (rlr->bitfield & ~RLR_BLOCK_INDEX_MASK) + | (block_index & RLR_BLOCK_INDEX_MASK); +} -union log_record { - struct full_record full_record; - struct same_file_record same_file_record; - struct same_file_next_block same_file_next_block; - struct same_file_next_block_short same_file_next_block_short; -}; +static inline bool get_timed_out(const struct read_log_record *rlr) +{ + return (rlr->bitfield & RLR_TIMED_OUT_MASK) == RLR_TIMED_OUT_MASK; +} + +static inline void set_timed_out(struct read_log_record *rlr, bool timed_out) +{ + if (timed_out) + rlr->bitfield |= RLR_TIMED_OUT_MASK; + else + rlr->bitfield &= ~RLR_TIMED_OUT_MASK; +} struct read_log_state { - /* Log buffer generation id, incremented on configuration changes */ - u32 generation_id; + /* Next slot in rl_ring_buf to write to. */ + u32 next_index; - /* Offset in rl_ring_buf to write into. */ - u32 next_offset; - - /* Current number of writer passes over rl_ring_buf */ + /* Current number of writer pass over rl_ring_buf */ u32 current_pass_no; - - /* Current full_record to diff against */ - struct full_record base_record; - - /* Current record number counting from configuration change */ - u64 current_record_no; }; /* A ring buffer to save records about data blocks which were recently read. */ struct read_log { - void *rl_ring_buf; + struct read_log_record *rl_ring_buf; + + struct read_log_state rl_state; + + spinlock_t rl_writer_lock; int rl_size; - struct read_log_state rl_head; - - struct read_log_state rl_tail; - - /* A lock to protect the above fields */ - spinlock_t rl_lock; - - /* A queue of waiters who want to be notified about reads */ + /* + * A queue of waiters who want to be notified about reads. + */ wait_queue_head_t ml_notif_wq; }; @@ -142,12 +131,6 @@ struct mount_info { /* Temporary buffer for read logger. */ struct read_log mi_log; - - void *log_xattr; - size_t log_xattr_size; - - void *pending_read_xattr; - size_t pending_read_xattr_size; }; struct data_file_block { @@ -220,20 +203,16 @@ struct data_file { /* File size in bytes */ loff_t df_size; - /* File header flags */ - u32 df_header_flags; - - /* File size in DATA_FILE_BLOCK_SIZE blocks */ - int df_data_block_count; - - /* Total number of blocks, data + hash */ - int df_total_block_count; + int df_block_count; /* File size in DATA_FILE_BLOCK_SIZE blocks */ struct file_attr n_attr; struct mtree *df_hash_tree; - struct incfs_df_signature *df_signature; + struct ondisk_signature *df_signature; + + /* True, if file signature has already been validated. */ + bool df_signature_validated; }; struct dir_file { @@ -260,9 +239,6 @@ struct mount_info *incfs_alloc_mount_info(struct super_block *sb, struct mount_options *options, struct path *backing_dir_path); -int incfs_realloc_mount_info(struct mount_info *mi, - struct mount_options *options); - void incfs_free_mount_info(struct mount_info *mi); struct data_file *incfs_open_data_file(struct mount_info *mi, struct file *bf); @@ -277,16 +253,14 @@ ssize_t incfs_read_data_file_block(struct mem_range dst, struct data_file *df, int index, int timeout_ms, struct mem_range tmp); -int incfs_get_filled_blocks(struct data_file *df, - struct incfs_get_filled_blocks_args *arg); - int incfs_read_file_signature(struct data_file *df, struct mem_range dst); int incfs_process_new_data_block(struct data_file *df, - struct incfs_fill_block *block, u8 *data); + struct incfs_new_data_block *block, u8 *data); int incfs_process_new_hash_block(struct data_file *df, - struct incfs_fill_block *block, u8 *data); + struct incfs_new_data_block *block, u8 *data); + bool incfs_fresh_pending_reads_exist(struct mount_info *mi, int last_number); @@ -305,7 +279,7 @@ int incfs_collect_logged_reads(struct mount_info *mi, int reads_size); struct read_log_state incfs_get_log_state(struct mount_info *mi); int incfs_get_uncollected_logs_count(struct mount_info *mi, - const struct read_log_state *state); + struct read_log_state state); static inline struct inode_info *get_incfs_node(struct inode *inode) { @@ -323,7 +297,7 @@ static inline struct inode_info *get_incfs_node(struct inode *inode) static inline struct data_file *get_incfs_data_file(struct file *f) { - struct inode_info *node = NULL; + struct inode_info *node; if (!f) return NULL; diff --git a/fs/incfs/format.c b/fs/incfs/format.c index c56e559b6893..db71f527cf36 100644 --- a/fs/incfs/format.c +++ b/fs/incfs/format.c @@ -13,7 +13,6 @@ #include #include "format.h" -#include "data_mgmt.h" struct backing_file_context *incfs_alloc_bfc(struct file *backing_file) { @@ -94,6 +93,7 @@ static int append_zeros(struct backing_file_context *bfc, size_t len) { loff_t file_size = 0; loff_t new_last_byte_offset = 0; + int res = 0; if (!bfc) return -EFAULT; @@ -110,18 +110,28 @@ static int append_zeros(struct backing_file_context *bfc, size_t len) */ file_size = incfs_get_end_offset(bfc->bc_file); new_last_byte_offset = file_size + len - 1; - return vfs_fallocate(bfc->bc_file, 0, new_last_byte_offset, 1); + res = vfs_fallocate(bfc->bc_file, 0, new_last_byte_offset, 1); + if (res) + return res; + + res = vfs_fsync_range(bfc->bc_file, file_size, file_size + len, 1); + return res; } static int write_to_bf(struct backing_file_context *bfc, const void *buf, - size_t count, loff_t pos) + size_t count, loff_t pos, bool sync) { - ssize_t res = incfs_kwrite(bfc->bc_file, buf, count, pos); + ssize_t res = 0; + res = incfs_kwrite(bfc->bc_file, buf, count, pos); if (res < 0) return res; if (res != count) return -EIO; + + if (sync) + return vfs_fsync_range(bfc->bc_file, pos, pos + count, 1); + return 0; } @@ -175,7 +185,7 @@ static int append_md_to_backing_file(struct backing_file_context *bfc, /* Write the metadata record to the end of the backing file */ record_offset = file_pos; new_md_offset = cpu_to_le64(record_offset); - result = write_to_bf(bfc, record, record_size, file_pos); + result = write_to_bf(bfc, record, record_size, file_pos, true); if (result) return result; @@ -196,7 +206,7 @@ static int append_md_to_backing_file(struct backing_file_context *bfc, fh_first_md_offset); } result = write_to_bf(bfc, &new_md_offset, sizeof(new_md_offset), - file_pos); + file_pos, true); if (result) return result; @@ -204,22 +214,12 @@ static int append_md_to_backing_file(struct backing_file_context *bfc, return result; } -int incfs_write_file_header_flags(struct backing_file_context *bfc, u32 flags) -{ - if (!bfc) - return -EFAULT; - - return write_to_bf(bfc, &flags, sizeof(flags), - offsetof(struct incfs_file_header, - fh_file_header_flags)); -} - /* * Reserve 0-filled space for the blockmap body, and append * incfs_blockmap metadata record pointing to it. */ int incfs_write_blockmap_to_backing_file(struct backing_file_context *bfc, - u32 block_count) + u32 block_count, loff_t *map_base_off) { struct incfs_blockmap blockmap = {}; int result = 0; @@ -245,9 +245,12 @@ int incfs_write_blockmap_to_backing_file(struct backing_file_context *bfc, /* Write blockmap metadata record pointing to the body written above. */ blockmap.m_base_offset = cpu_to_le64(file_end); result = append_md_to_backing_file(bfc, &blockmap.m_header); - if (result) + if (result) { /* Error, rollback file changes */ truncate_backing_file(bfc, file_end); + } else if (map_base_off) { + *map_base_off = file_end; + } return result; } @@ -280,7 +283,7 @@ int incfs_write_file_attr_to_backing_file(struct backing_file_context *bfc, file_attr.fa_offset = cpu_to_le64(value_offset); file_attr.fa_crc = cpu_to_le32(crc); - result = write_to_bf(bfc, value.data, value.len, value_offset); + result = write_to_bf(bfc, value.data, value.len, value_offset, true); if (result) return result; @@ -296,7 +299,9 @@ int incfs_write_file_attr_to_backing_file(struct backing_file_context *bfc, } int incfs_write_signature_to_backing_file(struct backing_file_context *bfc, - struct mem_range sig, u32 tree_size) + u8 hash_alg, u32 tree_size, + struct mem_range root_hash, struct mem_range add_data, + struct mem_range sig) { struct incfs_file_signature sg = {}; int result = 0; @@ -306,6 +311,8 @@ int incfs_write_signature_to_backing_file(struct backing_file_context *bfc, if (!bfc) return -EFAULT; + if (root_hash.len > sizeof(sg.sg_root_hash)) + return -E2BIG; LOCK_REQUIRED(bfc->bc_mutex); @@ -314,19 +321,32 @@ int incfs_write_signature_to_backing_file(struct backing_file_context *bfc, sg.sg_header.h_md_entry_type = INCFS_MD_SIGNATURE; sg.sg_header.h_record_size = cpu_to_le16(sizeof(sg)); sg.sg_header.h_next_md_offset = cpu_to_le64(0); + sg.sg_hash_alg = hash_alg; if (sig.data != NULL && sig.len > 0) { loff_t pos = incfs_get_end_offset(bfc->bc_file); sg.sg_sig_size = cpu_to_le32(sig.len); sg.sg_sig_offset = cpu_to_le64(pos); - result = write_to_bf(bfc, sig.data, sig.len, pos); + result = write_to_bf(bfc, sig.data, sig.len, pos, false); + if (result) + goto err; + } + + if (add_data.len > 0) { + loff_t pos = incfs_get_end_offset(bfc->bc_file); + + sg.sg_add_data_size = cpu_to_le32(add_data.len); + sg.sg_add_data_offset = cpu_to_le64(pos); + + result = write_to_bf(bfc, add_data.data, + add_data.len, pos, false); if (result) goto err; } tree_area_pos = incfs_get_end_offset(bfc->bc_file); - if (tree_size > 0) { + if (hash_alg && tree_size > 0) { if (tree_size > 5 * INCFS_DATA_FILE_BLOCK_SIZE) { /* * If hash tree is big enough, it makes sense to @@ -349,13 +369,15 @@ int incfs_write_signature_to_backing_file(struct backing_file_context *bfc, sg.sg_hash_tree_size = cpu_to_le32(tree_size); sg.sg_hash_tree_offset = cpu_to_le64(tree_area_pos); } + memcpy(sg.sg_root_hash, root_hash.data, root_hash.len); /* Write a hash tree metadata record pointing to the hash tree above. */ result = append_md_to_backing_file(bfc, &sg.sg_header); err: - if (result) + if (result) { /* Error, rollback file changes */ truncate_backing_file(bfc, rollback_pos); + } return result; } @@ -389,7 +411,7 @@ int incfs_write_fh_to_backing_file(struct backing_file_context *bfc, if (file_pos != 0) return -EEXIST; - return write_to_bf(bfc, &fh, sizeof(fh), file_pos); + return write_to_bf(bfc, &fh, sizeof(fh), file_pos, true); } /* Write a given data block and update file's blockmap to point it. */ @@ -418,7 +440,7 @@ int incfs_write_data_block_to_backing_file(struct backing_file_context *bfc, } /* Write the block data at the end of the backing file. */ - result = write_to_bf(bfc, block.data, block.len, data_offset); + result = write_to_bf(bfc, block.data, block.len, data_offset, false); if (result) return result; @@ -428,25 +450,18 @@ int incfs_write_data_block_to_backing_file(struct backing_file_context *bfc, bm_entry.me_data_size = cpu_to_le16((u16)block.len); bm_entry.me_flags = cpu_to_le16(flags); - return write_to_bf(bfc, &bm_entry, sizeof(bm_entry), - bm_entry_off); + result = write_to_bf(bfc, &bm_entry, sizeof(bm_entry), + bm_entry_off, false); + return result; } int incfs_write_hash_block_to_backing_file(struct backing_file_context *bfc, - struct mem_range block, - int block_index, - loff_t hash_area_off, - loff_t bm_base_off, - loff_t file_size) + struct mem_range block, + int block_index, loff_t hash_area_off) { - struct incfs_blockmap_entry bm_entry = {}; - int result; loff_t data_offset = 0; loff_t file_end = 0; - loff_t bm_entry_off = - bm_base_off + - sizeof(struct incfs_blockmap_entry) * - (block_index + get_blocks_count_for_size(file_size)); + if (!bfc) return -EFAULT; @@ -460,16 +475,7 @@ int incfs_write_hash_block_to_backing_file(struct backing_file_context *bfc, return -EINVAL; } - result = write_to_bf(bfc, block.data, block.len, data_offset); - if (result) - return result; - - bm_entry.me_data_offset_lo = cpu_to_le32((u32)data_offset); - bm_entry.me_data_offset_hi = cpu_to_le16((u16)(data_offset >> 32)); - bm_entry.me_data_size = cpu_to_le16(INCFS_DATA_FILE_BLOCK_SIZE); - bm_entry.me_flags = cpu_to_le16(INCFS_BLOCK_HASH); - - return write_to_bf(bfc, &bm_entry, sizeof(bm_entry), bm_entry_off); + return write_to_bf(bfc, block.data, block.len, data_offset, false); } /* Initialize a new image in a given backing file. */ @@ -499,19 +505,8 @@ int incfs_read_blockmap_entry(struct backing_file_context *bfc, int block_index, loff_t bm_base_off, struct incfs_blockmap_entry *bm_entry) { - int error = incfs_read_blockmap_entries(bfc, bm_entry, block_index, 1, - bm_base_off); - - if (error < 0) - return error; - - if (error == 0) - return -EIO; - - if (error != 1) - return -EFAULT; - - return 0; + return incfs_read_blockmap_entries(bfc, bm_entry, block_index, 1, + bm_base_off); } int incfs_read_blockmap_entries(struct backing_file_context *bfc, @@ -535,12 +530,15 @@ int incfs_read_blockmap_entries(struct backing_file_context *bfc, bm_entry_off); if (result < 0) return result; - return result / sizeof(*entries); + if (result < bytes_to_read) + return -EIO; + return 0; } + int incfs_read_file_header(struct backing_file_context *bfc, loff_t *first_md_off, incfs_uuid_t *uuid, - u64 *file_size, u32 *flags) + u64 *file_size) { ssize_t bytes_read = 0; struct incfs_file_header fh = {}; @@ -574,8 +572,6 @@ int incfs_read_file_header(struct backing_file_context *bfc, *uuid = fh.fh_uuid; if (file_size) *file_size = le64_to_cpu(fh.fh_file_size); - if (flags) - *flags = le32_to_cpu(fh.fh_file_header_flags); return 0; } diff --git a/fs/incfs/format.h b/fs/incfs/format.h index 1a83349bb2eb..a86881482e19 100644 --- a/fs/incfs/format.h +++ b/fs/incfs/format.h @@ -121,10 +121,6 @@ enum incfs_metadata_type { INCFS_MD_SIGNATURE = 3 }; -enum incfs_file_header_flags { - INCFS_FILE_COMPLETE = 1 << 0, -}; - /* Header included at the beginning of all metadata records on the disk. */ struct incfs_md_header { __u8 h_md_entry_type; @@ -163,8 +159,8 @@ struct incfs_file_header { /* INCFS_DATA_FILE_BLOCK_SIZE */ __le16 fh_data_block_size; - /* File flags, from incfs_file_header_flags */ - __le32 fh_file_header_flags; + /* Padding, also reserved for future use. */ + __le32 fh_dummy; /* Offset of the first metadata record */ __le64 fh_first_md_offset; @@ -182,7 +178,6 @@ struct incfs_file_header { enum incfs_block_map_entry_flags { INCFS_BLOCK_COMPRESSED_LZ4 = (1 << 0), - INCFS_BLOCK_HASH = (1 << 1), }; /* Block map entry pointing to an actual location of the data block. */ @@ -222,26 +217,26 @@ struct incfs_file_attr { __le32 fa_crc; } __packed; -/* Metadata record for file signature. Type = INCFS_MD_SIGNATURE */ +/* Metadata record for file attribute. Type = INCFS_MD_SIGNATURE */ struct incfs_file_signature { struct incfs_md_header sg_header; - __le32 sg_sig_size; /* The size of the signature. */ - - __le64 sg_sig_offset; /* Signature's offset in the backing file */ + __u8 sg_hash_alg; /* Value from incfs_hash_tree_algorithm */ __le32 sg_hash_tree_size; /* The size of the hash tree. */ __le64 sg_hash_tree_offset; /* Hash tree offset in the backing file */ -} __packed; -/* In memory version of above */ -struct incfs_df_signature { - u32 sig_size; - u64 sig_offset; - u32 hash_size; - u64 hash_offset; -}; + __u8 sg_root_hash[INCFS_MAX_HASH_SIZE]; + + __le32 sg_sig_size; /* The size of the pkcs7 signature. */ + + __le64 sg_sig_offset; /* pkcs7 signature's offset in the backing file */ + + __le32 sg_add_data_size; /* The size of the additional data. */ + + __le64 sg_add_data_offset; /* Additional data's offset */ +} __packed; /* State of the backing file. */ struct backing_file_context { @@ -258,6 +253,23 @@ struct backing_file_context { loff_t bc_last_md_record_offset; }; + +/* Backing file locations of things required for signature validation. */ +struct ondisk_signature { + + loff_t add_data_offset; /* Additional data's offset */ + + loff_t sig_offset; /* pkcs7 signature's offset in the backing file */ + + loff_t mtree_offset; /* Backing file offset of the hash tree. */ + + u32 add_data_size; /* The size of the additional data. */ + + u32 sig_size; /* The size of the pkcs7 signature. */ + + u32 mtree_size; /* The size of the hash tree. */ +}; + struct metadata_handler { loff_t md_record_offset; loff_t md_prev_record_offset; @@ -289,7 +301,7 @@ void incfs_free_bfc(struct backing_file_context *bfc); /* Writing stuff */ int incfs_write_blockmap_to_backing_file(struct backing_file_context *bfc, - u32 block_count); + u32 block_count, loff_t *map_base_off); int incfs_write_fh_to_backing_file(struct backing_file_context *bfc, incfs_uuid_t *uuid, u64 file_size); @@ -300,19 +312,16 @@ int incfs_write_data_block_to_backing_file(struct backing_file_context *bfc, u16 flags); int incfs_write_hash_block_to_backing_file(struct backing_file_context *bfc, - struct mem_range block, - int block_index, - loff_t hash_area_off, - loff_t bm_base_off, - loff_t file_size); + struct mem_range block, + int block_index, loff_t hash_area_off); int incfs_write_file_attr_to_backing_file(struct backing_file_context *bfc, struct mem_range value, struct incfs_file_attr *attr); int incfs_write_signature_to_backing_file(struct backing_file_context *bfc, - struct mem_range sig, u32 tree_size); - -int incfs_write_file_header_flags(struct backing_file_context *bfc, u32 flags); + u8 hash_alg, u32 tree_size, + struct mem_range root_hash, struct mem_range add_data, + struct mem_range sig); int incfs_make_empty_backing_file(struct backing_file_context *bfc, incfs_uuid_t *uuid, u64 file_size); @@ -320,7 +329,7 @@ int incfs_make_empty_backing_file(struct backing_file_context *bfc, /* Reading stuff */ int incfs_read_file_header(struct backing_file_context *bfc, loff_t *first_md_off, incfs_uuid_t *uuid, - u64 *file_size, u32 *flags); + u64 *file_size); int incfs_read_blockmap_entry(struct backing_file_context *bfc, int block_index, loff_t bm_base_off, diff --git a/fs/incfs/integrity.c b/fs/incfs/integrity.c index d049988ef037..feb212c38945 100644 --- a/fs/incfs/integrity.c +++ b/fs/incfs/integrity.c @@ -10,6 +10,70 @@ #include "integrity.h" +int incfs_validate_pkcs7_signature(struct mem_range pkcs7_blob, + struct mem_range root_hash, struct mem_range add_data) +{ + struct pkcs7_message *pkcs7 = NULL; + const void *data = NULL; + size_t data_len = 0; + const char *p; + int err; + + pkcs7 = pkcs7_parse_message(pkcs7_blob.data, pkcs7_blob.len); + if (IS_ERR(pkcs7)) { + pr_debug("PKCS#7 parsing error. ptr=%p size=%ld err=%ld\n", + pkcs7_blob.data, pkcs7_blob.len, -PTR_ERR(pkcs7)); + return PTR_ERR(pkcs7); + } + + err = pkcs7_get_content_data(pkcs7, &data, &data_len, NULL); + if (err || data_len == 0 || data == NULL) { + pr_debug("PKCS#7 message does not contain data\n"); + err = -EBADMSG; + goto out; + } + + if (root_hash.len == 0) { + pr_debug("Root hash is empty.\n"); + err = -EBADMSG; + goto out; + } + + if (data_len != root_hash.len + add_data.len) { + pr_debug("PKCS#7 data size doesn't match arguments.\n"); + err = -EKEYREJECTED; + goto out; + } + + p = data; + if (memcmp(p, root_hash.data, root_hash.len) != 0) { + pr_debug("Root hash mismatch.\n"); + err = -EKEYREJECTED; + goto out; + } + p += root_hash.len; + if (memcmp(p, add_data.data, add_data.len) != 0) { + pr_debug("Additional data mismatch.\n"); + err = -EKEYREJECTED; + goto out; + } + + err = pkcs7_verify(pkcs7, VERIFYING_UNSPECIFIED_SIGNATURE); + if (err) + pr_debug("PKCS#7 signature verification error: %d\n", -err); + + /* + * RSA signature verification sometimes returns unexpected error codes + * when signature doesn't match. + */ + if (err == -ERANGE || err == -EINVAL) + err = -EBADMSG; + +out: + pkcs7_free_message(pkcs7); + return err; +} + struct incfs_hash_alg *incfs_get_hash_alg(enum incfs_hash_tree_algorithm id) { static struct incfs_hash_alg sha256 = { @@ -49,90 +113,11 @@ struct incfs_hash_alg *incfs_get_hash_alg(enum incfs_hash_tree_algorithm id) return result; } -struct signature_info { - u32 version; - enum incfs_hash_tree_algorithm hash_algorithm; - u8 log2_blocksize; - struct mem_range salt; - struct mem_range root_hash; -}; -static bool read_u32(u8 **p, u8 *top, u32 *result) +struct mtree *incfs_alloc_mtree(enum incfs_hash_tree_algorithm id, + int data_block_count, + struct mem_range root_hash) { - if (*p + sizeof(u32) > top) - return false; - - *result = le32_to_cpu(*(__le32 *)*p); - *p += sizeof(u32); - return true; -} - -static bool read_u8(u8 **p, u8 *top, u8 *result) -{ - if (*p + sizeof(u8) > top) - return false; - - *result = *(u8 *)*p; - *p += sizeof(u8); - return true; -} - -static bool read_mem_range(u8 **p, u8 *top, struct mem_range *range) -{ - u32 len; - - if (!read_u32(p, top, &len) || *p + len > top) - return false; - - range->len = len; - range->data = *p; - *p += len; - return true; -} - -static int incfs_parse_signature(struct mem_range signature, - struct signature_info *si) -{ - u8 *p = signature.data; - u8 *top = signature.data + signature.len; - u32 hash_section_size; - - if (signature.len > INCFS_MAX_SIGNATURE_SIZE) - return -EINVAL; - - if (!read_u32(&p, top, &si->version) || - si->version != INCFS_SIGNATURE_VERSION) - return -EINVAL; - - if (!read_u32(&p, top, &hash_section_size) || - p + hash_section_size > top) - return -EINVAL; - top = p + hash_section_size; - - if (!read_u32(&p, top, &si->hash_algorithm) || - si->hash_algorithm != INCFS_HASH_TREE_SHA256) - return -EINVAL; - - if (!read_u8(&p, top, &si->log2_blocksize) || si->log2_blocksize != 12) - return -EINVAL; - - if (!read_mem_range(&p, top, &si->salt)) - return -EINVAL; - - if (!read_mem_range(&p, top, &si->root_hash)) - return -EINVAL; - - if (p != top) - return -EINVAL; - - return 0; -} - -struct mtree *incfs_alloc_mtree(struct mem_range signature, - int data_block_count) -{ - int error; - struct signature_info si; struct mtree *result = NULL; struct incfs_hash_alg *hash_alg = NULL; int hash_per_block; @@ -144,15 +129,11 @@ struct mtree *incfs_alloc_mtree(struct mem_range signature, if (data_block_count <= 0) return ERR_PTR(-EINVAL); - error = incfs_parse_signature(signature, &si); - if (error) - return ERR_PTR(error); - - hash_alg = incfs_get_hash_alg(si.hash_algorithm); + hash_alg = incfs_get_hash_alg(id); if (IS_ERR(hash_alg)) return ERR_PTR(PTR_ERR(hash_alg)); - if (si.root_hash.len < hash_alg->digest_size) + if (root_hash.len < hash_alg->digest_size) return ERR_PTR(-EINVAL); result = kzalloc(sizeof(*result), GFP_NOFS); @@ -192,7 +173,7 @@ struct mtree *incfs_alloc_mtree(struct mem_range signature, } /* Root hash is stored separately from the rest of the tree. */ - memcpy(result->root_hash, si.root_hash.data, hash_alg->digest_size); + memcpy(result->root_hash, root_hash.data, hash_alg->digest_size); return result; err: @@ -217,20 +198,16 @@ int incfs_calc_digest(struct incfs_hash_alg *alg, struct mem_range data, return -EINVAL; desc->tfm = alg->shash; - - if (data.len < INCFS_DATA_FILE_BLOCK_SIZE) { - int err; - void *buf = kzalloc(INCFS_DATA_FILE_BLOCK_SIZE, GFP_NOFS); - - if (!buf) - return -ENOMEM; - - memcpy(buf, data.data, data.len); - err = crypto_shash_digest(desc, buf, INCFS_DATA_FILE_BLOCK_SIZE, - digest.data); - kfree(buf); - return err; - } return crypto_shash_digest(desc, data.data, data.len, digest.data); } +void incfs_free_signature_info(struct signature_info *si) +{ + if (!si) + return; + kfree(si->root_hash.data); + kfree(si->additional_data.data); + kfree(si->signature.data); + kfree(si); +} + diff --git a/fs/incfs/integrity.h b/fs/incfs/integrity.h index cf79b64da736..da1c38486b2f 100644 --- a/fs/incfs/integrity.h +++ b/fs/incfs/integrity.h @@ -38,10 +38,21 @@ struct mtree { int depth; }; +struct signature_info { + struct mem_range root_hash; + + struct mem_range additional_data; + + struct mem_range signature; + + enum incfs_hash_tree_algorithm hash_alg; +}; + struct incfs_hash_alg *incfs_get_hash_alg(enum incfs_hash_tree_algorithm id); -struct mtree *incfs_alloc_mtree(struct mem_range signature, - int data_block_count); +struct mtree *incfs_alloc_mtree(enum incfs_hash_tree_algorithm id, + int data_block_count, + struct mem_range root_hash); void incfs_free_mtree(struct mtree *tree); @@ -53,4 +64,9 @@ size_t incfs_get_mtree_hash_count(enum incfs_hash_tree_algorithm alg, int incfs_calc_digest(struct incfs_hash_alg *alg, struct mem_range data, struct mem_range digest); +int incfs_validate_pkcs7_signature(struct mem_range pkcs7_blob, + struct mem_range root_hash, struct mem_range add_data); + +void incfs_free_signature_info(struct signature_info *si); + #endif /* _INCFS_INTEGRITY_H */ diff --git a/fs/incfs/vfs.c b/fs/incfs/vfs.c index d2c82047dd7c..aebd2b02bd83 100644 --- a/fs/incfs/vfs.c +++ b/fs/incfs/vfs.c @@ -52,6 +52,8 @@ static int dir_rename(struct inode *old_dir, struct dentry *old_dentry, static int file_open(struct inode *inode, struct file *file); static int file_release(struct inode *inode, struct file *file); +static ssize_t file_write(struct file *f, const char __user *buf, + size_t size, loff_t *offset); static int read_single_page(struct file *f, struct page *page); static long dispatch_ioctl(struct file *f, unsigned int req, unsigned long arg); @@ -71,11 +73,8 @@ static struct inode *alloc_inode(struct super_block *sb); static void free_inode(struct inode *inode); static void evict_inode(struct inode *inode); -static int incfs_setattr(struct dentry *dentry, struct iattr *ia); static ssize_t incfs_getxattr(struct dentry *d, const char *name, void *value, size_t size); -static ssize_t incfs_setxattr(struct dentry *d, const char *name, - const void *value, size_t size, int flags); static ssize_t incfs_listxattr(struct dentry *d, char *list, size_t size); static int show_options(struct seq_file *, struct dentry *); @@ -102,8 +101,7 @@ static const struct inode_operations incfs_dir_inode_ops = { .rename = dir_rename_wrap, .unlink = dir_unlink, .link = dir_link, - .rmdir = dir_rmdir, - .setattr = incfs_setattr, + .rmdir = dir_rmdir }; static const struct file_operations incfs_dir_fops = { @@ -129,6 +127,7 @@ static const struct address_space_operations incfs_address_space_ops = { static const struct file_operations incfs_file_ops = { .open = file_open, .release = file_release, + .write = file_write, .read_iter = generic_file_read_iter, .mmap = generic_file_mmap, .splice_read = generic_file_splice_read, @@ -137,11 +136,6 @@ static const struct file_operations incfs_file_ops = { .compat_ioctl = dispatch_ioctl }; -enum FILL_PERMISSION { - CANT_FILL = 0, - CAN_FILL = 1, -}; - static const struct file_operations incfs_pending_read_file_ops = { .read = pending_reads_read, .poll = pending_reads_poll, @@ -163,7 +157,7 @@ static const struct file_operations incfs_log_file_ops = { }; static const struct inode_operations incfs_file_inode_ops = { - .setattr = incfs_setattr, + .setattr = simple_setattr, .getattr = simple_getattr, .listxattr = incfs_listxattr }; @@ -175,18 +169,9 @@ static int incfs_handler_getxattr(const struct xattr_handler *xh, return incfs_getxattr(d, name, buffer, size); } -static int incfs_handler_setxattr(const struct xattr_handler *xh, - struct dentry *d, struct inode *inode, - const char *name, const void *buffer, - size_t size, int flags) -{ - return incfs_setxattr(d, name, buffer, size, flags); -} - static const struct xattr_handler incfs_xattr_handler = { .prefix = "", /* AKA all attributes */ .get = incfs_handler_getxattr, - .set = incfs_handler_setxattr, }; static const struct xattr_handler *incfs_xattr_ops[] = { @@ -351,8 +336,8 @@ static int inode_test(struct inode *inode, void *opaque) return (node->n_backing_inode == backing_inode) && inode->i_ino == search->ino; - } else - return inode->i_ino == search->ino; + } + return 1; } static int inode_set(struct inode *inode, void *opaque) @@ -374,7 +359,6 @@ static int inode_set(struct inode *inode, void *opaque) inode->i_mapping->a_ops = &incfs_address_space_ops; inode->i_op = &incfs_file_inode_ops; inode->i_fop = &incfs_file_ops; - inode->i_mode &= ~0222; } else if (S_ISDIR(inode->i_mode)) { inode->i_size = 0; inode->i_blocks = 1; @@ -470,6 +454,9 @@ static ssize_t pending_reads_read(struct file *f, char __user *buf, size_t len, ssize_t result = 0; int i = 0; + if (!access_ok(VERIFY_WRITE, buf, len)) + return -EFAULT; + if (!incfs_fresh_pending_reads_exist(mi, last_known_read_sn)) return 0; @@ -587,27 +574,22 @@ static ssize_t log_read(struct file *f, char __user *buf, size_t len, { struct log_file_state *log_state = f->private_data; struct mount_info *mi = get_mount_info(file_superblock(f)); + struct incfs_pending_read_info *reads_buf = + (struct incfs_pending_read_info *)__get_free_page(GFP_NOFS); + size_t reads_to_collect = len / sizeof(*reads_buf); + size_t reads_per_page = PAGE_SIZE / sizeof(*reads_buf); int total_reads_collected = 0; - int rl_size; ssize_t result = 0; - struct incfs_pending_read_info *reads_buf; - ssize_t reads_to_collect = len / sizeof(*reads_buf); - ssize_t reads_per_page = PAGE_SIZE / sizeof(*reads_buf); - rl_size = READ_ONCE(mi->mi_log.rl_size); - if (rl_size == 0) - return 0; - - reads_buf = (struct incfs_pending_read_info *)__get_free_page(GFP_NOFS); if (!reads_buf) return -ENOMEM; - reads_to_collect = min_t(ssize_t, rl_size, reads_to_collect); + reads_to_collect = min_t(size_t, mi->mi_log.rl_size, reads_to_collect); while (reads_to_collect > 0) { struct read_log_state next_state = READ_ONCE(log_state->state); int reads_collected = incfs_collect_logged_reads( mi, &next_state, reads_buf, - min_t(ssize_t, reads_to_collect, reads_per_page)); + min_t(size_t, reads_to_collect, reads_per_page)); if (reads_collected <= 0) { result = total_reads_collected ? total_reads_collected * @@ -646,7 +628,7 @@ static __poll_t log_poll(struct file *file, poll_table *wait) __poll_t ret = 0; poll_wait(file, &mi->mi_log.ml_notif_wq, wait); - count = incfs_get_uncollected_logs_count(mi, &log_state->state); + count = incfs_get_uncollected_logs_count(mi, log_state->state); if (count >= mi->mi_options.read_log_wakeup_count) ret = EPOLLIN | EPOLLRDNORM; @@ -807,6 +789,9 @@ static int read_single_page(struct file *f, struct page *page) size = df->df_size; timeout_ms = df->df_mount_info->mi_options.read_timeout_ms; + pr_debug("incfs: %s %s %lld\n", __func__, + f->f_path.dentry->d_name.name, offset); + if (offset < size) { struct mem_range tmp = { .len = 2 * INCFS_DATA_FILE_BLOCK_SIZE @@ -853,39 +838,107 @@ static char *file_id_to_str(incfs_uuid_t id) return result; } -static struct mem_range incfs_copy_signature_info_from_user(u8 __user *original, - u64 size) +static struct signature_info *incfs_copy_signature_info_from_user( + struct incfs_file_signature_info __user *original) { - u8 *result; + struct incfs_file_signature_info usr_si; + struct signature_info *result; + int error; if (!original) - return range(NULL, 0); + return NULL; - if (size > INCFS_MAX_SIGNATURE_SIZE) - return range(ERR_PTR(-EFAULT), 0); + if (!access_ok(VERIFY_READ, original, sizeof(usr_si))) + return ERR_PTR(-EFAULT); - result = kzalloc(size, GFP_NOFS | __GFP_COMP); + if (copy_from_user(&usr_si, original, sizeof(usr_si)) > 0) + return ERR_PTR(-EFAULT); + + result = kzalloc(sizeof(*result), GFP_NOFS); if (!result) - return range(ERR_PTR(-ENOMEM), 0); + return ERR_PTR(-ENOMEM); - if (copy_from_user(result, original, size)) { - kfree(result); - return range(ERR_PTR(-EFAULT), 0); + result->hash_alg = usr_si.hash_tree_alg; + + if (result->hash_alg) { + void *p = kzalloc(INCFS_MAX_HASH_SIZE, GFP_NOFS); + + if (!p) { + error = -ENOMEM; + goto err; + } + + /* TODO this sets the root_hash length to MAX_HASH_SIZE not + * the actual size. Fix, then set INCFS_MAX_HASH_SIZE back + * to 64 + */ + result->root_hash = range(p, INCFS_MAX_HASH_SIZE); + if (copy_from_user(p, u64_to_user_ptr(usr_si.root_hash), + result->root_hash.len) > 0) { + error = -EFAULT; + goto err; + } } - return range(result, size); + if (usr_si.additional_data_size > INCFS_MAX_FILE_ATTR_SIZE) { + error = -E2BIG; + goto err; + } + + if (usr_si.additional_data && usr_si.additional_data_size) { + void *p = kzalloc(usr_si.additional_data_size, GFP_NOFS); + + if (!p) { + error = -ENOMEM; + goto err; + } + result->additional_data = range(p, + usr_si.additional_data_size); + if (copy_from_user(p, u64_to_user_ptr(usr_si.additional_data), + result->additional_data.len) > 0) { + error = -EFAULT; + goto err; + } + } + + if (usr_si.signature_size > INCFS_MAX_SIGNATURE_SIZE) { + error = -E2BIG; + goto err; + } + + if (usr_si.signature && usr_si.signature_size) { + void *p = kzalloc(usr_si.signature_size, GFP_NOFS); + + if (!p) { + error = -ENOMEM; + goto err; + } + result->signature = range(p, usr_si.signature_size); + if (copy_from_user(p, u64_to_user_ptr(usr_si.signature), + result->signature.len) > 0) { + error = -EFAULT; + goto err; + } + } + + return result; + +err: + incfs_free_signature_info(result); + return ERR_PTR(-error); } static int init_new_file(struct mount_info *mi, struct dentry *dentry, - incfs_uuid_t *uuid, u64 size, struct mem_range attr, - u8 __user *user_signature_info, u64 signature_size) + incfs_uuid_t *uuid, u64 size, struct mem_range attr, + struct incfs_file_signature_info __user *fsi) { struct path path = {}; struct file *new_file; int error = 0; struct backing_file_context *bfc = NULL; u32 block_count; - struct mem_range raw_signature = { NULL }; + struct mem_range mem_range = {NULL}; + struct signature_info *si = NULL; struct mtree *hash_tree = NULL; if (!mi || !dentry || !uuid) @@ -896,8 +949,7 @@ static int init_new_file(struct mount_info *mi, struct dentry *dentry, .mnt = mi->mi_backing_dir_path.mnt, .dentry = dentry }; - new_file = dentry_open(&path, O_RDWR | O_NOATIME | O_LARGEFILE, - mi->mi_owner); + new_file = dentry_open(&path, O_RDWR | O_NOATIME, mi->mi_owner); if (IS_ERR(new_file)) { error = PTR_ERR(new_file); @@ -905,7 +957,6 @@ static int init_new_file(struct mount_info *mi, struct dentry *dentry, } bfc = incfs_alloc_bfc(new_file); - fput(new_file); if (IS_ERR(bfc)) { error = PTR_ERR(bfc); bfc = NULL; @@ -917,6 +968,19 @@ static int init_new_file(struct mount_info *mi, struct dentry *dentry, if (error) goto out; + block_count = (u32)get_blocks_count_for_size(size); + error = incfs_write_blockmap_to_backing_file(bfc, block_count, NULL); + if (error) + goto out; + + /* This fill has data, reserve space for the block map. */ + if (block_count > 0) { + error = incfs_write_blockmap_to_backing_file( + bfc, block_count, NULL); + if (error) + goto out; + } + if (attr.data && attr.len) { error = incfs_write_file_attr_to_backing_file(bfc, attr, NULL); @@ -924,46 +988,54 @@ static int init_new_file(struct mount_info *mi, struct dentry *dentry, goto out; } - block_count = (u32)get_blocks_count_for_size(size); + if (fsi) { + si = incfs_copy_signature_info_from_user(fsi); - if (user_signature_info) { - raw_signature = incfs_copy_signature_info_from_user( - user_signature_info, signature_size); - - if (IS_ERR(raw_signature.data)) { - error = PTR_ERR(raw_signature.data); - raw_signature.data = NULL; + if (IS_ERR(si)) { + error = PTR_ERR(si); + si = NULL; goto out; } - hash_tree = incfs_alloc_mtree(raw_signature, block_count); - if (IS_ERR(hash_tree)) { - error = PTR_ERR(hash_tree); - hash_tree = NULL; - goto out; + if (si->hash_alg) { + hash_tree = incfs_alloc_mtree(si->hash_alg, block_count, + si->root_hash); + if (IS_ERR(hash_tree)) { + error = PTR_ERR(hash_tree); + hash_tree = NULL; + goto out; + } + + /* TODO This code seems wrong when len is zero - we + * should error out?? + */ + if (si->signature.len > 0) + error = incfs_validate_pkcs7_signature( + si->signature, + si->root_hash, + si->additional_data); + if (error) + goto out; + + error = incfs_write_signature_to_backing_file(bfc, + si->hash_alg, + hash_tree->hash_tree_area_size, + si->root_hash, si->additional_data, + si->signature); + + if (error) + goto out; } - - error = incfs_write_signature_to_backing_file( - bfc, raw_signature, hash_tree->hash_tree_area_size); - if (error) - goto out; - - block_count += get_blocks_count_for_size( - hash_tree->hash_tree_area_size); } - if (block_count) - error = incfs_write_blockmap_to_backing_file(bfc, block_count); - - if (error) - goto out; out: if (bfc) { mutex_unlock(&bfc->bc_mutex); incfs_free_bfc(bfc); } incfs_free_mtree(hash_tree); - kfree(raw_signature.data); + incfs_free_signature_info(si); + kfree(mem_range.data); if (error) pr_debug("incfs: %s error: %d\n", __func__, error); @@ -1108,7 +1180,10 @@ static long ioctl_create_file(struct mount_info *mi, error = -EFAULT; goto out; } - + if (!access_ok(VERIFY_READ, usr_args, sizeof(args))) { + error = -EFAULT; + goto out; + } if (copy_from_user(&args, usr_args, sizeof(args)) > 0) { error = -EFAULT; goto out; @@ -1221,7 +1296,7 @@ static long ioctl_create_file(struct mount_info *mi, goto delete_index_file; } - /* Save the file's attribute as an xattr */ + /* Save the file's attrubute as an xattr */ if (args.file_attr_len && args.file_attr) { if (args.file_attr_len > INCFS_MAX_FILE_ATTR_SIZE) { error = -E2BIG; @@ -1234,6 +1309,12 @@ static long ioctl_create_file(struct mount_info *mi, goto delete_index_file; } + if (!access_ok(VERIFY_READ, u64_to_user_ptr(args.file_attr), + args.file_attr_len)) { + error = -EFAULT; + goto delete_index_file; + } + if (copy_from_user(attr_value, u64_to_user_ptr(args.file_attr), args.file_attr_len) > 0) { @@ -1252,9 +1333,9 @@ static long ioctl_create_file(struct mount_info *mi, /* Initializing a newly created file. */ error = init_new_file(mi, index_file_dentry, &args.file_id, args.size, - range(attr_value, args.file_attr_len), - (u8 __user *)args.signature_info, - args.signature_size); + range(attr_value, args.file_attr_len), + (struct incfs_file_signature_info __user *) + args.signature_info); if (error) goto delete_index_file; @@ -1282,123 +1363,6 @@ out: return error; } -static long ioctl_fill_blocks(struct file *f, void __user *arg) -{ - struct incfs_fill_blocks __user *usr_fill_blocks = arg; - struct incfs_fill_blocks fill_blocks; - struct incfs_fill_block __user *usr_fill_block_array; - struct data_file *df = get_incfs_data_file(f); - const ssize_t data_buf_size = 2 * INCFS_DATA_FILE_BLOCK_SIZE; - u8 *data_buf = NULL; - ssize_t error = 0; - int i = 0; - - if (!df) - return -EBADF; - - if ((uintptr_t)f->private_data != CAN_FILL) - return -EPERM; - - if (copy_from_user(&fill_blocks, usr_fill_blocks, sizeof(fill_blocks))) - return -EFAULT; - - usr_fill_block_array = u64_to_user_ptr(fill_blocks.fill_blocks); - data_buf = (u8 *)__get_free_pages(GFP_NOFS | __GFP_COMP, - get_order(data_buf_size)); - if (!data_buf) - return -ENOMEM; - - for (i = 0; i < fill_blocks.count; i++) { - struct incfs_fill_block fill_block = {}; - - if (copy_from_user(&fill_block, &usr_fill_block_array[i], - sizeof(fill_block)) > 0) { - error = -EFAULT; - break; - } - - if (fill_block.data_len > data_buf_size) { - error = -E2BIG; - break; - } - - if (copy_from_user(data_buf, u64_to_user_ptr(fill_block.data), - fill_block.data_len) > 0) { - error = -EFAULT; - break; - } - fill_block.data = 0; /* To make sure nobody uses it. */ - if (fill_block.flags & INCFS_BLOCK_FLAGS_HASH) { - error = incfs_process_new_hash_block(df, &fill_block, - data_buf); - } else { - error = incfs_process_new_data_block(df, &fill_block, - data_buf); - } - if (error) - break; - } - - if (data_buf) - free_pages((unsigned long)data_buf, get_order(data_buf_size)); - - /* - * Only report the error if no records were processed, otherwise - * just return how many were processed successfully. - */ - if (i == 0) - return error; - - return i; -} - -static long ioctl_permit_fill(struct file *f, void __user *arg) -{ - struct incfs_permit_fill __user *usr_permit_fill = arg; - struct incfs_permit_fill permit_fill; - long error = 0; - struct file *file = NULL; - - if (f->f_op != &incfs_pending_read_file_ops) - return -EPERM; - - if (copy_from_user(&permit_fill, usr_permit_fill, sizeof(permit_fill))) - return -EFAULT; - - file = fget(permit_fill.file_descriptor); - if (IS_ERR(file)) - return PTR_ERR(file); - - if (file->f_op != &incfs_file_ops) { - error = -EPERM; - goto out; - } - - if (file->f_inode->i_sb != f->f_inode->i_sb) { - error = -EPERM; - goto out; - } - - switch ((uintptr_t)file->private_data) { - case CANT_FILL: - file->private_data = (void *)CAN_FILL; - break; - - case CAN_FILL: - pr_debug("CAN_FILL already set"); - break; - - default: - pr_warn("Invalid file private data"); - error = -EFAULT; - goto out; - } - -out: - fput(file); - return error; -} - static long ioctl_read_file_signature(struct file *f, void __user *arg) { struct incfs_get_file_sig_args __user *args_usr_ptr = arg; @@ -1412,14 +1376,20 @@ static long ioctl_read_file_signature(struct file *f, void __user *arg) if (!df) return -EINVAL; + if (!access_ok(VERIFY_READ, args_usr_ptr, sizeof(args))) + return -EFAULT; if (copy_from_user(&args, args_usr_ptr, sizeof(args)) > 0) return -EINVAL; + if (!access_ok(VERIFY_WRITE, u64_to_user_ptr(args.file_signature), + args.file_signature_buf_size)) + return -EFAULT; + sig_buf_size = args.file_signature_buf_size; if (sig_buf_size > INCFS_MAX_SIGNATURE_SIZE) return -E2BIG; - sig_buffer = kzalloc(sig_buf_size, GFP_NOFS | __GFP_COMP); + sig_buffer = kzalloc(sig_buf_size, GFP_NOFS); if (!sig_buffer) return -ENOMEM; @@ -1447,30 +1417,6 @@ out: return error; } -static long ioctl_get_filled_blocks(struct file *f, void __user *arg) -{ - struct incfs_get_filled_blocks_args __user *args_usr_ptr = arg; - struct incfs_get_filled_blocks_args args = {}; - struct data_file *df = get_incfs_data_file(f); - int error; - - if (!df) - return -EINVAL; - - if ((uintptr_t)f->private_data != CAN_FILL) - return -EPERM; - - if (copy_from_user(&args, args_usr_ptr, sizeof(args)) > 0) - return -EINVAL; - - error = incfs_get_filled_blocks(df, &args); - - if (copy_to_user(args_usr_ptr, &args, sizeof(args))) - return -EFAULT; - - return error; -} - static long dispatch_ioctl(struct file *f, unsigned int req, unsigned long arg) { struct mount_info *mi = get_mount_info(file_superblock(f)); @@ -1478,14 +1424,8 @@ static long dispatch_ioctl(struct file *f, unsigned int req, unsigned long arg) switch (req) { case INCFS_IOC_CREATE_FILE: return ioctl_create_file(mi, (void __user *)arg); - case INCFS_IOC_FILL_BLOCKS: - return ioctl_fill_blocks(f, (void __user *)arg); - case INCFS_IOC_PERMIT_FILL: - return ioctl_permit_fill(f, (void __user *)arg); case INCFS_IOC_READ_FILE_SIGNATURE: return ioctl_read_file_signature(f, (void __user *)arg); - case INCFS_IOC_GET_FILLED_BLOCKS: - return ioctl_get_filled_blocks(f, (void __user *)arg); default: return -EINVAL; } @@ -1692,7 +1632,6 @@ static int final_file_delete(struct mount_info *mi, if (d_really_is_positive(index_file_dentry)) error = incfs_unlink(index_file_dentry); out: - dput(index_file_dentry); if (error) pr_debug("incfs: delete_file_from_index err:%d\n", error); return error; @@ -1905,8 +1844,8 @@ static int file_open(struct inode *inode, struct file *file) int err = 0; get_incfs_backing_path(file->f_path.dentry, &backing_path); - backing_file = dentry_open( - &backing_path, O_RDWR | O_NOATIME | O_LARGEFILE, mi->mi_owner); + backing_file = dentry_open(&backing_path, O_RDWR | O_NOATIME, + mi->mi_owner); path_put(&backing_path); if (IS_ERR(backing_file)) { @@ -1915,10 +1854,9 @@ static int file_open(struct inode *inode, struct file *file) goto out; } - if (S_ISREG(inode->i_mode)) { + if (S_ISREG(inode->i_mode)) err = make_inode_ready_for_data_ops(mi, inode, backing_file); - file->private_data = (void *)CANT_FILL; - } else if (S_ISDIR(inode->i_mode)) { + else if (S_ISDIR(inode->i_mode)) { struct dir_file *dir = NULL; dir = incfs_open_dir_file(mi, backing_file); @@ -1953,6 +1891,77 @@ static int file_release(struct inode *inode, struct file *file) return 0; } +static ssize_t file_write(struct file *f, const char __user *buf, + size_t size, loff_t *offset) +{ + struct data_file *df = get_incfs_data_file(f); + const ssize_t data_buf_size = 2 * INCFS_DATA_FILE_BLOCK_SIZE; + size_t block_count = size / sizeof(struct incfs_new_data_block); + struct incfs_new_data_block __user *usr_blocks = + (struct incfs_new_data_block __user *)buf; + u8 *data_buf = NULL; + ssize_t error = 0; + int i = 0; + + if (!df) + return -EBADF; + + if (!access_ok(VERIFY_READ, usr_blocks, size)) + return -EFAULT; + + data_buf = (u8 *)__get_free_pages(GFP_NOFS, get_order(data_buf_size)); + if (!data_buf) + return -ENOMEM; + + for (i = 0; i < block_count; i++) { + struct incfs_new_data_block block = {}; + + if (copy_from_user(&block, &usr_blocks[i], sizeof(block)) > 0) { + error = -EFAULT; + break; + } + + if (block.data_len > data_buf_size) { + error = -E2BIG; + break; + } + if (!access_ok(VERIFY_READ, u64_to_user_ptr(block.data), + block.data_len)) { + error = -EFAULT; + break; + } + if (copy_from_user(data_buf, u64_to_user_ptr(block.data), + block.data_len) > 0) { + error = -EFAULT; + break; + } + block.data = 0; /* To make sure nobody uses it. */ + if (block.flags & INCFS_BLOCK_FLAGS_HASH) { + error = incfs_process_new_hash_block(df, &block, + data_buf); + } else { + error = incfs_process_new_data_block(df, &block, + data_buf); + } + if (error) + break; + } + + if (data_buf) + free_pages((unsigned long)data_buf, get_order(data_buf_size)); + *offset = 0; + + /* + * Only report the error if no records were processed, otherwise + * just return how many were processed successfully. + */ + if (i == 0) + return error; + + return i * sizeof(struct incfs_new_data_block); +} + + static int dentry_revalidate(struct dentry *d, unsigned int flags) { struct path backing_path = {}; @@ -1995,7 +2004,6 @@ static void dentry_release(struct dentry *d) if (di) path_put(&di->backing_path); - kfree(d->d_fsdata); d->d_fsdata = NULL; } @@ -2036,117 +2044,15 @@ static void evict_inode(struct inode *inode) clear_inode(inode); } -static int incfs_setattr(struct dentry *dentry, struct iattr *ia) -{ - struct dentry_info *di = get_incfs_dentry(dentry); - struct dentry *backing_dentry; - struct inode *backing_inode; - int error; - - if (ia->ia_valid & ATTR_SIZE) - return -EINVAL; - - if (!di) - return -EINVAL; - backing_dentry = di->backing_path.dentry; - if (!backing_dentry) - return -EINVAL; - - backing_inode = d_inode(backing_dentry); - - /* incfs files are readonly, but the backing files must be writeable */ - if (S_ISREG(backing_inode->i_mode)) { - if ((ia->ia_valid & ATTR_MODE) && (ia->ia_mode & 0222)) - return -EINVAL; - - ia->ia_mode |= 0222; - } - - inode_lock(d_inode(backing_dentry)); - error = notify_change(backing_dentry, ia, NULL); - inode_unlock(d_inode(backing_dentry)); - - if (error) - return error; - - if (S_ISREG(backing_inode->i_mode)) - ia->ia_mode &= ~0222; - - return simple_setattr(dentry, ia); -} - static ssize_t incfs_getxattr(struct dentry *d, const char *name, void *value, size_t size) { struct dentry_info *di = get_incfs_dentry(d); - struct mount_info *mi = get_mount_info(d->d_sb); - char *stored_value; - size_t stored_size; - if (di && di->backing_path.dentry) - return vfs_getxattr(di->backing_path.dentry, name, value, size); - - if (strcmp(name, "security.selinux")) + if (!di || !di->backing_path.dentry) return -ENODATA; - if (!strcmp(d->d_iname, INCFS_PENDING_READS_FILENAME)) { - stored_value = mi->pending_read_xattr; - stored_size = mi->pending_read_xattr_size; - } else if (!strcmp(d->d_iname, INCFS_LOG_FILENAME)) { - stored_value = mi->log_xattr; - stored_size = mi->log_xattr_size; - } else { - return -ENODATA; - } - - if (!stored_value) - return -ENODATA; - - if (stored_size > size) - return -E2BIG; - - memcpy(value, stored_value, stored_size); - return stored_size; - -} - - -static ssize_t incfs_setxattr(struct dentry *d, const char *name, - const void *value, size_t size, int flags) -{ - struct dentry_info *di = get_incfs_dentry(d); - struct mount_info *mi = get_mount_info(d->d_sb); - void **stored_value; - size_t *stored_size; - - if (di && di->backing_path.dentry) - return vfs_setxattr(di->backing_path.dentry, name, value, size, - flags); - - if (strcmp(name, "security.selinux")) - return -ENODATA; - - if (size > INCFS_MAX_FILE_ATTR_SIZE) - return -E2BIG; - - if (!strcmp(d->d_iname, INCFS_PENDING_READS_FILENAME)) { - stored_value = &mi->pending_read_xattr; - stored_size = &mi->pending_read_xattr_size; - } else if (!strcmp(d->d_iname, INCFS_LOG_FILENAME)) { - stored_value = &mi->log_xattr; - stored_size = &mi->log_xattr_size; - } else { - return -ENODATA; - } - - kfree (*stored_value); - *stored_value = kzalloc(size, GFP_NOFS); - if (!*stored_value) - return -ENOMEM; - - memcpy(*stored_value, value, size); - *stored_size = size; - return 0; + return vfs_getxattr(di->backing_path.dentry, name, value, size); } static ssize_t incfs_listxattr(struct dentry *d, char *list, size_t size) @@ -2246,7 +2152,7 @@ struct dentry *incfs_mount_fs(struct file_system_type *type, int flags, path_put(&backing_dir_path); sb->s_flags |= SB_ACTIVE; - pr_debug("incfs: mount\n"); + pr_debug("infs: mount\n"); return dget(sb->s_root); err: sb->s_fs_info = NULL; @@ -2267,11 +2173,12 @@ static int incfs_remount_fs(struct super_block *sb, int *flags, char *data) if (err) return err; - err = incfs_realloc_mount_info(mi, &options); - if (err) - return err; + if (mi->mi_options.read_timeout_ms != options.read_timeout_ms) { + mi->mi_options.read_timeout_ms = options.read_timeout_ms; + pr_debug("incfs: new timeout_ms=%d", options.read_timeout_ms); + } - pr_debug("incfs: remount\n"); + pr_debug("infs: remount\n"); return 0; } @@ -2279,7 +2186,7 @@ void incfs_kill_sb(struct super_block *sb) { struct mount_info *mi = sb->s_fs_info; - pr_debug("incfs: unmount\n"); + pr_debug("infs: unmount\n"); incfs_free_mount_info(mi); generic_shutdown_super(sb); } diff --git a/include/uapi/linux/incrementalfs.h b/include/uapi/linux/incrementalfs.h index 13c3d5173e14..787049031cca 100644 --- a/include/uapi/linux/incrementalfs.h +++ b/include/uapi/linux/incrementalfs.h @@ -35,8 +35,6 @@ #define INCFS_XATTR_METADATA_NAME (XATTR_USER_PREFIX "incfs.metadata") #define INCFS_MAX_SIGNATURE_SIZE 8096 -#define INCFS_SIGNATURE_VERSION 2 -#define INCFS_SIGNATURE_SECTIONS 2 #define INCFS_IOCTL_BASE_CODE 'g' @@ -48,49 +46,7 @@ /* Read file signature */ #define INCFS_IOC_READ_FILE_SIGNATURE \ - _IOR(INCFS_IOCTL_BASE_CODE, 31, struct incfs_get_file_sig_args) - -/* - * Fill in one or more data block. This may only be called on a handle - * passed as a parameter to INCFS_IOC_PERMIT_FILLING - * - * Returns number of blocks filled in, or error if none were - */ -#define INCFS_IOC_FILL_BLOCKS \ - _IOR(INCFS_IOCTL_BASE_CODE, 32, struct incfs_fill_blocks) - -/* - * Permit INCFS_IOC_FILL_BLOCKS on the given file descriptor - * May only be called on .pending_reads file - * - * Returns 0 on success or error - */ -#define INCFS_IOC_PERMIT_FILL \ - _IOW(INCFS_IOCTL_BASE_CODE, 33, struct incfs_permit_fill) - -/* - * Fills buffer with ranges of populated blocks - * - * Returns 0 if all ranges written - * error otherwise - * - * Either way, range_buffer_size_out is set to the number - * of bytes written. Should be set to 0 by caller. The ranges - * filled are valid, but if an error was returned there might - * be more ranges to come. - * - * Ranges are ranges of filled blocks: - * - * 1 2 7 9 - * - * means blocks 1, 2, 7, 8, 9 are filled, 0, 3, 4, 5, 6 and 10 on - * are not - * - * If hashing is enabled for the file, the hash blocks are simply - * treated as though they immediately followed the data blocks. - */ -#define INCFS_IOC_GET_FILLED_BLOCKS \ - _IOR(INCFS_IOCTL_BASE_CODE, 34, struct incfs_get_filled_blocks_args) + _IOWR(INCFS_IOCTL_BASE_CODE, 31, struct incfs_get_file_sig_args) enum incfs_compression_alg { COMPRESSION_NONE = 0, @@ -125,9 +81,10 @@ struct incfs_pending_read_info { }; /* - * Description of a data or hash block to add to a data file. + * A struct to be written into a control file to load a data or hash + * block to a data file. */ -struct incfs_fill_block { +struct incfs_new_data_block { /* Index of a data block. */ __u32 block_index; @@ -150,42 +107,63 @@ struct incfs_fill_block { /* Values from enum incfs_block_flags */ __u8 flags; + /* Reserved - must be 0 */ __u16 reserved1; + /* Reserved - must be 0 */ __u32 reserved2; + /* Reserved - must be 0 */ __aligned_u64 reserved3; }; -/* - * Description of a number of blocks to add to a data file - * - * Argument for INCFS_IOC_FILL_BLOCKS - */ -struct incfs_fill_blocks { - /* Number of blocks */ - __u64 count; - - /* A pointer to an array of incfs_fill_block structs */ - __aligned_u64 fill_blocks; -}; - -/* - * Permit INCFS_IOC_FILL_BLOCKS on the given file descriptor - * May only be called on .pending_reads file - * - * Argument for INCFS_IOC_PERMIT_FILL - */ -struct incfs_permit_fill { - /* File to permit fills on */ - __u32 file_descriptor; -}; - enum incfs_hash_tree_algorithm { INCFS_HASH_TREE_NONE = 0, INCFS_HASH_TREE_SHA256 = 1 }; +struct incfs_file_signature_info { + /* + * A pointer to file's root hash (if determined != 0) + * Actual hash size determined by hash_tree_alg. + * Size of the buffer should be at least INCFS_MAX_HASH_SIZE + * + * Equivalent to: u8 *root_hash; + */ + __aligned_u64 root_hash; + + /* + * A pointer to additional data that was attached to the root hash + * before signing. + * + * Equivalent to: u8 *additional_data; + */ + __aligned_u64 additional_data; + + /* Size of additional data. */ + __u32 additional_data_size; + + /* Reserved - must be 0 */ + __u32 reserved1; + + /* + * A pointer to pkcs7 signature DER blob. + * + * Equivalent to: u8 *signature; + */ + __aligned_u64 signature; + + + /* Size of pkcs7 signature DER blob */ + __u32 signature_size; + + /* Reserved - must be 0 */ + __u32 reserved2; + + /* Value from incfs_hash_tree_algorithm */ + __u8 hash_tree_alg; +}; + /* * Create a new file or directory. */ @@ -203,8 +181,10 @@ struct incfs_new_file_args { */ __u16 mode; + /* Reserved - must be 0 */ __u16 reserved1; + /* Reserved - must be 0 */ __u32 reserved2; /* @@ -237,33 +217,16 @@ struct incfs_new_file_args { */ __u32 file_attr_len; + /* Reserved - must be 0 */ __u32 reserved4; - /* - * Points to an APK V4 Signature data blob - * Signature must have two sections - * Format is: - * u32 version - * u32 size_of_hash_info_section - * u8 hash_info_section[] - * u32 size_of_signing_info_section - * u8 signing_info_section[] - * - * Note that incfs does not care about what is in signing_info_section - * - * hash_info_section has following format: - * u32 hash_algorithm; // Must be SHA256 == 1 - * u8 log2_blocksize; // Must be 12 for 4096 byte blocks - * u32 salt_size; - * u8 salt[]; - * u32 hash_size; - * u8 root_hash[]; - */ + /* struct incfs_file_signature_info *signature_info; */ __aligned_u64 signature_info; - /* Size of signature_info */ - __aligned_u64 signature_size; + /* Reserved - must be 0 */ + __aligned_u64 reserved5; + /* Reserved - must be 0 */ __aligned_u64 reserved6; }; @@ -289,46 +252,4 @@ struct incfs_get_file_sig_args { __u32 file_signature_len_out; }; -struct incfs_filled_range { - __u32 begin; - __u32 end; -}; - -/* - * Request ranges of filled blocks - * Argument for INCFS_IOC_GET_FILLED_BLOCKS - */ -struct incfs_get_filled_blocks_args { - /* - * A buffer to populate with ranges of filled blocks - * - * Equivalent to struct incfs_filled_ranges *range_buffer - */ - __aligned_u64 range_buffer; - - /* Size of range_buffer */ - __u32 range_buffer_size; - - /* Start index to read from */ - __u32 start_index; - - /* - * End index to read to. 0 means read to end. This is a range, - * so incfs will read from start_index to end_index - 1 - */ - __u32 end_index; - - /* Actual number of blocks in file */ - __u32 total_blocks_out; - - /* The number of data blocks in file */ - __u32 data_blocks_out; - - /* Number of bytes written to range buffer */ - __u32 range_buffer_size_out; - - /* Sector scanned up to, if the call was interrupted */ - __u32 index_out; -}; - #endif /* _UAPI_LINUX_INCREMENTALFS_H */ diff --git a/tools/testing/selftests/filesystems/incfs/Makefile b/tools/testing/selftests/filesystems/incfs/Makefile index 5b2e627ce883..1f13573d3617 100644 --- a/tools/testing/selftests/filesystems/incfs/Makefile +++ b/tools/testing/selftests/filesystems/incfs/Makefile @@ -1,11 +1,18 @@ # SPDX-License-Identifier: GPL-2.0 -CFLAGS += -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -Wall -CFLAGS += -I../.. -I../../../../.. +CFLAGS += -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -Wall -lssl -lcrypto -llz4 +CFLAGS += -I../../../../../usr/include/ +CFLAGS += -I../../../../include/uapi/ +CFLAGS += -I../../../../lib -LDLIBS := -llz4 -lcrypto EXTRA_SOURCES := utils.c +CFLAGS += $(EXTRA_SOURCES) + TEST_GEN_PROGS := incfs_test -$(TEST_GEN_PROGS): $(EXTRA_SOURCES) - include ../../lib.mk + +$(OUTPUT)incfs_test: incfs_test.c $(EXTRA_SOURCES) +all: $(OUTPUT)incfs_test + +clean: + rm -rf $(OUTPUT)incfs_test *.o diff --git a/tools/testing/selftests/filesystems/incfs/config b/tools/testing/selftests/filesystems/incfs/config new file mode 100644 index 000000000000..b6749837a318 --- /dev/null +++ b/tools/testing/selftests/filesystems/incfs/config @@ -0,0 +1 @@ +CONFIG_INCREMENTAL_FS=y \ No newline at end of file diff --git a/tools/testing/selftests/filesystems/incfs/incfs_test.c b/tools/testing/selftests/filesystems/incfs/incfs_test.c index 6809399eac97..dd70e019dc4c 100644 --- a/tools/testing/selftests/filesystems/incfs/incfs_test.c +++ b/tools/testing/selftests/filesystems/incfs/incfs_test.c @@ -2,31 +2,31 @@ /* * Copyright 2018 Google LLC */ -#include -#include -#include -#include -#include -#include -#include -#include #include -#include #include - -#include -#include #include +#include +#include +#include +#include +#include #include #include - +#include +#include +#include +#include +#include #include #include -#include +#include "../../kselftest.h" +#include "lz4.h" #include "utils.h" +#define __packed __attribute__((__packed__)) + #define TEST_FAILURE 1 #define TEST_SUCCESS 0 #define INCFS_MAX_MTREE_LEVELS 8 @@ -69,6 +69,101 @@ struct linux_dirent64 { char d_name[0]; } __packed; +/* + * The certificate below and the private key were created by calling: + * openssl req -x509 -newkey rsa:4096 -keyout private.key -out cert.crt + * -days 1000 -sha256 -nodes -outform PEM -subj + * "/C=US/ST=WA/L=Kirkland/O=Example/OU=Org/CN=www.example.com" + */ +char x509_cert[] = +"-----BEGIN CERTIFICATE-----\n" +"MIIFvzCCA6egAwIBAgIUXpwqelEljm6BBllRQGHLrls2MYgwDQYJKoZIhvcNAQEL\n" +"BQAwbzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xETAPBgNVBAcM\n" +"CEtpcmtsYW5kMRAwDgYDVQQKDAdFeGFtcGxlMQwwCgYDVQQLDANPcmcxGDAWBgNV\n" +"BAMMD3d3dy5leGFtcGxlLmNvbTAeFw0xOTA4MDgyMzA3MDZaFw0yMjA1MDQyMzA3\n" +"MDZaMG8xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMREwDwYDVQQH\n" +"DAhLaXJrbGFuZDEQMA4GA1UECgwHRXhhbXBsZTEMMAoGA1UECwwDT3JnMRgwFgYD\n" +"VQQDDA93d3cuZXhhbXBsZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK\n" +"AoICAQC1LuFW/lDV/GflqFMz7RDvFFgWld982ZuDJRaK55JNj+MI4RZNL61PDw43\n" +"NeeJtqUoVxSLS9wHURjSjD/CV5GudUOnzGfbwFlLko+jhYRT4HNFS+5ys1FEJLtA\n" +"uYcY4P9GHQEXYUX+ue82A2kJ91oY6G3vCQYJFiGteb6TRDICmug31x4pBfB8rOdt\n" +"4/NXS/Dn+S0/mJlxw34IKfqrlFjzUziRZtAWWqDcfxFDUizSggkdXIUq4GY38RAD\n" +"qGewNNCab3ClJDP7/M32BhSNgsIKhgtSTM2+ocfvBhwup+BjV6UbL21DPAshlolV\n" +"gSL1HM2jin5bi4bpFMreY0LXwFih87/6AVSfQHY9TZrombVZnMxvB7NG1NCSwDBT\n" +"qjjFb3oiSMugJzY+MhISM754m46fwUyHZ1ylWCLJEU8kQ5A1q9vvqMcaDa4uTGP3\n" +"UgC6SyVmZxG2o+AO6m8TRTCtqHN41mPTM9HK4T1UyuzVpykSc2LlYkKE517SyEiV\n" +"XDmotNb2myXNYHHTjRYNxkq75Lbii2I4Q4z8XtDngaIrhZqACKSqIt2CocGjx61S\n" +"oxKWi+LGa7B4NaCMjz1LnaOIsXn1rJDRnUWL49T42g4kOi/5QaC2JDygfefw1hAb\n" +"uxkq9EYUDg+w9broltiBf4rKAnw8JMySARnyPZbj0lhZK3va5wIDAQABo1MwUTAd\n" +"BgNVHQ4EFgQUo6JN3gY2yGbzOTNj8Al7hNB3rw0wHwYDVR0jBBgwFoAUo6JN3gY2\n" +"yGbzOTNj8Al7hNB3rw0wDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC\n" +"AgEAQb3pJqOzM4whfNVdpEOswd1EApcWNM1ps9iTlEEjDoRv9F7F1PW0uXCIpk3B\n" +"j5JgCmIxAcPnzj42rduRSx421hHMZhbAIWI/JL4ZSF64qlG0YrmJDXlJgSMoyst5\n" +"biUqeWgO7Js5udPt3zhkeA62z3hGM6dE5B3k7gHTaKKtK17+UeR9imZKsOK8GBnM\n" +"rxMPI6XghxxAK2OQ/r09DHDiyf/GxgOE46oknfXfMPx3HaSvDKrZUTZ+UvVbM5c2\n" +"5eXOgH5UO/e4llLknJK7CoP/R6G7pV44iT4t4t9FMnvCYvavAHwfR+6z5vTF3o8a\n" +"wd80fC8z1vfLsIPLROdzBl9rGCvv536fPiEA677CM1AZkjfT0a9DVzrE1NDvuCUF\n" +"0KgEdiNwux+hO6dbTyiS38yPT6TbpoWJptJmFhFkC4hGvUgoX/TI0covSyf74VRH\n" +"k3BHojOBMYiX1K66xoN7fhlGK8cith3L0XXPB8CgSEUPWURvm8RCaGuX2T3FZomF\n" +"BCnNpN+WNnN3Yf4OkjtuvtxxktUU7pfVLsUxrdpo/ph4rWm6U83VT/Zlq92aF4vW\n" +"QJ+7uraQFip7e+Gy9g3UJINm3B7b1C4ch/Z/upCZESOI/23sVGzkfTgOrS+23i6/\n" +"Vi9YW75zySC2FCa1AWMS1NmS5qfDSycJUgD6YvOUg0C54ZI=\n" +"-----END CERTIFICATE-----"; + +char private_key[] = +"-----BEGIN PRIVATE KEY-----\n" +"MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQC1LuFW/lDV/Gfl\n" +"qFMz7RDvFFgWld982ZuDJRaK55JNj+MI4RZNL61PDw43NeeJtqUoVxSLS9wHURjS\n" +"jD/CV5GudUOnzGfbwFlLko+jhYRT4HNFS+5ys1FEJLtAuYcY4P9GHQEXYUX+ue82\n" +"A2kJ91oY6G3vCQYJFiGteb6TRDICmug31x4pBfB8rOdt4/NXS/Dn+S0/mJlxw34I\n" +"KfqrlFjzUziRZtAWWqDcfxFDUizSggkdXIUq4GY38RADqGewNNCab3ClJDP7/M32\n" +"BhSNgsIKhgtSTM2+ocfvBhwup+BjV6UbL21DPAshlolVgSL1HM2jin5bi4bpFMre\n" +"Y0LXwFih87/6AVSfQHY9TZrombVZnMxvB7NG1NCSwDBTqjjFb3oiSMugJzY+MhIS\n" +"M754m46fwUyHZ1ylWCLJEU8kQ5A1q9vvqMcaDa4uTGP3UgC6SyVmZxG2o+AO6m8T\n" +"RTCtqHN41mPTM9HK4T1UyuzVpykSc2LlYkKE517SyEiVXDmotNb2myXNYHHTjRYN\n" +"xkq75Lbii2I4Q4z8XtDngaIrhZqACKSqIt2CocGjx61SoxKWi+LGa7B4NaCMjz1L\n" +"naOIsXn1rJDRnUWL49T42g4kOi/5QaC2JDygfefw1hAbuxkq9EYUDg+w9broltiB\n" +"f4rKAnw8JMySARnyPZbj0lhZK3va5wIDAQABAoICAQCMKul/0J2e/ncub6t2t4dr\n" +"PnTrfCT6xKqPqciny4Ee6hr9So1jR2gvink380bd/mQFMmEdZqGhM3cdpAzLf82f\n" +"hu7BSNxsYIF0er0PB4MZFMJ4sMaXC+zp5/TJnP5MG/zBND0c5k8tQpEyWy8O28Jj\n" +"FKW/0F5P90Q0ncP20EJUS50tXgniOMsU2Prtw/UE6yZDgD0mPxsurMu66ycXSFwM\n" +"WqyfqEeBk7lw/AjR6Sft71W31lTbl+DclG0MN2OIKUPcxiwCRmDFKI36MDgERk1x\n" +"sMPfdrWRLj2ryDFTUuLAWBTOVEGWS0RdRsWWVaJCuHbKd6FLl0TW2xQbOfWDTjYC\n" +"Ps31ejh163qdbk7OGOZIbd83fP3jsyL+4eNzhUpeXMKhfG58mFIv4yhdZIUOpuL6\n" +"aqnoU9z9wEsJKj/SrKr3nw6tuTnmbXgNjun9LfTFmqqDRBYd0Okiprw6jHNM1jgA\n" +"GG0kC/K7r89jKymVDABwGMFCS33ynR1Tb6zG+cqgNMPw19Fy3uQuW21CjqSzCOyP\n" +"aEVCEUZeP+ofql5+7ZKi6Dj+EdTfeKt2ihgheHZZoaYSINb8tsnKbdJhwBfW9PFT\n" +"aT/hu3bnO2FPC8H2NGOqxOEeel9ALU4SFu1pOknEhiL3/mNfOQ+KgrSRDtNRlcL0\n" +"cto05J90u0cmqwWKlshfaQKCAQEA5dcklxs4ezyzt28NcsiyS02oZ+9TkQp6pCXV\n" +"kx7AwhivAmVTlJ+c6BegA5EPd7A1gknM3+EKzGpoBOqmlF45G57phVIAphAp4oCH\n" +"UOVtIQgM8p4EU2gtX+uNOopdYlpBQnWimXaHA2sOD9/yTbZ03j/McRH6D15+iCld\n" +"3880GHdZaYYbQmHoSDg39LRRO1bdS3WC0oKBD2gPi3K0b9RaZSwKzuVrmlvrLURj\n" +"WMZfmkGl4BsITfuoTxbWFVncG3Kb9eYkYUFZy4M2G/s849PS/HjrN7BvgpanjtVp\n" +"1/39APQfAYfUuBPbKYnb6F8dE0pb5cVd4uMZklAeTb3bXjOO9QKCAQEAyc4CxWXr\n" +"bG6Do5dGpWudQ7ucq00MR0T3MHQIu5XTn6BsPHAJ9ZgrQw9C24PXm2VEjjsrMs5T\n" +"rHNF9oeO39s25Za1iyJ+893icqA3h3ivCUOOoVE54BkuJK6REhkXPD5G1ubmxeBz\n" +"MKNehlpd/eSbJJArkzKFZ8sBtLt8i9VFhRnXSpDAbiMpCbjW+bem9MWdLmkenSnu\n" +"OUbnqYcJhFBCvOT7ZCHFCDNUNPfHcaReSY2EYjw0ZqtqAZD0Q+DL+RkLz7l1+/bF\n" +"eEwNjmjFTcwRyawqf38D4miU0H6ca16FkeSlbmM5p3HdwZK2HVYYz3FSwhox6Ebd\n" +"n6in42qfL4Ug6wKCAQAh9IDRWhIkErmyNdPUy1WbzmM8x5ye5t9rdLNywq5TfnYM\n" +"co/AezwhBax8GmgglIWzM9fykzqXLHklkMz/SlRBgl6ZdZ3m6qhlb/uNtfdDU/8l\n" +"sLaO4+sgKpp4tYxKRW8ytFJLPbmAhcZUDg+r73KgiuhXJAK/VoR29TWLJP9bRfaN\n" +"omRQkEpSsQuDOUhu7cxPo5KqKuGKNyNkxJNnmgWowLLwEfCtozrBO0M6EER7c4tf\n" +"6l51tuIMnSEPknD0FSB5WYCyZYcwi7fotlsuhVK8PdjyJzyyHDOw5FJ4uGsyQt55\n" +"yWlhsH1GS7mTQMn42Zlt/pR6OnbCqNdxQMUxy4gpAoIBAFvMbs5E0pb8nr0n72cI\n" +"UP2itl3mKpOw95D+94n9WcrfOt0zShSCKAvVQWCB1O5HXqwklj4CRWXI+iZu+7sx\n" +"CQPfTq3//ygH4x6paxkg+N6J8LPJMz6Rtb/R+QP2je9FlQvk9U1GEKArcLBFI0R/\n" +"XWOAgZHwBWd1nU0NjFY/qeQmIR02Q5LWQ7C8eG4X8MafriSShO6RSGCdtHwVhWq+\n" +"59ztfL3L7skQMFn37K3xS0LCMVpOcLfTeeFEgxjthVvG3OydPOJlGubiEbiaSEZf\n" +"cif/PUXKDYZMdIVzUsw0ryXykJ5qXKuizHFlv5oQtDCJKFBLgjBbLC2YluaIdekz\n" +"8gkCggEBAJWxS7EuB/qL7fOz0o3HRy0plR3qbwZ0pLoCz0Ii7WxraBS1yQwmxif1\n" +"Rgv89GyFqg1yQl3CSrMiw7oC9WxxxuiEZDO18c4KO3NTv9K4itN9OPQVBTHmEhod\n" +"KWcyP4/W/Sfuae77PyclSqUsAARRrKYn2fpLTS5ibaU0QZgHmdPgYDUrPr+6PHKK\n" +"ZfQKU2uBfuo6zoMbMmFi3UYG49j9rv4d6v+44vS1MPHV9JK/LD8YfBhgx8Pg/u6D\n" +"nUgipS48pkGjJr2u2Vu7Mx70vqz0Yf2neyyDbdLtkYauC4w7YKPTD0yzDJyGuAeB\n" +"GyPbW1yZa5vE302a1Cr0Cd7RC4AFAAw=\n" +"-----END PRIVATE KEY-----"; + struct test_files_set get_test_files_set(void) { static struct test_file files[] = { @@ -195,7 +290,7 @@ char *bin2hex(char *dst, const void *src, size_t count) return dst; } -static char *get_index_filename(const char *mnt_dir, incfs_uuid_t id) +static char *get_index_filename(char *mnt_dir, incfs_uuid_t id) { char path[FILENAME_MAX]; char str_id[1 + 2 * sizeof(id)]; @@ -206,43 +301,15 @@ static char *get_index_filename(const char *mnt_dir, incfs_uuid_t id) return strdup(path); } -int open_file_by_id(const char *mnt_dir, incfs_uuid_t id, bool use_ioctl) +int open_file_by_id(char *mnt_dir, incfs_uuid_t id) { char *path = get_index_filename(mnt_dir, id); - int cmd_fd = open_commands_file(mnt_dir); - int fd = open(path, O_RDWR | O_CLOEXEC); - struct incfs_permit_fill permit_fill = { - .file_descriptor = fd, - }; - int error = 0; + int fd = open(path, O_RDWR); + free(path); if (fd < 0) { print_error("Can't open file by id."); - error = -errno; - goto out; - } - - if (use_ioctl && ioctl(cmd_fd, INCFS_IOC_PERMIT_FILL, &permit_fill)) { - print_error("Failed to call PERMIT_FILL"); - error = -errno; - goto out; - } - - if (ioctl(fd, INCFS_IOC_PERMIT_FILL, &permit_fill) != -1 || - errno != EPERM) { - print_error( - "Successfully called PERMIT_FILL on non pending_read file"); return -errno; - goto out; - } - -out: - free(path); - close(cmd_fd); - - if (error) { - close(fd); - return error; } return fd; @@ -276,18 +343,20 @@ static int emit_test_blocks(char *mnt_dir, struct test_file *file, uint8_t *data_buf = malloc(data_buf_size); uint8_t *current_data = data_buf; uint8_t *data_end = data_buf + data_buf_size; - struct incfs_fill_block *block_buf = - calloc(block_count, sizeof(struct incfs_fill_block)); - struct incfs_fill_blocks fill_blocks = { - .count = block_count, - .fill_blocks = ptr_to_u64(block_buf), - }; + struct incfs_new_data_block *block_buf = + calloc(block_count, sizeof(*block_buf)); ssize_t write_res = 0; - int fd = -1; + int fd; int error = 0; int i = 0; int blocks_written = 0; + fd = open_file_by_id(mnt_dir, file->id); + if (fd <= 0) { + error = -errno; + goto out; + } + for (i = 0; i < block_count; i++) { int block_index = blocks[i]; bool compress = (file->index + block_index) % 2 == 0; @@ -335,33 +404,17 @@ static int emit_test_blocks(char *mnt_dir, struct test_file *file, block_buf[i].block_index = block_index; block_buf[i].data_len = block_size; block_buf[i].data = ptr_to_u64(current_data); + block_buf[i].compression = + compress ? COMPRESSION_LZ4 : COMPRESSION_NONE; current_data += block_size; } if (!error) { - fd = open_file_by_id(mnt_dir, file->id, false); - if (fd < 0) { - error = -errno; - goto out; - } - write_res = ioctl(fd, INCFS_IOC_FILL_BLOCKS, &fill_blocks); - if (write_res >= 0) { - ksft_print_msg("Wrote to file via normal fd error\n"); - error = -EPERM; - goto out; - } - - close(fd); - fd = open_file_by_id(mnt_dir, file->id, true); - if (fd < 0) { - error = -errno; - goto out; - } - write_res = ioctl(fd, INCFS_IOC_FILL_BLOCKS, &fill_blocks); + write_res = write(fd, block_buf, sizeof(*block_buf) * i); if (write_res < 0) error = -errno; else - blocks_written = write_res; + blocks_written = write_res / sizeof(*block_buf); } if (error) { ksft_print_msg( @@ -446,7 +499,7 @@ static loff_t read_whole_file(char *filename) loff_t bytes_read = 0; uint8_t buff[16 * 1024]; - fd = open(filename, O_RDONLY | O_CLOEXEC); + fd = open(filename, O_RDONLY); if (fd <= 0) return fd; @@ -478,7 +531,7 @@ static int read_test_file(uint8_t *buf, size_t len, char *filename, size_t bytes_to_read = len; off_t offset = ((off_t)block_idx) * INCFS_DATA_FILE_BLOCK_SIZE; - fd = open(filename, O_RDONLY | O_CLOEXEC); + fd = open(filename, O_RDONLY); if (fd <= 0) return fd; @@ -667,6 +720,8 @@ static int build_mtree(struct test_file *file) int tree_lvl_index[INCFS_MAX_MTREE_LEVELS] = {}; int tree_lvl_count[INCFS_MAX_MTREE_LEVELS] = {}; int levels_count = 0; + char data_to_sign[256] = {}; + int sig_data_size; int i, level; if (file->size == 0) @@ -693,9 +748,8 @@ static int build_mtree(struct test_file *file) if (block_count == 1) { int seed = get_file_block_seed(file->index, 0); - memset(data, 0, INCFS_DATA_FILE_BLOCK_SIZE); rnd_buf((uint8_t *)data, file->size, seed); - sha256(data, INCFS_DATA_FILE_BLOCK_SIZE, file->root_hash); + sha256(data, file->size, file->root_hash); return 0; } @@ -710,13 +764,11 @@ static int build_mtree(struct test_file *file) int seed = get_file_block_seed(file->index, i); char *hash_ptr = file->mtree[block_index].data + block_off; - if (file->size - offset < block_size) { + if (file->size - offset < block_size) block_size = file->size - offset; - memset(data, 0, INCFS_DATA_FILE_BLOCK_SIZE); - } rnd_buf((uint8_t *)data, block_size, seed); - sha256(data, INCFS_DATA_FILE_BLOCK_SIZE, hash_ptr); + sha256(data, block_size, hash_ptr); } /* Build higher levels of hash tree. */ @@ -740,6 +792,19 @@ static int build_mtree(struct test_file *file) sha256(file->mtree[0].data, INCFS_DATA_FILE_BLOCK_SIZE, file->root_hash); + /* Calculating digital signature */ + snprintf(file->sig.add_data, sizeof(file->sig.add_data), "%ld", + file->size); + memcpy(data_to_sign, file->root_hash, SHA256_DIGEST_SIZE); + memcpy(data_to_sign + SHA256_DIGEST_SIZE, file->sig.add_data, + strlen(file->sig.add_data)); + sig_data_size = SHA256_DIGEST_SIZE + strlen(file->sig.add_data); + if (!sign_pkcs7(data_to_sign, sig_data_size, private_key, x509_cert, + &file->sig.data, &file->sig.size)) { + ksft_print_msg("Signing failed.\n"); + return -EINVAL; + } + return 0; } @@ -748,21 +813,21 @@ static int load_hash_tree(const char *mount_dir, struct test_file *file) int err; int i; int fd; - struct incfs_fill_blocks fill_blocks = { - .count = file->mtree_block_count, - }; - struct incfs_fill_block *fill_block_array = - calloc(fill_blocks.count, sizeof(struct incfs_fill_block)); - if (fill_blocks.count == 0) + size_t blocks_size = + file->mtree_block_count * sizeof(struct incfs_new_data_block); + struct incfs_new_data_block *blocks = NULL; + char *file_path; + + if (blocks_size == 0) return 0; - if (!fill_block_array) + blocks = malloc(blocks_size); + if (!blocks) return -ENOMEM; - fill_blocks.fill_blocks = ptr_to_u64(fill_block_array); - for (i = 0; i < fill_blocks.count; i++) { - fill_block_array[i] = (struct incfs_fill_block){ + for (i = 0; i < file->mtree_block_count; i++) { + blocks[i] = (struct incfs_new_data_block){ .block_index = i, .data_len = INCFS_DATA_FILE_BLOCK_SIZE, .data = ptr_to_u64(file->mtree[i].data), @@ -770,28 +835,18 @@ static int load_hash_tree(const char *mount_dir, struct test_file *file) }; } - fd = open_file_by_id(mount_dir, file->id, false); + file_path = concat_file_name(mount_dir, file->name); + fd = open(file_path, O_RDWR); + free(file_path); if (fd < 0) { err = errno; goto failure; } - err = ioctl(fd, INCFS_IOC_FILL_BLOCKS, &fill_blocks); + err = write(fd, blocks, blocks_size); close(fd); - if (err >= 0) { - err = -EPERM; - goto failure; - } - fd = open_file_by_id(mount_dir, file->id, true); - if (fd < 0) { - err = errno; - goto failure; - } - - err = ioctl(fd, INCFS_IOC_FILL_BLOCKS, &fill_blocks); - close(fd); - if (err < fill_blocks.count) + if (err < blocks_size) err = errno; else { err = 0; @@ -799,7 +854,7 @@ static int load_hash_tree(const char *mount_dir, struct test_file *file) } failure: - free(fill_block_array); + free(blocks); return err; } @@ -911,7 +966,7 @@ static bool iterate_directory(char *dir_to_iterate, bool root, int file_count) int i; /* Test directory iteration */ - int fd = open(dir_to_iterate, O_RDONLY | O_DIRECTORY | O_CLOEXEC); + int fd = open(dir_to_iterate, O_RDONLY | O_DIRECTORY); if (fd < 0) { print_error("Can't open directory\n"); @@ -1112,7 +1167,7 @@ static int basic_file_ops_test(char *mount_dir) char *path = concat_file_name(mount_dir, file->name); int fd; - fd = open(path, O_RDWR | O_CLOEXEC); + fd = open(path, O_RDWR); free(path); if (fd <= 0) { print_error("Can't open file"); @@ -1219,6 +1274,13 @@ static int dynamic_files_and_data_test(char *mount_dir) if (i == missing_file_idx) continue; + res = load_hash_tree(mount_dir, file); + if (res) { + ksft_print_msg("Can't load hashes for %s. error: %s\n", + file->name, strerror(-res)); + goto failure; + } + res = emit_test_file_data(mount_dir, file); if (res) { ksft_print_msg("Error %s emiting data for %s.\n", @@ -1417,6 +1479,7 @@ static int work_after_remount_test(char *mount_dir) /* Write first half of the data into the command file. (stage 1) */ for (i = 0; i < file_num_stage1; i++) { struct test_file *file = &test.files[i]; + int res; build_mtree(file); if (emit_file(cmd_fd, NULL, file->name, &file->id, @@ -1425,7 +1488,14 @@ static int work_after_remount_test(char *mount_dir) if (emit_test_file_data(mount_dir, file)) goto failure; - } + + res = load_hash_tree(mount_dir, file); + if (res) { + ksft_print_msg("Can't load hashes for %s. error: %s\n", + file->name, strerror(-res)); + goto failure; + } +} /* Unmount and mount again, to see that data is persistent. */ close(cmd_fd); @@ -1812,6 +1882,162 @@ failure: return TEST_FAILURE; } +static int signature_test(char *mount_dir) +{ + struct test_files_set test = get_test_files_set(); + const int file_num = test.files_count; + int i = 0; + unsigned char sig_buf[INCFS_MAX_SIGNATURE_SIZE]; + char *backing_dir; + int cmd_fd = -1; + + backing_dir = create_backing_dir(mount_dir); + if (!backing_dir) + goto failure; + + /* Mount FS and release the backing file. (10s wait time) */ + if (mount_fs(mount_dir, backing_dir, 10000) != 0) + goto failure; + + cmd_fd = open_commands_file(mount_dir); + if (cmd_fd < 0) + goto failure; + + /* Write hashes and data. */ + for (i = 0; i < file_num; i++) { + struct test_file *file = &test.files[i]; + int res; + + build_mtree(file); + + res = crypto_emit_file(cmd_fd, NULL, file->name, &file->id, + file->size, file->root_hash, + file->sig.data, file->sig.size, file->sig.add_data); + + if (res) { + ksft_print_msg("Emit failed for %s. error: %s\n", + file->name, strerror(-res)); + goto failure; + } + + if (emit_test_file_data(mount_dir, file)) + goto failure; + + res = load_hash_tree(mount_dir, file); + if (res) { + ksft_print_msg("Can't load hashes for %s. error: %s\n", + file->name, strerror(-res)); + goto failure; + } + } + + /* Validate data */ + for (i = 0; i < file_num; i++) { + struct test_file *file = &test.files[i]; + int sig_len; + char *path; + int fd; + + if (validate_test_file_content(mount_dir, file) < 0) + goto failure; + + path = concat_file_name(mount_dir, file->name); + fd = open(path, O_RDWR); + free(path); + if (fd < 0) { + print_error("Can't open file"); + goto failure; + } + + sig_len = get_file_signature(fd, sig_buf, ARRAY_SIZE(sig_buf)); + + if (close(fd)) { + print_error("Can't close file"); + goto failure; + } + + if (sig_len < 0) { + ksft_print_msg("Can't load signature %s. error: %s\n", + file->name, strerror(-sig_len)); + goto failure; + } + + if (sig_len != file->sig.size || + memcmp(sig_buf, file->sig.data, sig_len)) { + ksft_print_msg("Signature mismatch %s.\n", + file->name); + goto failure; + } + } + + /* Unmount and mount again, to make sure the signature is persistent. */ + close(cmd_fd); + cmd_fd = -1; + if (umount(mount_dir) != 0) { + print_error("Can't unmout FS"); + goto failure; + } + if (mount_fs(mount_dir, backing_dir, 50) != 0) + goto failure; + + cmd_fd = open_commands_file(mount_dir); + if (cmd_fd < 0) + goto failure; + + /* Validate data again */ + for (i = 0; i < file_num; i++) { + struct test_file *file = &test.files[i]; + int sig_len; + char *path; + int fd; + + if (validate_test_file_content(mount_dir, file) < 0) + goto failure; + + path = concat_file_name(mount_dir, file->name); + fd = open(path, O_RDWR); + free(path); + if (fd < 0) { + print_error("Can't open file"); + goto failure; + } + + sig_len = get_file_signature(fd, sig_buf, ARRAY_SIZE(sig_buf)); + + if (close(fd)) { + print_error("Can't close file"); + goto failure; + } + + if (sig_len < 0) { + ksft_print_msg("Can't load signature %s. error: %s\n", + file->name, strerror(-sig_len)); + goto failure; + } + if (sig_len != file->sig.size || + memcmp(sig_buf, file->sig.data, sig_len)) { + ksft_print_msg("Signature mismatch %s.\n", + file->name); + goto failure; + } + } + + /* Final unmount */ + close(cmd_fd); + cmd_fd = -1; + if (umount(mount_dir) != 0) { + print_error("Can't unmout FS"); + goto failure; + } + return TEST_SUCCESS; + +failure: + close(cmd_fd); + free(backing_dir); + umount(mount_dir); + return TEST_FAILURE; +} + static int hash_tree_test(char *mount_dir) { char *backing_dir; @@ -1840,8 +2066,8 @@ static int hash_tree_test(char *mount_dir) build_mtree(file); res = crypto_emit_file(cmd_fd, NULL, file->name, &file->id, - file->size, file->root_hash, - file->sig.add_data); + file->size, file->root_hash, + file->sig.data, file->sig.size, file->sig.add_data); if (i == corrupted_file_idx) { /* Corrupt third blocks hash */ @@ -1932,88 +2158,48 @@ failure: return TEST_FAILURE; } -enum expected_log { FULL_LOG, NO_LOG, PARTIAL_LOG }; - -static int validate_logs(char *mount_dir, int log_fd, struct test_file *file, - enum expected_log expected_log) +static int validate_logs(char *mount_dir, int log_fd, struct test_file *file) { uint8_t data[INCFS_DATA_FILE_BLOCK_SIZE]; - struct incfs_pending_read_info prs[2048] = {}; + struct incfs_pending_read_info prs[100] = {}; int prs_size = ARRAY_SIZE(prs); int block_cnt = 1 + (file->size - 1) / INCFS_DATA_FILE_BLOCK_SIZE; - int expected_read_block_cnt; int res; int read_count; - int i, j; + int i; char *filename = concat_file_name(mount_dir, file->name); int fd; - fd = open(filename, O_RDONLY | O_CLOEXEC); + fd = open(filename, O_RDONLY); free(filename); if (fd <= 0) return TEST_FAILURE; if (block_cnt > prs_size) block_cnt = prs_size; - expected_read_block_cnt = block_cnt; for (i = 0; i < block_cnt; i++) { res = pread(fd, data, sizeof(data), INCFS_DATA_FILE_BLOCK_SIZE * i); - - /* Make some read logs of type SAME_FILE_NEXT_BLOCK */ - if (i % 10 == 0) - usleep(20000); - - /* Skip some blocks to make logs of type SAME_FILE */ - if (i % 10 == 5) { - ++i; - --expected_read_block_cnt; - } - if (res <= 0) goto failure; } - read_count = wait_for_pending_reads( - log_fd, expected_log == NO_LOG ? 10 : 0, prs, prs_size); - if (expected_log == NO_LOG) { - if (read_count == 0) - goto success; - if (read_count < 0) - ksft_print_msg("Error reading logged reads %s.\n", - strerror(-read_count)); - else - ksft_print_msg("Somehow read empty logs.\n"); - goto failure; - } - + read_count = wait_for_pending_reads(log_fd, 0, prs, prs_size); if (read_count < 0) { ksft_print_msg("Error reading logged reads %s.\n", strerror(-read_count)); goto failure; } - i = 0; - if (expected_log == PARTIAL_LOG) { - if (read_count == 0) { - ksft_print_msg("No logs %s.\n", file->name); - goto failure; - } - - for (i = 0, j = 0; j < expected_read_block_cnt - read_count; - i++, j++) - if (i % 10 == 5) - ++i; - - } else if (read_count != expected_read_block_cnt) { + if (read_count != block_cnt) { ksft_print_msg("Bad log read count %s %d %d.\n", file->name, - read_count, expected_read_block_cnt); + read_count, block_cnt); goto failure; } - for (j = 0; j < read_count; i++, j++) { - struct incfs_pending_read_info *read = &prs[j]; + for (i = 0; i < read_count; i++) { + struct incfs_pending_read_info *read = &prs[i]; if (!same_id(&read->file_id, &file->id)) { ksft_print_msg("Bad log read ino %s\n", file->name); @@ -2026,8 +2212,8 @@ static int validate_logs(char *mount_dir, int log_fd, struct test_file *file, goto failure; } - if (j != 0) { - unsigned long psn = prs[j - 1].serial_number; + if (i != 0) { + unsigned long psn = prs[i - 1].serial_number; if (read->serial_number != psn + 1) { ksft_print_msg("Bad log read sn %s %d %d.\n", @@ -2042,12 +2228,7 @@ static int validate_logs(char *mount_dir, int log_fd, struct test_file *file, file->name); goto failure; } - - if (i % 10 == 5) - ++i; } - -success: close(fd); return TEST_SUCCESS; @@ -2061,14 +2242,14 @@ static int read_log_test(char *mount_dir) struct test_files_set test = get_test_files_set(); const int file_num = test.files_count; int i = 0; - int cmd_fd = -1, log_fd = -1, drop_caches = -1; + int cmd_fd = -1, log_fd = -1; char *backing_dir; backing_dir = create_backing_dir(mount_dir); if (!backing_dir) goto failure; - if (mount_fs_opt(mount_dir, backing_dir, "readahead=0", false) != 0) + if (mount_fs_opt(mount_dir, backing_dir, "readahead=0") != 0) goto failure; cmd_fd = open_commands_file(mount_dir); @@ -2076,7 +2257,7 @@ static int read_log_test(char *mount_dir) goto failure; log_fd = open_log_file(mount_dir); - if (log_fd < 0) + if (cmd_fd < 0) ksft_print_msg("Can't open log file.\n"); /* Write data. */ @@ -2095,7 +2276,7 @@ static int read_log_test(char *mount_dir) for (i = 0; i < file_num; i++) { struct test_file *file = &test.files[i]; - if (validate_logs(mount_dir, log_fd, file, FULL_LOG)) + if (validate_logs(mount_dir, log_fd, file)) goto failure; } @@ -2108,7 +2289,7 @@ static int read_log_test(char *mount_dir) goto failure; } - if (mount_fs_opt(mount_dir, backing_dir, "readahead=0", false) != 0) + if (mount_fs_opt(mount_dir, backing_dir, "readahead=0") != 0) goto failure; cmd_fd = open_commands_file(mount_dir); @@ -2116,91 +2297,19 @@ static int read_log_test(char *mount_dir) goto failure; log_fd = open_log_file(mount_dir); - if (log_fd < 0) + if (cmd_fd < 0) ksft_print_msg("Can't open log file.\n"); /* Validate data again */ for (i = 0; i < file_num; i++) { struct test_file *file = &test.files[i]; - if (validate_logs(mount_dir, log_fd, file, FULL_LOG)) - goto failure; - } - - /* - * Unmount and mount again with no read log to make sure poll - * doesn't crash - */ - close(cmd_fd); - close(log_fd); - if (umount(mount_dir) != 0) { - print_error("Can't unmout FS"); - goto failure; - } - - if (mount_fs_opt(mount_dir, backing_dir, "readahead=0,rlog_pages=0", - false) != 0) - goto failure; - - log_fd = open_log_file(mount_dir); - if (log_fd < 0) - ksft_print_msg("Can't open log file.\n"); - - /* Validate data again - note should fail this time */ - for (i = 0; i < file_num; i++) { - struct test_file *file = &test.files[i]; - - if (validate_logs(mount_dir, log_fd, file, NO_LOG)) - goto failure; - } - - /* - * Remount and check that logs start working again - */ - drop_caches = open("/proc/sys/vm/drop_caches", O_WRONLY | O_CLOEXEC); - if (drop_caches == -1) - goto failure; - i = write(drop_caches, "3", 1); - close(drop_caches); - if (i != 1) - goto failure; - - if (mount_fs_opt(mount_dir, backing_dir, "readahead=0,rlog_pages=1", - true) != 0) - goto failure; - - /* Validate data again */ - for (i = 0; i < file_num; i++) { - struct test_file *file = &test.files[i]; - - if (validate_logs(mount_dir, log_fd, file, PARTIAL_LOG)) - goto failure; - } - - /* - * Remount and check that logs start working again - */ - drop_caches = open("/proc/sys/vm/drop_caches", O_WRONLY | O_CLOEXEC); - if (drop_caches == -1) - goto failure; - i = write(drop_caches, "3", 1); - close(drop_caches); - if (i != 1) - goto failure; - - if (mount_fs_opt(mount_dir, backing_dir, "readahead=0,rlog_pages=4", - true) != 0) - goto failure; - - /* Validate data again */ - for (i = 0; i < file_num; i++) { - struct test_file *file = &test.files[i]; - - if (validate_logs(mount_dir, log_fd, file, FULL_LOG)) + if (validate_logs(mount_dir, log_fd, file)) goto failure; } /* Final unmount */ + close(cmd_fd); close(log_fd); free(backing_dir); if (umount(mount_dir) != 0) { @@ -2218,456 +2327,6 @@ failure: return TEST_FAILURE; } -static int emit_partial_test_file_data(char *mount_dir, struct test_file *file) -{ - int i, j; - int block_cnt = 1 + (file->size - 1) / INCFS_DATA_FILE_BLOCK_SIZE; - int *block_indexes = NULL; - int result = 0; - int blocks_written = 0; - - if (file->size == 0) - return 0; - - /* Emit 2 blocks, skip 2 blocks etc*/ - block_indexes = calloc(block_cnt, sizeof(*block_indexes)); - for (i = 0, j = 0; i < block_cnt; ++i) - if ((i & 2) == 0) { - block_indexes[j] = i; - ++j; - } - - for (i = 0; i < j; i += blocks_written) { - blocks_written = emit_test_blocks(mount_dir, file, - block_indexes + i, j - i); - if (blocks_written < 0) { - result = blocks_written; - goto out; - } - if (blocks_written == 0) { - result = -EIO; - goto out; - } - } -out: - free(block_indexes); - return result; -} - -static int validate_ranges(const char *mount_dir, struct test_file *file) -{ - int block_cnt = 1 + (file->size - 1) / INCFS_DATA_FILE_BLOCK_SIZE; - char *filename = concat_file_name(mount_dir, file->name); - int fd; - struct incfs_filled_range ranges[128]; - struct incfs_get_filled_blocks_args fba = { - .range_buffer = ptr_to_u64(ranges), - .range_buffer_size = sizeof(ranges), - }; - int error = TEST_SUCCESS; - int i; - int range_cnt; - int cmd_fd = -1; - struct incfs_permit_fill permit_fill; - - fd = open(filename, O_RDONLY | O_CLOEXEC); - free(filename); - if (fd <= 0) - return TEST_FAILURE; - - error = ioctl(fd, INCFS_IOC_GET_FILLED_BLOCKS, &fba); - if (error != -1 || errno != EPERM) { - ksft_print_msg("INCFS_IOC_GET_FILLED_BLOCKS not blocked\n"); - error = -EPERM; - goto out; - } - - cmd_fd = open_commands_file(mount_dir); - permit_fill.file_descriptor = fd; - if (ioctl(cmd_fd, INCFS_IOC_PERMIT_FILL, &permit_fill)) { - print_error("INCFS_IOC_PERMIT_FILL failed"); - return -EPERM; - goto out; - } - - error = ioctl(fd, INCFS_IOC_GET_FILLED_BLOCKS, &fba); - if (error && errno != ERANGE) - goto out; - - if (error && errno == ERANGE && block_cnt < 509) - goto out; - - if (!error && block_cnt >= 509) { - error = -ERANGE; - goto out; - } - - if (fba.total_blocks_out != block_cnt) { - error = -EINVAL; - goto out; - } - - if (fba.data_blocks_out != block_cnt) { - error = -EINVAL; - goto out; - } - - range_cnt = (block_cnt + 3) / 4; - if (range_cnt > 128) - range_cnt = 128; - if (range_cnt != fba.range_buffer_size_out / sizeof(*ranges)) { - error = -ERANGE; - goto out; - } - - error = TEST_SUCCESS; - for (i = 0; i < fba.range_buffer_size_out / sizeof(*ranges) - 1; ++i) - if (ranges[i].begin != i * 4 || ranges[i].end != i * 4 + 2) { - error = -EINVAL; - goto out; - } - - if (ranges[i].begin != i * 4 || - (ranges[i].end != i * 4 + 1 && ranges[i].end != i * 4 + 2)) { - error = -EINVAL; - goto out; - } - - for (i = 0; i < 64; ++i) { - fba.start_index = i * 2; - fba.end_index = i * 2 + 2; - error = ioctl(fd, INCFS_IOC_GET_FILLED_BLOCKS, &fba); - if (error) - goto out; - - if (fba.total_blocks_out != block_cnt) { - error = -EINVAL; - goto out; - } - - if (fba.start_index >= block_cnt) { - if (fba.index_out != fba.start_index) { - error = -EINVAL; - goto out; - } - - break; - } - - if (i % 2) { - if (fba.range_buffer_size_out != 0) { - error = -EINVAL; - goto out; - } - } else { - if (fba.range_buffer_size_out != sizeof(*ranges)) { - error = -EINVAL; - goto out; - } - - if (ranges[0].begin != i * 2) { - error = -EINVAL; - goto out; - } - - if (ranges[0].end != i * 2 + 1 && - ranges[0].end != i * 2 + 2) { - error = -EINVAL; - goto out; - } - } - } - -out: - close(fd); - close(cmd_fd); - return error; -} - -static int get_blocks_test(char *mount_dir) -{ - char *backing_dir; - int cmd_fd = -1; - int i; - struct test_files_set test = get_test_files_set(); - const int file_num = test.files_count; - - backing_dir = create_backing_dir(mount_dir); - if (!backing_dir) - goto failure; - - if (mount_fs_opt(mount_dir, backing_dir, "readahead=0", false) != 0) - goto failure; - - cmd_fd = open_commands_file(mount_dir); - if (cmd_fd < 0) - goto failure; - - /* Write data. */ - for (i = 0; i < file_num; i++) { - struct test_file *file = &test.files[i]; - - if (emit_file(cmd_fd, NULL, file->name, &file->id, file->size, - NULL)) - goto failure; - - if (emit_partial_test_file_data(mount_dir, file)) - goto failure; - } - - for (i = 0; i < file_num; i++) { - struct test_file *file = &test.files[i]; - - if (validate_ranges(mount_dir, file)) - goto failure; - - /* - * The smallest files are filled completely, so this checks that - * the fast get_filled_blocks path is not causing issues - */ - if (validate_ranges(mount_dir, file)) - goto failure; - } - - close(cmd_fd); - umount(mount_dir); - free(backing_dir); - return TEST_SUCCESS; - -failure: - close(cmd_fd); - umount(mount_dir); - free(backing_dir); - return TEST_FAILURE; -} - -static int emit_partial_test_file_hash(char *mount_dir, struct test_file *file) -{ - int err; - int fd; - struct incfs_fill_blocks fill_blocks = { - .count = 1, - }; - struct incfs_fill_block *fill_block_array = - calloc(fill_blocks.count, sizeof(struct incfs_fill_block)); - uint8_t data[INCFS_DATA_FILE_BLOCK_SIZE]; - - if (file->size <= 4096 / 32 * 4096) - return 0; - - if (fill_blocks.count == 0) - return 0; - - if (!fill_block_array) - return -ENOMEM; - fill_blocks.fill_blocks = ptr_to_u64(fill_block_array); - - rnd_buf(data, sizeof(data), 0); - - fill_block_array[0] = - (struct incfs_fill_block){ .block_index = 1, - .data_len = - INCFS_DATA_FILE_BLOCK_SIZE, - .data = ptr_to_u64(data), - .flags = INCFS_BLOCK_FLAGS_HASH }; - - fd = open_file_by_id(mount_dir, file->id, true); - if (fd < 0) { - err = errno; - goto failure; - } - - err = ioctl(fd, INCFS_IOC_FILL_BLOCKS, &fill_blocks); - close(fd); - if (err < fill_blocks.count) - err = errno; - else - err = 0; - -failure: - free(fill_block_array); - return err; -} - -static int validate_hash_ranges(const char *mount_dir, struct test_file *file) -{ - int block_cnt = 1 + (file->size - 1) / INCFS_DATA_FILE_BLOCK_SIZE; - char *filename = concat_file_name(mount_dir, file->name); - int fd; - struct incfs_filled_range ranges[128]; - struct incfs_get_filled_blocks_args fba = { - .range_buffer = ptr_to_u64(ranges), - .range_buffer_size = sizeof(ranges), - }; - int error = TEST_SUCCESS; - int file_blocks = (file->size + INCFS_DATA_FILE_BLOCK_SIZE - 1) / - INCFS_DATA_FILE_BLOCK_SIZE; - int cmd_fd = -1; - struct incfs_permit_fill permit_fill; - - if (file->size <= 4096 / 32 * 4096) - return 0; - - fd = open(filename, O_RDONLY | O_CLOEXEC); - free(filename); - if (fd <= 0) - return TEST_FAILURE; - - error = ioctl(fd, INCFS_IOC_GET_FILLED_BLOCKS, &fba); - if (error != -1 || errno != EPERM) { - ksft_print_msg("INCFS_IOC_GET_FILLED_BLOCKS not blocked\n"); - error = -EPERM; - goto out; - } - - cmd_fd = open_commands_file(mount_dir); - permit_fill.file_descriptor = fd; - if (ioctl(cmd_fd, INCFS_IOC_PERMIT_FILL, &permit_fill)) { - print_error("INCFS_IOC_PERMIT_FILL failed"); - return -EPERM; - goto out; - } - - error = ioctl(fd, INCFS_IOC_GET_FILLED_BLOCKS, &fba); - if (error) - goto out; - - if (fba.total_blocks_out <= block_cnt) { - error = -EINVAL; - goto out; - } - - if (fba.data_blocks_out != block_cnt) { - error = -EINVAL; - goto out; - } - - if (fba.range_buffer_size_out != sizeof(struct incfs_filled_range)) { - error = -EINVAL; - goto out; - } - - if (ranges[0].begin != file_blocks + 1 || - ranges[0].end != file_blocks + 2) { - error = -EINVAL; - goto out; - } - -out: - close(cmd_fd); - close(fd); - return error; -} - -static int get_hash_blocks_test(char *mount_dir) -{ - char *backing_dir; - int cmd_fd = -1; - int i; - struct test_files_set test = get_test_files_set(); - const int file_num = test.files_count; - - backing_dir = create_backing_dir(mount_dir); - if (!backing_dir) - goto failure; - - if (mount_fs_opt(mount_dir, backing_dir, "readahead=0", false) != 0) - goto failure; - - cmd_fd = open_commands_file(mount_dir); - if (cmd_fd < 0) - goto failure; - - for (i = 0; i < file_num; i++) { - struct test_file *file = &test.files[i]; - - if (crypto_emit_file(cmd_fd, NULL, file->name, &file->id, - file->size, file->root_hash, - file->sig.add_data)) - goto failure; - - if (emit_partial_test_file_hash(mount_dir, file)) - goto failure; - } - - for (i = 0; i < file_num; i++) { - struct test_file *file = &test.files[i]; - - if (validate_hash_ranges(mount_dir, file)) - goto failure; - } - - close(cmd_fd); - umount(mount_dir); - free(backing_dir); - return TEST_SUCCESS; - -failure: - close(cmd_fd); - umount(mount_dir); - free(backing_dir); - return TEST_FAILURE; -} - -static int large_file(char *mount_dir) -{ - char *backing_dir; - int cmd_fd = -1; - int i; - int result = TEST_FAILURE; - uint8_t data[INCFS_DATA_FILE_BLOCK_SIZE] = {}; - int block_count = 3LL * 1024 * 1024 * 1024 / INCFS_DATA_FILE_BLOCK_SIZE; - struct incfs_fill_block *block_buf = - calloc(block_count, sizeof(struct incfs_fill_block)); - struct incfs_fill_blocks fill_blocks = { - .count = block_count, - .fill_blocks = ptr_to_u64(block_buf), - }; - incfs_uuid_t id; - int fd; - - backing_dir = create_backing_dir(mount_dir); - if (!backing_dir) - goto failure; - - if (mount_fs_opt(mount_dir, backing_dir, "readahead=0", false) != 0) - goto failure; - - cmd_fd = open_commands_file(mount_dir); - if (cmd_fd < 0) - goto failure; - - if (emit_file(cmd_fd, NULL, "very_large_file", &id, - (uint64_t)block_count * INCFS_DATA_FILE_BLOCK_SIZE, - NULL) < 0) - goto failure; - - for (i = 0; i < block_count; i++) { - block_buf[i].compression = COMPRESSION_NONE; - block_buf[i].block_index = i; - block_buf[i].data_len = INCFS_DATA_FILE_BLOCK_SIZE; - block_buf[i].data = ptr_to_u64(data); - } - - fd = open_file_by_id(mount_dir, id, true); - if (fd < 0) - goto failure; - - if (ioctl(fd, INCFS_IOC_FILL_BLOCKS, &fill_blocks) != block_count) - goto failure; - - if (emit_file(cmd_fd, NULL, "very_very_large_file", &id, 1LL << 40, - NULL) < 0) - goto failure; - - result = TEST_SUCCESS; - -failure: - close(fd); - close(cmd_fd); - return result; -} - static char *setup_mount_dir() { struct stat st; @@ -2702,7 +2361,7 @@ int main(int argc, char *argv[]) // NOTE - this abuses the concept of randomness - do *not* ever do this // on a machine for production use - the device will think it has good // randomness when it does not. - fd = open("/dev/urandom", O_WRONLY | O_CLOEXEC); + fd = open("/dev/urandom", O_WRONLY); count = 4096; for (int i = 0; i < 128; ++i) ioctl(fd, RNDADDTOENTCNT, &count); @@ -2733,11 +2392,9 @@ int main(int argc, char *argv[]) MAKE_TEST(work_after_remount_test), MAKE_TEST(child_procs_waiting_for_data_test), MAKE_TEST(multiple_providers_test), + MAKE_TEST(signature_test), MAKE_TEST(hash_tree_test), MAKE_TEST(read_log_test), - MAKE_TEST(get_blocks_test), - MAKE_TEST(get_hash_blocks_test), - MAKE_TEST(large_file), }; #undef MAKE_TEST @@ -2758,7 +2415,7 @@ int main(int argc, char *argv[]) rmdir(mount_dir); if (fails > 0) - ksft_exit_fail(); + ksft_exit_pass(); else ksft_exit_pass(); return 0; diff --git a/tools/testing/selftests/filesystems/incfs/utils.c b/tools/testing/selftests/filesystems/incfs/utils.c index e194f63ba922..08b8452ad0bc 100644 --- a/tools/testing/selftests/filesystems/incfs/utils.c +++ b/tools/testing/selftests/filesystems/incfs/utils.c @@ -2,31 +2,28 @@ /* * Copyright 2018 Google LLC */ -#include -#include -#include -#include #include -#include -#include +#include +#include +#include +#include +#include #include - #include #include -#include -#include - +#include +#include +#include +#include +#include +#include +#include #include #include #include "utils.h" -#ifndef __S_IFREG -#define __S_IFREG S_IFREG -#endif - -int mount_fs(const char *mount_dir, const char *backing_dir, - int read_timeout_ms) +int mount_fs(char *mount_dir, char *backing_dir, int read_timeout_ms) { static const char fs_name[] = INCFS_NAME; char mount_options[512]; @@ -42,107 +39,190 @@ int mount_fs(const char *mount_dir, const char *backing_dir, return result; } -int mount_fs_opt(const char *mount_dir, const char *backing_dir, - const char *opt, bool remount) +int mount_fs_opt(char *mount_dir, char *backing_dir, char *opt) { static const char fs_name[] = INCFS_NAME; int result; - result = mount(backing_dir, mount_dir, fs_name, - remount ? MS_REMOUNT : 0, opt); + result = mount(backing_dir, mount_dir, fs_name, 0, opt); if (result != 0) perror("Error mounting fs."); return result; } -struct hash_section { - uint32_t algorithm; - uint8_t log2_blocksize; - uint32_t salt_size; - /* no salt */ - uint32_t hash_size; - uint8_t hash[SHA256_DIGEST_SIZE]; -} __packed; - -struct signature_blob { - uint32_t version; - uint32_t hash_section_size; - struct hash_section hash_section; - uint32_t signing_section_size; - uint8_t signing_section[]; -} __packed; - -size_t format_signature(void **buf, const char *root_hash, const char *add_data) +int unlink_node(int fd, int parent_ino, char *filename) { - size_t size = sizeof(struct signature_blob) + strlen(add_data) + 1; - struct signature_blob *sb = malloc(size); - - *sb = (struct signature_blob){ - .version = INCFS_SIGNATURE_VERSION, - .hash_section_size = sizeof(struct hash_section), - .hash_section = - (struct hash_section){ - .algorithm = INCFS_HASH_TREE_SHA256, - .log2_blocksize = 12, - .salt_size = 0, - .hash_size = SHA256_DIGEST_SIZE, - }, - .signing_section_size = sizeof(uint32_t) + strlen(add_data) + 1, - }; - - memcpy(sb->hash_section.hash, root_hash, SHA256_DIGEST_SIZE); - memcpy((char *)sb->signing_section, add_data, strlen(add_data) + 1); - *buf = sb; - return size; + return 0; } -int crypto_emit_file(int fd, const char *dir, const char *filename, - incfs_uuid_t *id_out, size_t size, const char *root_hash, - const char *add_data) + +static EVP_PKEY *deserialize_private_key(const char *pem_key) +{ + BIO *bio = NULL; + EVP_PKEY *pkey = NULL; + int len = strlen(pem_key); + + bio = BIO_new_mem_buf(pem_key, len); + if (!bio) + return NULL; + + pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL); + BIO_free(bio); + return pkey; +} + +static X509 *deserialize_cert(const char *pem_cert) +{ + BIO *bio = NULL; + X509 *cert = NULL; + int len = strlen(pem_cert); + + bio = BIO_new_mem_buf(pem_cert, len); + if (!bio) + return NULL; + + cert = PEM_read_bio_X509(bio, NULL, NULL, NULL); + BIO_free(bio); + return cert; +} + +bool sign_pkcs7(const void *data_to_sign, size_t data_size, + char *pkey_pem, char *cert_pem, + void **sig_ret, size_t *sig_size_ret) +{ + /* + * PKCS#7 signing flags: + * + * - PKCS7_BINARY signing binary data, so skip MIME translation + * + * - PKCS7_NOATTR omit extra authenticated attributes, such as + * SMIMECapabilities + * + * - PKCS7_PARTIAL PKCS7_sign() creates a handle only, then + * PKCS7_sign_add_signer() can add a signer later. + * This is necessary to change the message digest + * algorithm from the default of SHA-1. Requires + * OpenSSL 1.0.0 or later. + */ + int pkcs7_flags = PKCS7_BINARY | PKCS7_NOATTR | PKCS7_PARTIAL; + void *sig; + size_t sig_size; + BIO *bio = NULL; + PKCS7 *p7 = NULL; + EVP_PKEY *pkey = NULL; + X509 *cert = NULL; + bool ok = false; + + const EVP_MD *md = EVP_sha256(); + + pkey = deserialize_private_key(pkey_pem); + if (!pkey) { + printf("deserialize_private_key failed\n"); + goto out; + } + + cert = deserialize_cert(cert_pem); + if (!cert) { + printf("deserialize_cert failed\n"); + goto out; + } + + bio = BIO_new_mem_buf(data_to_sign, data_size); + if (!bio) + goto out; + + p7 = PKCS7_sign(NULL, NULL, NULL, bio, pkcs7_flags); + if (!p7) { + printf("failed to initialize PKCS#7 signature object\n"); + goto out; + } + + if (!PKCS7_sign_add_signer(p7, cert, pkey, md, pkcs7_flags)) { + printf("failed to add signer to PKCS#7 signature object\n"); + goto out; + } + + if (PKCS7_final(p7, bio, pkcs7_flags) != 1) { + printf("failed to finalize PKCS#7 signature\n"); + goto out; + } + + BIO_free(bio); + bio = BIO_new(BIO_s_mem()); + if (!bio) { + printf("out of memory\n"); + goto out; + } + + if (i2d_PKCS7_bio(bio, p7) != 1) { + printf("failed to DER-encode PKCS#7 signature object\n"); + goto out; + } + + sig_size = BIO_get_mem_data(bio, &sig); + *sig_ret = malloc(sig_size); + memcpy(*sig_ret, sig, sig_size); + *sig_size_ret = sig_size; + ok = true; +out: + PKCS7_free(p7); + BIO_free(bio); + return ok; +} + +int crypto_emit_file(int fd, char *dir, char *filename, incfs_uuid_t *id_out, + size_t size, const char *root_hash, char *sig, size_t sig_size, + char *add_data) { int mode = __S_IFREG | 0555; - void *signature; - int error = 0; + struct incfs_file_signature_info sig_info = { + .hash_tree_alg = root_hash + ? INCFS_HASH_TREE_SHA256 + : 0, + .root_hash = ptr_to_u64(root_hash), + .additional_data = ptr_to_u64(add_data), + .additional_data_size = strlen(add_data), + .signature = ptr_to_u64(sig), + .signature_size = sig_size, + }; struct incfs_new_file_args args = { .size = size, .mode = mode, .file_name = ptr_to_u64(filename), .directory_path = ptr_to_u64(dir), + .signature_info = ptr_to_u64(&sig_info), .file_attr = 0, .file_attr_len = 0 }; - args.signature_size = format_signature(&signature, root_hash, add_data); - args.signature_info = ptr_to_u64(signature); - md5(filename, strlen(filename), (char *)args.file_id.bytes); - if (ioctl(fd, INCFS_IOC_CREATE_FILE, &args) != 0) { - error = -errno; - goto out; - } + if (ioctl(fd, INCFS_IOC_CREATE_FILE, &args) != 0) + return -errno; *id_out = args.file_id; - -out: - free(signature); - return error; + return 0; } -int emit_file(int fd, const char *dir, const char *filename, - incfs_uuid_t *id_out, size_t size, const char *attr) + +int emit_file(int fd, char *dir, char *filename, incfs_uuid_t *id_out, + size_t size, char *attr) { int mode = __S_IFREG | 0555; - struct incfs_new_file_args args = { .size = size, - .mode = mode, - .file_name = ptr_to_u64(filename), - .directory_path = ptr_to_u64(dir), - .signature_info = ptr_to_u64(NULL), - .signature_size = 0, - .file_attr = ptr_to_u64(attr), - .file_attr_len = - attr ? strlen(attr) : 0 }; + struct incfs_file_signature_info sig_info = { + .hash_tree_alg = 0, + .root_hash = ptr_to_u64(NULL) + }; + struct incfs_new_file_args args = { + .size = size, + .mode = mode, + .file_name = ptr_to_u64(filename), + .directory_path = ptr_to_u64(dir), + .signature_info = ptr_to_u64(&sig_info), + .file_attr = ptr_to_u64(attr), + .file_attr_len = attr ? strlen(attr) : 0 + }; md5(filename, strlen(filename), (char *)args.file_id.bytes); @@ -170,7 +250,7 @@ int get_file_signature(int fd, unsigned char *buf, int buf_size) return -errno; } -loff_t get_file_size(const char *name) +loff_t get_file_size(char *name) { struct stat st; @@ -179,27 +259,27 @@ loff_t get_file_size(const char *name) return -ENOENT; } -int open_commands_file(const char *mount_dir) +int open_commands_file(char *mount_dir) { char cmd_file[255]; int cmd_fd; snprintf(cmd_file, ARRAY_SIZE(cmd_file), "%s/%s", mount_dir, INCFS_PENDING_READS_FILENAME); - cmd_fd = open(cmd_file, O_RDONLY | O_CLOEXEC); + cmd_fd = open(cmd_file, O_RDONLY); if (cmd_fd < 0) perror("Can't open commands file"); return cmd_fd; } -int open_log_file(const char *mount_dir) +int open_log_file(char *mount_dir) { char cmd_file[255]; int cmd_fd; snprintf(cmd_file, ARRAY_SIZE(cmd_file), "%s/.log", mount_dir); - cmd_fd = open(cmd_file, O_RDWR | O_CLOEXEC); + cmd_fd = open(cmd_file, O_RDWR); if (cmd_fd < 0) perror("Can't open log file"); return cmd_fd; @@ -278,7 +358,7 @@ out: return result; } -void sha256(const char *data, size_t dsize, char *hash) +void sha256(char *data, size_t dsize, char *hash) { SHA256_CTX ctx; @@ -287,7 +367,7 @@ void sha256(const char *data, size_t dsize, char *hash) SHA256_Final((unsigned char *)hash, &ctx); } -void md5(const char *data, size_t dsize, char *hash) +void md5(char *data, size_t dsize, char *hash) { MD5_CTX ctx; diff --git a/tools/testing/selftests/filesystems/incfs/utils.h b/tools/testing/selftests/filesystems/incfs/utils.h index 9af63e4e922c..9c9ba3c5f70a 100644 --- a/tools/testing/selftests/filesystems/incfs/utils.h +++ b/tools/testing/selftests/filesystems/incfs/utils.h @@ -5,12 +5,10 @@ #include #include -#include +#include "../../include/uapi/linux/incrementalfs.h" #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0])) -#define __packed __attribute__((__packed__)) - #ifdef __LP64__ #define ptr_to_u64(p) ((__u64)p) #else @@ -19,11 +17,9 @@ #define SHA256_DIGEST_SIZE 32 -int mount_fs(const char *mount_dir, const char *backing_dir, - int read_timeout_ms); +int mount_fs(char *mount_dir, char *backing_dir, int read_timeout_ms); -int mount_fs_opt(const char *mount_dir, const char *backing_dir, - const char *opt, bool remount); +int mount_fs_opt(char *mount_dir, char *backing_dir, char *opt); int get_file_bmap(int cmd_fd, int ino, unsigned char *buf, int buf_size); @@ -32,26 +28,32 @@ int get_file_signature(int fd, unsigned char *buf, int buf_size); int emit_node(int fd, char *filename, int *ino_out, int parent_ino, size_t size, mode_t mode, char *attr); -int emit_file(int fd, const char *dir, const char *filename, - incfs_uuid_t *id_out, size_t size, const char *attr); +int emit_file(int fd, char *dir, char *filename, incfs_uuid_t *id_out, + size_t size, char *attr); -int crypto_emit_file(int fd, const char *dir, const char *filename, - incfs_uuid_t *id_out, size_t size, const char *root_hash, - const char *add_data); +int crypto_emit_file(int fd, char *dir, char *filename, incfs_uuid_t *id_out, + size_t size, const char *root_hash, char *sig, size_t sig_size, + char *add_data); -loff_t get_file_size(const char *name); +int unlink_node(int fd, int parent_ino, char *filename); -int open_commands_file(const char *mount_dir); +loff_t get_file_size(char *name); -int open_log_file(const char *mount_dir); +int open_commands_file(char *mount_dir); + +int open_log_file(char *mount_dir); int wait_for_pending_reads(int fd, int timeout_ms, struct incfs_pending_read_info *prs, int prs_count); char *concat_file_name(const char *dir, char *file); -void sha256(const char *data, size_t dsize, char *hash); +void sha256(char *data, size_t dsize, char *hash); -void md5(const char *data, size_t dsize, char *hash); +void md5(char *data, size_t dsize, char *hash); + +bool sign_pkcs7(const void *data_to_sign, size_t data_size, + char *pkey_pem, char *cert_pem, + void **sig_ret, size_t *sig_size_ret); int delete_dir_tree(const char *path); From 7764b501b90efb2219dd73fd528274a3a5a380a6 Mon Sep 17 00:00:00 2001 From: Pavankumar Kondeti Date: Thu, 16 Jul 2020 00:49:59 +0530 Subject: [PATCH 255/592] sched/walt: Improve the scheduler This change is for general scheduler improvements. Change-Id: I84f84973b815fb0bb95d1d950a4ac90be11f9470 Signed-off-by: Pavankumar Kondeti --- kernel/sched/sched.h | 7 +++---- kernel/sched/tune.c | 22 +++++++++++++++++----- kernel/sched/walt.c | 32 +++++++++++--------------------- 3 files changed, 31 insertions(+), 30 deletions(-) diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index 38aae2631f1d..98aa8c1a6eb8 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -2867,15 +2867,14 @@ extern void clear_top_tasks_bitmap(unsigned long *bitmap); #if defined(CONFIG_SCHED_TUNE) extern bool task_sched_boost(struct task_struct *p); extern int sync_cgroup_colocation(struct task_struct *p, bool insert); -extern bool same_schedtune(struct task_struct *tsk1, struct task_struct *tsk2); +extern bool schedtune_task_colocated(struct task_struct *p); extern void update_cgroup_boost_settings(void); extern void restore_cgroup_boost_settings(void); #else -static inline bool -same_schedtune(struct task_struct *tsk1, struct task_struct *tsk2) +static inline bool schedtune_task_colocated(struct task_struct *p) { - return true; + return false; } static inline bool task_sched_boost(struct task_struct *p) diff --git a/kernel/sched/tune.c b/kernel/sched/tune.c index 51862ccdb719..5670542c774e 100644 --- a/kernel/sched/tune.c +++ b/kernel/sched/tune.c @@ -150,11 +150,6 @@ static inline void init_sched_boost(struct schedtune *st) st->colocate_update_disabled = false; } -bool same_schedtune(struct task_struct *tsk1, struct task_struct *tsk2) -{ - return task_schedtune(tsk1) == task_schedtune(tsk2); -} - void update_cgroup_boost_settings(void) { int i; @@ -482,6 +477,23 @@ static int sched_colocate_write(struct cgroup_subsys_state *css, return 0; } +bool schedtune_task_colocated(struct task_struct *p) +{ + struct schedtune *st; + bool colocated; + + if (unlikely(!schedtune_initialized)) + return false; + + /* Get task boost value */ + rcu_read_lock(); + st = task_schedtune(p); + colocated = st->colocate; + rcu_read_unlock(); + + return colocated; +} + #else /* CONFIG_SCHED_WALT */ static inline void init_sched_boost(struct schedtune *st) { } diff --git a/kernel/sched/walt.c b/kernel/sched/walt.c index fbf12f07b4dc..be19e3b0c25d 100644 --- a/kernel/sched/walt.c +++ b/kernel/sched/walt.c @@ -2514,7 +2514,6 @@ static void transfer_busy_time(struct rq *rq, struct related_thread_group *grp, * Enable colocation and frequency aggregation for all threads in a process. * The children inherits the group id from the parent. */ -unsigned int __read_mostly sysctl_sched_enable_thread_grouping; struct related_thread_group *related_thread_groups[MAX_NUM_CGROUP_COLOC_ID]; static LIST_HEAD(active_related_thread_groups); @@ -2780,34 +2779,25 @@ void add_new_task_to_grp(struct task_struct *new) { unsigned long flags; struct related_thread_group *grp; - struct task_struct *leader = new->group_leader; - unsigned int leader_grp_id = sched_get_group_id(leader); - if (!sysctl_sched_enable_thread_grouping && - leader_grp_id != DEFAULT_CGROUP_COLOC_ID) + /* + * If the task does not belong to colocated schedtune + * cgroup, nothing to do. We are checking this without + * lock. Even if there is a race, it will be added + * to the co-located cgroup via cgroup attach. + */ + if (!schedtune_task_colocated(new)) return; - if (thread_group_leader(new)) - return; - - if (leader_grp_id == DEFAULT_CGROUP_COLOC_ID) { - if (!same_schedtune(new, leader)) - return; - } - + grp = lookup_related_thread_group(DEFAULT_CGROUP_COLOC_ID); write_lock_irqsave(&related_thread_group_lock, flags); - rcu_read_lock(); - grp = task_related_thread_group(leader); - rcu_read_unlock(); - /* * It's possible that someone already added the new task to the - * group. A leader's thread group is updated prior to calling - * this function. It's also possible that the leader has exited - * the group. In either case, there is nothing else to do. + * group. or it might have taken out from the colocated schedtune + * cgroup. check these conditions under lock. */ - if (!grp || new->grp) { + if (!schedtune_task_colocated(new) || new->grp) { write_unlock_irqrestore(&related_thread_group_lock, flags); return; } From f8386f0c67f4069993c16c83074d4b9f9b347d43 Mon Sep 17 00:00:00 2001 From: Ajay Agarwal Date: Mon, 29 Jun 2020 13:39:29 +0530 Subject: [PATCH 256/592] usb: dwc3-msm: Add markers for peripheral bus resume Add prints and markers for peripheral bus resume. While at it, also fix USB resume print in composite driver. Change-Id: Idaaba41e59ee2e93c1fd5956d352bdce673247b3 Signed-off-by: Ajay Agarwal --- drivers/usb/dwc3/dwc3-msm.c | 13 +++++++++++++ drivers/usb/gadget/composite.c | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index 9bfad4bfbb02..f35b1a0b42f5 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -47,6 +47,7 @@ #include #include #include +#include #include "power.h" #include "core.h" @@ -3294,6 +3295,12 @@ static irqreturn_t msm_dwc3_pwr_irq(int irq, void *data) dwc->t_pwr_evt_irq = ktime_get(); dev_dbg(mdwc->dev, "%s received\n", __func__); + + if (mdwc->drd_state == DRD_STATE_PERIPHERAL_SUSPEND) { + dev_info(mdwc->dev, "USB Resume start\n"); + place_marker("M - USB device resume started"); + } + /* * When in Low Power Mode, can't read PWR_EVNT_IRQ_STAT_REG to acertain * which interrupts have been triggered, as the clocks are disabled. @@ -5161,6 +5168,12 @@ static int dwc3_msm_pm_resume(struct device *dev) flush_workqueue(mdwc->dwc3_wq); atomic_set(&mdwc->pm_suspended, 0); + if (atomic_read(&dwc->in_lpm) && + mdwc->drd_state == DRD_STATE_PERIPHERAL_SUSPEND) { + dev_info(mdwc->dev, "USB Resume start\n"); + place_marker("M - USB device resume started"); + } + if (!dwc->ignore_wakeup_src_in_hostmode || !mdwc->in_host_mode) { /* kick in otg state machine */ queue_work(mdwc->dwc3_wq, &mdwc->resume_work); diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 73f1fd35e386..ad9f3f423e61 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -2431,7 +2431,7 @@ void composite_resume(struct usb_gadget *gadget) /* REVISIT: should we have config level * suspend/resume callbacks? */ - INFO(cdev, "USB Resume\n"); + INFO(cdev, "USB Resume end\n"); place_marker("M - USB device is resumed"); if (cdev->driver->resume) cdev->driver->resume(cdev); From 4e8ef6147eea6065a4fa11bd4bae3c1dd405a665 Mon Sep 17 00:00:00 2001 From: Jeya R Date: Wed, 22 Jul 2020 16:53:49 +0530 Subject: [PATCH 257/592] msm: ADSPRPC: Size check before allocating memory from DMA For allocating memory from DMA we need to do a size check. This validation is required to avoid any improper paging request. We already have the range in which the size is expected to be. Change-Id: I72919a8807a7e3bacb7f8353a2aabb8cc6c19f0f Acked-by: Ekansh Gupta Signed-off-by: Jeya R --- drivers/char/adsprpc.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 8ed94351e897..ada4f3a4c81c 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -648,12 +648,20 @@ static int fastrpc_mmap_find(struct fastrpc_file *fl, int fd, static int dma_alloc_memory(dma_addr_t *region_phys, void **vaddr, size_t size, unsigned long dma_attr) { + int err = 0; struct fastrpc_apps *me = &gfa; if (me->dev == NULL) { pr_err("device adsprpc-mem is not initialized\n"); return -ENODEV; } + VERIFY(err, size > 0 && size < MAX_SIZE_LIMIT); + if (err) { + err = -EFAULT; + pr_err("adsprpc: %s: invalid allocation size 0x%zx\n", + __func__, size); + return err; + } *vaddr = dma_alloc_attrs(me->dev, size, region_phys, GFP_KERNEL, dma_attr); if (IS_ERR_OR_NULL(*vaddr)) { From f719967e6607dc40aa3b1cc67dd92643714e0e4b Mon Sep 17 00:00:00 2001 From: Deepak Dimri Date: Wed, 22 Jul 2020 22:18:03 +0530 Subject: [PATCH 258/592] iio: adc: Add channels AMUX1 and AMUX3 for voltage reading Add channels AMUX1 and AMUX3 for reading voltage for SA2150p based CCARD. Change-Id: Ib6f7215b0af018a06b320671e114d010b68f8b96 Signed-off-by: Deepak Dimri --- drivers/iio/adc/qcom-spmi-adc5.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/iio/adc/qcom-spmi-adc5.c b/drivers/iio/adc/qcom-spmi-adc5.c index f34c2ac8490e..4ba747ce108d 100644 --- a/drivers/iio/adc/qcom-spmi-adc5.c +++ b/drivers/iio/adc/qcom-spmi-adc5.c @@ -796,6 +796,10 @@ static const struct adc_channels adc_chans_rev2[ADC_MAX_CHANNEL] = { SCALE_HW_CALIB_THERM_100K_PULLUP) [ANA_IN] = ADC_CHAN_TEMP("drax_temp", 1, SCALE_HW_CALIB_PMIC_THERM) + [ADC_AMUX_THM1] = ADC_CHAN_VOLT("amux_thm1", 1, + SCALE_HW_CALIB_DEFAULT) + [ADC_AMUX_THM3] = ADC_CHAN_VOLT("amux_thm3", 1, + SCALE_HW_CALIB_DEFAULT) }; static int adc_get_dt_channel_data(struct device *dev, From 42b329536d2b8b0d363c8fb00909f4a69437f6eb Mon Sep 17 00:00:00 2001 From: Arun Prakash Date: Wed, 22 Jul 2020 17:31:55 +0530 Subject: [PATCH 259/592] ARM: dts: msm: Add UFS support for kdump kernel on sa8155 Add UFS support for kdump kernel on sa8155. Change-Id: I6bfe75b8474077c28d79cf65979d5e39c2072a02 Signed-off-by: Arun Prakash --- arch/arm64/boot/dts/qcom/sa8155-capture.dtsi | 176 +++++++++++++++++++ 1 file changed, 176 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sa8155-capture.dtsi b/arch/arm64/boot/dts/qcom/sa8155-capture.dtsi index 5c3d5c1c20ea..b876b34ae0c9 100644 --- a/arch/arm64/boot/dts/qcom/sa8155-capture.dtsi +++ b/arch/arm64/boot/dts/qcom/sa8155-capture.dtsi @@ -345,6 +345,178 @@ , <0 1000>; }; + + ufs_ice: ufsice@1d90000 { + compatible = "qcom,ice"; + reg = <0x1d90000 0x8000>; + qcom,enable-ice-clk; + clock-names = "ufs_core_clk", "bus_clk", + "iface_clk", "ice_core_clk"; + clocks = <&clock_gcc GCC_UFS_PHY_AXI_CLK>, + <&clock_gcc GCC_UFS_MEM_CLKREF_CLK>, + <&clock_gcc GCC_UFS_PHY_AHB_CLK>, + <&clock_gcc GCC_UFS_PHY_ICE_CORE_CLK>; + qcom,op-freq-hz = <0>, <0>, <0>, <300000000>; + vdd-hba-supply = <&ufs_phy_gdsc>; + qcom,msm-bus,name = "ufs_ice_noc"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + <1 650 0 0>, /* No vote */ + <1 650 1000 0>; /* Max. bandwidth */ + qcom,bus-vector-names = "MIN", + "MAX"; + qcom,instance-type = "ufs"; + }; + + ufsphy_mem: ufsphy_mem@1d87000 { + compatible = "qcom,ufs-phy-qmp-v4"; + reg = <0x1d87000 0xda8>; /* PHY regs */ + reg-names = "phy_mem"; + #phy-cells = <0>; + ufs-qcom-crypto = <&ufs_ice>; + + lanes-per-direction = <2>; + + clock-names = "ref_clk_src", + "ref_clk", + "ref_aux_clk"; + clocks = <&clock_rpmh RPMH_CXO_CLK>, + <&clock_gcc GCC_UFS_MEM_CLKREF_CLK>, + <&clock_gcc GCC_UFS_PHY_PHY_AUX_CLK>; + + vdda-pll-supply = <&pm8150_2_l8>; + vdda-phy-max-microamp = <87100>; + vdda-pll-max-microamp = <18300>; + vdda-phy-supply = <&pm8150_1_l5>; + + status = "ok"; + }; + + ufshc_mem: ufshc@1d84000 { + compatible = "qcom,ufshc"; + reg = <0x1d84000 0x2500>; + interrupts = <0 265 0>; + phys = <&ufsphy_mem>; + phy-names = "ufsphy"; + ufs-qcom-crypto = <&ufs_ice>; + + lanes-per-direction = <2>; + dev-ref-clk-freq = <0>; /* 19.2 MHz */ + + clock-names = + "core_clk", + "bus_aggr_clk", + "iface_clk", + "core_clk_unipro", + "core_clk_ice", + "ref_clk", + "tx_lane0_sync_clk", + "rx_lane0_sync_clk", + "rx_lane1_sync_clk"; + clocks = + <&clock_gcc GCC_UFS_PHY_AXI_CLK>, + <&clock_gcc GCC_AGGRE_UFS_PHY_AXI_CLK>, + <&clock_gcc GCC_UFS_PHY_AHB_CLK>, + <&clock_gcc GCC_UFS_PHY_UNIPRO_CORE_CLK>, + <&clock_gcc GCC_UFS_PHY_ICE_CORE_CLK>, + <&clock_rpmh RPMH_CXO_CLK>, + <&clock_gcc GCC_UFS_PHY_TX_SYMBOL_0_CLK>, + <&clock_gcc GCC_UFS_PHY_RX_SYMBOL_0_CLK>, + <&clock_gcc GCC_UFS_PHY_RX_SYMBOL_1_CLK>; + freq-table-hz = + <37500000 300000000>, + <0 0>, + <0 0>, + <37500000 300000000>, + <37500000 300000000>, + <0 0>, + <0 0>, + <0 0>, + <0 0>; + + qcom,msm-bus,name = "ufshc_mem"; + qcom,msm-bus,num-cases = <26>; + qcom,msm-bus,num-paths = <2>; + qcom,msm-bus,vectors-KBps = + /* + * During HS G3 UFS runs at nominal voltage corner, vote + * higher bandwidth to push other buses in the data path + * to run at nominal to achieve max throughput. + * 4GBps pushes BIMC to run at nominal. + * 200MBps pushes CNOC to run at nominal. + * Vote for half of this bandwidth for HS G3 1-lane. + * For max bandwidth, vote high enough to push the buses + * to run in turbo voltage corner. + */ + <123 512 0 0>, <1 757 0 0>, /* No vote */ + <123 512 922 0>, <1 757 1000 0>, /* PWM G1 */ + <123 512 1844 0>, <1 757 1000 0>, /* PWM G2 */ + <123 512 3688 0>, <1 757 1000 0>, /* PWM G3 */ + <123 512 7376 0>, <1 757 1000 0>, /* PWM G4 */ + <123 512 1844 0>, <1 757 1000 0>, /* PWM G1 L2 */ + <123 512 3688 0>, <1 757 1000 0>, /* PWM G2 L2 */ + <123 512 7376 0>, <1 757 1000 0>, /* PWM G3 L2 */ + <123 512 14752 0>, <1 757 1000 0>, /* PWM G4 L2 */ + <123 512 127796 0>, <1 757 1000 0>, /* HS G1 RA */ + <123 512 255591 0>, <1 757 1000 0>, /* HS G2 RA */ + <123 512 2097152 0>, <1 757 102400 0>, /* HS G3 RA */ + <123 512 4194304 0>, <1 757 204800 0>, /* HS G4 RA */ + <123 512 255591 0>, <1 757 1000 0>, /* HS G1 RA L2 */ + <123 512 511181 0>, <1 757 1000 0>, /* HS G2 RA L2 */ + <123 512 4194304 0>, <1 757 204800 0>, /* HS G3 RA L2 */ + <123 512 8388608 0>, <1 757 409600 0>, /* HS G4 RA L2 */ + <123 512 149422 0>, <1 757 1000 0>, /* HS G1 RB */ + <123 512 298189 0>, <1 757 1000 0>, /* HS G2 RB */ + <123 512 2097152 0>, <1 757 102400 0>, /* HS G3 RB */ + <123 512 4194304 0>, <1 757 204800 0>, /* HS G4 RB */ + <123 512 298189 0>, <1 757 1000 0>, /* HS G1 RB L2 */ + <123 512 596378 0>, <1 757 1000 0>, /* HS G2 RB L2 */ + /* As UFS working in HS G3 RB L2 mode, aggregated + * bandwidth (AB) should take care of providing + * optimum throughput requested. However, as tested, + * in order to scale up CNOC clock, instantaneous + * bindwidth (IB) needs to be given a proper value too. + */ + <123 512 4194304 0>, <1 757 204800 409600>, /* HS G3 RB L2 */ + <123 512 8388608 0>, <1 757 409600 409600>, /* HS G4 RB L2 */ + <123 512 7643136 0>, <1 757 307200 0>; /* Max. bandwidth */ + + qcom,bus-vector-names = "MIN", + "PWM_G1_L1", "PWM_G2_L1", "PWM_G3_L1", "PWM_G4_L1", + "PWM_G1_L2", "PWM_G2_L2", "PWM_G3_L2", "PWM_G4_L2", + "HS_RA_G1_L1", "HS_RA_G2_L1", "HS_RA_G3_L1", "HS_RA_G4_L1", + "HS_RA_G1_L2", "HS_RA_G2_L2", "HS_RA_G3_L2", "HS_RA_G4_L2", + "HS_RB_G1_L1", "HS_RB_G2_L1", "HS_RB_G3_L1", "HS_RB_G4_L1", + "HS_RB_G1_L2", "HS_RB_G2_L2", "HS_RB_G3_L2", "HS_RB_G4_L2", + "MAX"; + + /* PM QoS */ + qcom,pm-qos-cpu-groups = <0x0f 0xf0>; + qcom,pm-qos-cpu-group-latency-us = <44 44>; + qcom,pm-qos-default-cpu = <0>; + + pinctrl-names = "dev-reset-assert", "dev-reset-deassert"; + pinctrl-0 = <&ufs_dev_reset_assert>; + pinctrl-1 = <&ufs_dev_reset_deassert>; + + resets = <&clock_gcc GCC_UFS_PHY_BCR>; + reset-names = "core_reset"; + + vdd-hba-supply = <&ufs_phy_gdsc>; + vdd-hba-fixed-regulator; + vcc-supply = <&pm8150_1_l10>; + vcc-voltage-level = <2950000 2960000>; + vccq2-supply = <&pm8150_1_s4>; + vcc-max-microamp = <750000>; + vccq2-max-microamp = <750000>; + + qcom,vddp-ref-clk-supply = <&pm8150_2_l5>; + qcom,vddp-ref-clk-max-microamp = <100>; + + status = "ok"; + }; + }; &apps_smmu { @@ -362,6 +534,10 @@ <0x1084 0x1 0x303>; }; +&ufs_phy_gdsc { + status = "ok"; +}; + #include "sa8155-regulator.dtsi" #include "sm8150-pinctrl.dtsi" #include "sm8150-bus.dtsi" From 4d761a7dbb610d9acd59c77ce24cfb35e82c0701 Mon Sep 17 00:00:00 2001 From: Ray Zhang Date: Thu, 23 Jul 2020 19:59:15 +0800 Subject: [PATCH 260/592] drm/msm/sde: initialize sde_encoder_wait_info before usage wait_info is not initialized in some cases, so fix it in sde driver. Change-Id: I7224cade5f088410dbfa1d95bbb0b05d3fbfde47 Signed-off-by: Ray Zhang --- drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c | 8 ++++---- drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c | 4 ++-- drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c index ef0f55041a9f..3d31c6497f6d 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c @@ -708,7 +708,7 @@ static int _sde_encoder_phys_cmd_wait_for_idle( { struct sde_encoder_phys_cmd *cmd_enc = to_sde_encoder_phys_cmd(phys_enc); - struct sde_encoder_wait_info wait_info = {NULL}; + struct sde_encoder_wait_info wait_info = {0}; bool recovery_events; int ret; @@ -761,7 +761,7 @@ static int _sde_encoder_phys_cmd_wait_for_autorefresh_done( { struct sde_encoder_phys_cmd *cmd_enc = to_sde_encoder_phys_cmd(phys_enc); - struct sde_encoder_wait_info wait_info = {NULL}; + struct sde_encoder_wait_info wait_info = {0}; int ret = 0; if (!phys_enc) { @@ -1386,7 +1386,7 @@ static int _sde_encoder_phys_cmd_wait_for_wr_ptr( { struct sde_encoder_phys_cmd *cmd_enc = to_sde_encoder_phys_cmd(phys_enc); - struct sde_encoder_wait_info wait_info = {NULL}; + struct sde_encoder_wait_info wait_info = {0}; int ret; bool frame_pending = true; struct sde_hw_ctl *ctl; @@ -1536,7 +1536,7 @@ static int sde_encoder_phys_cmd_wait_for_vblank( { int rc = 0; struct sde_encoder_phys_cmd *cmd_enc; - struct sde_encoder_wait_info wait_info = {NULL}; + struct sde_encoder_wait_info wait_info = {0}; if (!phys_enc) return -EINVAL; diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c index 34ebe8d2503d..c6c2c99ef496 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -945,7 +945,7 @@ static void sde_encoder_phys_vid_get_hw_resources( static int _sde_encoder_phys_vid_wait_for_vblank( struct sde_encoder_phys *phys_enc, bool notify) { - struct sde_encoder_wait_info wait_info; + struct sde_encoder_wait_info wait_info = {0}; int ret = 0; u32 event = 0; u32 event_helper = 0; diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c index 2e81e31288b0..e79450e2b941 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2020 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1227,7 +1227,7 @@ static int _sde_encoder_phys_wb_wait_for_commit_done( u32 event = 0; u64 wb_time = 0; int rc = 0; - struct sde_encoder_wait_info wait_info; + struct sde_encoder_wait_info wait_info = {0}; /* Return EWOULDBLOCK since we know the wait isn't necessary */ if (phys_enc->enable_state == SDE_ENC_DISABLED) { From ea07f9fa9ca48487d5083f6e57bafb8579e32861 Mon Sep 17 00:00:00 2001 From: Ray Zhang Date: Thu, 23 Jul 2020 20:08:32 +0800 Subject: [PATCH 261/592] drm/msm/sde: avoid frame_done event trigger for idle scenario Current sde video mode encoder triggers frame done event without checking pending frame count in vblank_wait API call. That may lead to multiple frame_done events for last frame during encoder disable sequence. It can be avoided by managing frame_done event trigger along with retire fence because retire fence trigger always checks the pending frame count. It also avoids the frame_event callback from two different places and reduced event thread workload. Change-Id: I4bf0723f559c8c235bf56d8a676f6b6e8b6d6381 Signed-off-by: Dhaval Patel Signed-off-by: Ray Zhang --- .../gpu/drm/msm/sde/sde_encoder_phys_vid.c | 34 ++++++++----------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c index c6c2c99ef496..426870b57164 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c @@ -597,7 +597,8 @@ static void sde_encoder_phys_vid_vblank_irq(void *arg, int irq_idx) if (sde_encoder_phys_vid_is_master(phys_enc)) { if (atomic_add_unless(&phys_enc->pending_retire_fence_cnt, -1, 0)) - event |= SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE | + event |= SDE_ENCODER_FRAME_EVENT_DONE | + SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE | SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE; } @@ -616,9 +617,10 @@ not_flushed: phys_enc); SDE_EVT32_IRQ(DRMID(phys_enc->parent), phys_enc->hw_intf->idx - INTF_0, - old_cnt, new_cnt, reset_status ? SDE_EVTLOG_ERROR : 0, + old_cnt, atomic_read(&phys_enc->pending_kickoff_cnt), + reset_status ? SDE_EVTLOG_ERROR : 0, flush_register, event, - pend_ret_fence_cnt); + atomic_read(&phys_enc->pending_retire_fence_cnt)); /* Signal any waiting atomic commit thread */ wake_up_all(&phys_enc->pending_kickoff_wq); @@ -947,27 +949,25 @@ static int _sde_encoder_phys_vid_wait_for_vblank( { struct sde_encoder_wait_info wait_info = {0}; int ret = 0; - u32 event = 0; - u32 event_helper = 0; + u32 event = 0, event_helper = 0; if (!phys_enc) { pr_err("invalid encoder\n"); return -EINVAL; } - wait_info.wq = &phys_enc->pending_kickoff_wq; - wait_info.atomic_cnt = &phys_enc->pending_kickoff_cnt; - wait_info.timeout_ms = KICKOFF_TIMEOUT_MS; - if (!sde_encoder_phys_vid_is_master(phys_enc)) { /* signal done for slave video encoder, unless it is pp-split */ if (!_sde_encoder_phys_is_ppsplit(phys_enc) && notify) { event = SDE_ENCODER_FRAME_EVENT_DONE; goto end; } - return 0; } + wait_info.wq = &phys_enc->pending_kickoff_wq; + wait_info.atomic_cnt = &phys_enc->pending_kickoff_cnt; + wait_info.timeout_ms = KICKOFF_TIMEOUT_MS; + /* Wait for kickoff to complete */ ret = sde_encoder_helper_wait_for_irq(phys_enc, INTR_IDX_VSYNC, &wait_info); @@ -975,15 +975,11 @@ static int _sde_encoder_phys_vid_wait_for_vblank( event_helper = SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE | SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE; - if (notify) { - if (ret == -ETIMEDOUT) { - event = SDE_ENCODER_FRAME_EVENT_ERROR; - if (atomic_add_unless( - &phys_enc->pending_retire_fence_cnt, -1, 0)) - event |= event_helper; - } else if (!ret) { - event = SDE_ENCODER_FRAME_EVENT_DONE; - } + if (notify && (ret == -ETIMEDOUT)) { + event = SDE_ENCODER_FRAME_EVENT_ERROR; + if (atomic_add_unless(&phys_enc->pending_retire_fence_cnt, + -1, 0)) + event |= event_helper; } end: From ffba31d28364283635e018d1302c904a95fa6295 Mon Sep 17 00:00:00 2001 From: Ray Zhang Date: Thu, 23 Jul 2020 20:19:59 +0800 Subject: [PATCH 262/592] drm/msm/sde: trigger single frame_done evt for vid encoder Commit 5db4349803d6 ("drm/msm/sde: avoid frame_done event trigger for idle scenario") supports frame_done event merging with release and retire fence for video mode. This works for single dsi display but it causes issue for dual dsi display. Dual dsi display needs two frame_done events in current design. The second dummy frame_done event is generated by physical video mode display. This patch simplifies the frame_done event trigger for video mode by generating single event. It aligns the logic with wb display. Command mode display still waits for two pp_done IRQs and triggers the frame_done interrupt when both events are arrived. Change-Id: I8d5a15d1d478001450b3e86a84f19e031f777d8d Signed-off-by: Dhaval Patel Signed-off-by: Ray Zhang --- drivers/gpu/drm/msm/sde/sde_encoder.c | 13 ++++-- .../gpu/drm/msm/sde/sde_encoder_phys_vid.c | 44 ++++++------------- 2 files changed, 23 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c index 1cfa67a88d31..e598ce85fc9e 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder.c @@ -3662,7 +3662,7 @@ static void sde_encoder_frame_done_callback( { struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc); unsigned int i; - bool trigger = true; + bool trigger = true, is_cmd_mode; enum sde_rm_topology_name topology = SDE_RM_TOPOLOGY_NONE; if (!drm_enc || !sde_enc->cur_master) { @@ -3674,10 +3674,12 @@ static void sde_encoder_frame_done_callback( sde_enc->crtc_frame_event_cb_data.connector = sde_enc->cur_master->connector; + is_cmd_mode = sde_enc->disp_info.capabilities & + MSM_DISPLAY_CAP_CMD_MODE; if (event & (SDE_ENCODER_FRAME_EVENT_DONE | SDE_ENCODER_FRAME_EVENT_ERROR - | SDE_ENCODER_FRAME_EVENT_PANEL_DEAD)) { + | SDE_ENCODER_FRAME_EVENT_PANEL_DEAD) && is_cmd_mode) { if (ready_phys->connector) topology = sde_connector_get_topology_name( ready_phys->connector); @@ -3717,9 +3719,14 @@ static void sde_encoder_frame_done_callback( atomic_set(&sde_enc->frame_done_cnt[i], 0); } } else { - if (sde_enc->crtc_frame_event_cb) + if (sde_enc->crtc_frame_event_cb) { + if (!is_cmd_mode) + sde_encoder_resource_control(drm_enc, + SDE_ENC_RC_EVENT_FRAME_DONE); + sde_enc->crtc_frame_event_cb( &sde_enc->crtc_frame_event_cb_data, event); + } } } diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c index 426870b57164..670c405b6605 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c @@ -594,12 +594,11 @@ static void sde_encoder_phys_vid_vblank_irq(void *arg, int irq_idx) pend_ret_fence_cnt = atomic_read(&phys_enc->pending_retire_fence_cnt); /* signal only for master, where there is a pending kickoff */ - if (sde_encoder_phys_vid_is_master(phys_enc)) { - if (atomic_add_unless(&phys_enc->pending_retire_fence_cnt, - -1, 0)) - event |= SDE_ENCODER_FRAME_EVENT_DONE | - SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE | - SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE; + if (sde_encoder_phys_vid_is_master(phys_enc) && + atomic_add_unless(&phys_enc->pending_retire_fence_cnt, -1, 0)) { + event = SDE_ENCODER_FRAME_EVENT_DONE | + SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE | + SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE; } not_flushed: @@ -949,21 +948,15 @@ static int _sde_encoder_phys_vid_wait_for_vblank( { struct sde_encoder_wait_info wait_info = {0}; int ret = 0; - u32 event = 0, event_helper = 0; + u32 event = SDE_ENCODER_FRAME_EVENT_ERROR | + SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE | + SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE; if (!phys_enc) { pr_err("invalid encoder\n"); return -EINVAL; } - if (!sde_encoder_phys_vid_is_master(phys_enc)) { - /* signal done for slave video encoder, unless it is pp-split */ - if (!_sde_encoder_phys_is_ppsplit(phys_enc) && notify) { - event = SDE_ENCODER_FRAME_EVENT_DONE; - goto end; - } - } - wait_info.wq = &phys_enc->pending_kickoff_wq; wait_info.atomic_cnt = &phys_enc->pending_kickoff_cnt; wait_info.timeout_ms = KICKOFF_TIMEOUT_MS; @@ -972,23 +965,12 @@ static int _sde_encoder_phys_vid_wait_for_vblank( ret = sde_encoder_helper_wait_for_irq(phys_enc, INTR_IDX_VSYNC, &wait_info); - event_helper = SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE - | SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE; - - if (notify && (ret == -ETIMEDOUT)) { - event = SDE_ENCODER_FRAME_EVENT_ERROR; - if (atomic_add_unless(&phys_enc->pending_retire_fence_cnt, - -1, 0)) - event |= event_helper; - } - -end: - SDE_EVT32(DRMID(phys_enc->parent), event, notify, ret, - ret ? SDE_EVTLOG_FATAL : 0); - if (phys_enc->parent_ops.handle_frame_done && event) + if (notify && (ret == -ETIMEDOUT) && + atomic_add_unless(&phys_enc->pending_retire_fence_cnt, -1, 0) && + phys_enc->parent_ops.handle_frame_done) phys_enc->parent_ops.handle_frame_done( - phys_enc->parent, phys_enc, - event); + phys_enc->parent, phys_enc, event); + return ret; } From d488d056d2b61f3bcadae3ad64d0eaf52bd6b821 Mon Sep 17 00:00:00 2001 From: Raghavendra Ambadas Date: Fri, 17 Jul 2020 21:30:00 +0800 Subject: [PATCH 263/592] clk: qcom: mdss: Add check to read the gdsc status Add check for SDM660 target and 12NM pll interface to read the gdsc status bit. Change-Id: I8bdee9deb9b68844769c2ab66a87d79e8659b6fd Signed-off-by: Nirmal Abraham --- drivers/clk/qcom/mdss/mdss-pll.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/clk/qcom/mdss/mdss-pll.h b/drivers/clk/qcom/mdss/mdss-pll.h index 4e3af2f03b8b..070c62ea69d7 100644 --- a/drivers/clk/qcom/mdss/mdss-pll.h +++ b/drivers/clk/qcom/mdss/mdss-pll.h @@ -219,8 +219,14 @@ static inline bool is_gdsc_disabled(struct mdss_pll_resources *pll_res) WARN(1, "gdsc_base register is not defined\n"); return true; } - ret = ((readl_relaxed(pll_res->gdsc_base + 0x4) & BIT(31)) && - (!(readl_relaxed(pll_res->gdsc_base) & BIT(0)))) ? false : true; + if ((pll_res->target_id == MDSS_PLL_TARGET_SDM660) || + (pll_res->pll_interface_type == MDSS_DSI_PLL_12NM)) + ret = ((readl_relaxed(pll_res->gdsc_base + 0x4) & BIT(31)) && + (!(readl_relaxed(pll_res->gdsc_base) & BIT(0)))) ? + false : true; + else + ret = readl_relaxed(pll_res->gdsc_base) & BIT(31) ? + false : true; return ret; } From 07d4b903deccdd8ea064574a3457643ca152052b Mon Sep 17 00:00:00 2001 From: Vipin Deep Kaur Date: Fri, 28 Feb 2020 11:15:46 +0530 Subject: [PATCH 264/592] i2c: i2c-qcom-geni: Reinitialize the variables after every transfer Reinitialize fifo cur_wr, cur_rd and gi2c->xfer for every transfer. Add "MSM_GPI_QUP_FW_ERROR" event to callback event list. Dump GSI registers in case of Channel RESET failure. Change-Id: I7607572c6b70ea46325cce3ff648ee1b70b49fbf Signed-off-by: Vipin Deep Kaur --- drivers/dma/qcom/gpi.c | 7 ++++++- drivers/i2c/busses/i2c-qcom-geni.c | 27 +++++++++++++++------------ 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/drivers/dma/qcom/gpi.c b/drivers/dma/qcom/gpi.c index e7dfa1b9767e..c4e466e16d01 100644 --- a/drivers/dma/qcom/gpi.c +++ b/drivers/dma/qcom/gpi.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -287,6 +287,7 @@ static const char *const gpi_cb_event_str[MSM_GPI_QUP_MAX_EVENT] = { [MSM_GPI_QUP_NOTIFY] = "NOTIFY", [MSM_GPI_QUP_ERROR] = "GLOBAL ERROR", [MSM_GPI_QUP_CH_ERROR] = "CHAN ERROR", + [MSM_GPI_QUP_FW_ERROR] = "UNHANDLED ERROR", [MSM_GPI_QUP_PENDING_EVENT] = "PENDING EVENT", [MSM_GPI_QUP_EOT_DESC_MISMATCH] = "EOT/DESC MISMATCH", [MSM_GPI_QUP_SW_ERROR] = "SW ERROR", @@ -2191,6 +2192,10 @@ int gpi_terminate_all(struct dma_chan *chan) if (ret) { GPII_ERR(gpii, gpii_chan->chid, "Error resetting channel ret:%d\n", ret); + if (!gpii->reg_table_dump) { + gpi_dump_debug_reg(gpii); + gpii->reg_table_dump = true; + } goto terminate_exit; } diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c index 8eeea7f72261..1984b22c1dfa 100644 --- a/drivers/i2c/busses/i2c-qcom-geni.c +++ b/drivers/i2c/busses/i2c-qcom-geni.c @@ -395,6 +395,7 @@ static void gi2c_ev_cb(struct dma_chan *ch, struct msm_gpi_cb const *cb_str, case MSM_GPI_QUP_MAX_EVENT: /* fall through to stall impacted channel */ case MSM_GPI_QUP_CH_ERROR: + case MSM_GPI_QUP_FW_ERROR: case MSM_GPI_QUP_PENDING_EVENT: case MSM_GPI_QUP_EOT_DESC_MISMATCH: break; @@ -412,9 +413,9 @@ static void gi2c_ev_cb(struct dma_chan *ch, struct msm_gpi_cb const *cb_str, } if (cb_str->cb_event != MSM_GPI_QUP_NOTIFY) GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev, - "GSI QN err:0x%x, status:0x%x, err:%d\n", - cb_str->error_log.error_code, - m_stat, cb_str->cb_event); + "GSI QN err:0x%x, status:0x%x, err:%d\n", + cb_str->error_log.error_code, m_stat, + cb_str->cb_event); } static void gi2c_gsi_cb_err(struct msm_gpi_dma_async_tx_cb_param *cb, @@ -538,6 +539,7 @@ static int geni_i2c_gsi_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], struct msm_gpi_tre *go_t = &gi2c->go_t; struct device *rx_dev = gi2c->wrapper_dev; struct device *tx_dev = gi2c->wrapper_dev; + reinit_completion(&gi2c->xfer); gi2c->cur = &msgs[i]; qcom_geni_i2c_calc_timeout(gi2c); @@ -708,7 +710,14 @@ static int geni_i2c_xfer(struct i2c_adapter *adap, int i, ret = 0, timeout = 0; gi2c->err = 0; - reinit_completion(&gi2c->xfer); + + /* Client to respect system suspend */ + if (!pm_runtime_enabled(gi2c->dev)) { + GENI_SE_ERR(gi2c->ipcl, false, gi2c->dev, + "%s: System suspended\n", __func__); + return -EACCES; + } + mutex_lock(&gi2c->i2c_ssr.ssr_lock); if (gi2c->i2c_ssr.is_ssr_down) { GENI_SE_DBG(gi2c->ipcl, false, gi2c->dev, @@ -716,12 +725,6 @@ static int geni_i2c_xfer(struct i2c_adapter *adap, mutex_unlock(&gi2c->i2c_ssr.ssr_lock); return -EINVAL; } - /* Client to respect system suspend */ - if (!pm_runtime_enabled(gi2c->dev)) { - GENI_SE_ERR(gi2c->ipcl, false, gi2c->dev, - "%s: System suspended\n", __func__); - return -EACCES; - } ret = pm_runtime_get_sync(gi2c->dev); if (ret < 0) { @@ -856,6 +859,8 @@ static int geni_i2c_xfer(struct i2c_adapter *adap, geni_abort_m_cmd(gi2c->base); } } + gi2c->cur_wr = 0; + gi2c->cur_rd = 0; gi2c->cur_wr = 0; gi2c->cur_rd = 0; @@ -889,8 +894,6 @@ geni_i2c_txn_ret: pm_runtime_mark_last_busy(gi2c->dev); pm_runtime_put_autosuspend(gi2c->dev); - gi2c->cur_wr = 0; - gi2c->cur_rd = 0; gi2c->cur = NULL; gi2c->err = 0; GENI_SE_DBG(gi2c->ipcl, false, gi2c->dev, From 8e7a0d4061d9ed93e9d2f01e35d2f49cdb2bf910 Mon Sep 17 00:00:00 2001 From: Vishwanath Raju K Date: Tue, 28 Jul 2020 12:58:08 +0530 Subject: [PATCH 265/592] iommu/arm-smmu: Do not write to slave side protected context banks For msm targets that have slave side access control, iommu driver is not allowed to write to secure context bank register space. Extend arm_smmu_skip_write logic to consider such protected context bank ttbr address space as well for skipping. Change-Id: Ibb6ee5a0425c1aa86ab82b78eca386de09baaace Signed-off-by: Vishwanath Raju K --- include/soc/qcom/msm_tz_smmu.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/soc/qcom/msm_tz_smmu.h b/include/soc/qcom/msm_tz_smmu.h index 0a247be2d450..ed7407a0b6c3 100644 --- a/include/soc/qcom/msm_tz_smmu.h +++ b/include/soc/qcom/msm_tz_smmu.h @@ -62,11 +62,16 @@ extern void *get_smmu_from_addr(struct iommu_device *iommu, void __iomem *addr); extern void *arm_smmu_get_by_addr(void __iomem *addr); /* Donot write to smmu global space with CONFIG_MSM_TZ_SMMU */ #undef writel_relaxed +#undef writeq_relaxed #define writel_relaxed(v, c) do { \ if (!arm_smmu_skip_write(c)) \ ((void)__raw_writel((u32)cpu_to_le32(v), (c))); \ } while (0) +#define writeq_relaxed(v, c) do { \ + if (!arm_smmu_skip_write(c)) \ + ((void)__raw_writeq((u64)cpu_to_le64(v), (c))); \ + } while (0) #else static inline int msm_tz_smmu_atos_start(struct device *dev, int cb_num) From 337553055a4ce4dd4b49a0f60961d53ea1398398 Mon Sep 17 00:00:00 2001 From: Venkata Rao Kakani Date: Fri, 24 Jul 2020 16:13:32 +0530 Subject: [PATCH 266/592] drivers: soc: rename block device nodes Rename block driver enables the renaming of block dev nodes assigned by generic driver. Change-Id: If4acbfdc13bd6c87e761af8ff8eeab9c0c6770d6 Signed-off-by: Venkata Rao Kakani --- drivers/soc/qcom/Kconfig | 6 +++ drivers/soc/qcom/Makefile | 1 + drivers/soc/qcom/rename_block_device.c | 65 ++++++++++++++++++++++++++ 3 files changed, 72 insertions(+) create mode 100644 drivers/soc/qcom/rename_block_device.c diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 8d9c0e27508f..fa4e8e735872 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -1061,4 +1061,10 @@ config QCOM_HYP_CORE_CTL An offline CPU is considered as a reserved CPU since this OS can't use it. +config RENAME_BLOCK_DEVICE + bool "Rename block device node in /dev" + help + This driver is used to rename the block device node assigned by generic driver + to a name that is needed. + source "drivers/soc/qcom/wcnss/Kconfig" diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index 9c2a3fb9fd36..1de8bfeefda0 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile @@ -118,3 +118,4 @@ obj-$(CONFIG_QCOM_ADSP_MANUAL_VOTE) += adsp_vote_qmi.o adsp_lpm_voting_v01.o obj-$(CONFIG_CPU_V7) += idle-v7.o obj-$(CONFIG_MSM_BAM_DMUX) += bam_dmux.o obj-$(CONFIG_WCNSS_CORE) += wcnss/ +obj-$(CONFIG_RENAME_BLOCK_DEVICE) += rename_block_device.o diff --git a/drivers/soc/qcom/rename_block_device.c b/drivers/soc/qcom/rename_block_device.c new file mode 100644 index 000000000000..c2dd284b0ac3 --- /dev/null +++ b/drivers/soc/qcom/rename_block_device.c @@ -0,0 +1,65 @@ +/* Copyright (c) 2020 The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#define PATH_SIZE 32 + +static int rename_blk_dev_init(void) +{ + dev_t dev; + int index = 0, partno; + struct gendisk *disk; + struct device_node *node; + char dev_path[PATH_SIZE]; + const char *actual_name, *modified_name; + + node = of_find_compatible_node(NULL, NULL, "qcom,blkdev-rename"); + if (!node) { + pr_err("qcom,blkdev-rename is missing\n"); + goto out; + } + while (!of_property_read_string_index(node, "actual-dev", index, + &actual_name)) { + memset(dev_path, '\0', PATH_SIZE); + snprintf(dev_path, PATH_SIZE, "/dev/%s", actual_name); + dev = name_to_dev_t(dev_path); + if (!dev) { + pr_err("No device path : %s\n", dev_path); + return -EINVAL; + } + disk = get_gendisk(dev, &partno); + if (!disk) { + pr_err("No device with dev path : %s\n", dev_path); + return -ENXIO; + } + if (!of_property_read_string_index(node, "rename-dev", index, + &modified_name)) { + device_rename(disk_to_dev(disk), modified_name); + } else { + pr_err("rename-dev for actual-dev = %s is missing", + actual_name); + return -ENXIO; + } + index++; + } +out: + return 0; +} + +late_initcall(rename_blk_dev_init); +MODULE_DESCRIPTION("Rename block devices"); +MODULE_LICENSE("GPL v2"); From 17af901779b2e07466c8d237817abec7c7da9ca3 Mon Sep 17 00:00:00 2001 From: Peter Chen Date: Fri, 15 Nov 2019 18:50:00 +0200 Subject: [PATCH 267/592] usb: host: xhci: update event ring dequeue pointer on purpose On some situations, the software handles TRB events slower than adding TRBs, then xhci_handle_event can't return zero long time, the xHC will consider the event ring is full, and trigger "Event Ring Full" error, but in fact, the software has already finished lots of events, just no chance to update ERDP (event ring dequeue pointer). In this commit, we force update ERDP if half of TRBS_PER_SEGMENT events have handled to avoid "Event Ring Full" error. Change-Id: I88b8dff5f7c3d6848a17c9efe564475602bf701d Signed-off-by: Peter Chen Signed-off-by: Mathias Nyman Link: https://lore.kernel.org/r/1573836603-10871-2-git-send-email-mathias.nyman@linux.intel.com Signed-off-by: Greg Kroah-Hartman Git-commit: dc0ffbea5729a3abafa577ebfce87f18b79e294b Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Signed-off-by: Ajay Agarwal --- drivers/usb/host/xhci-ring.c | 60 ++++++++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 17 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 37dfef107d3c..82530947d105 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -2758,6 +2758,42 @@ static int xhci_handle_event(struct xhci_hcd *xhci) return 1; } +/* + * Update Event Ring Dequeue Pointer: + * - When all events have finished + * - To avoid "Event Ring Full Error" condition + */ +static void xhci_update_erst_dequeue(struct xhci_hcd *xhci, + union xhci_trb *event_ring_deq) +{ + u64 temp_64; + dma_addr_t deq; + + temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); + /* If necessary, update the HW's version of the event ring deq ptr. */ + if (event_ring_deq != xhci->event_ring->dequeue) { + deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg, + xhci->event_ring->dequeue); + if (deq == 0) + xhci_warn(xhci, "WARN something wrong with SW event ring dequeue ptr\n"); + /* + * Per 4.9.4, Software writes to the ERDP register shall + * always advance the Event Ring Dequeue Pointer value. + */ + if ((temp_64 & (u64) ~ERST_PTR_MASK) == + ((u64) deq & (u64) ~ERST_PTR_MASK)) + return; + + /* Update HC event ring dequeue pointer */ + temp_64 &= ERST_PTR_MASK; + temp_64 |= ((u64) deq & (u64) ~ERST_PTR_MASK); + } + + /* Clear the event handler busy flag (RW1C) */ + temp_64 |= ERST_EHB; + xhci_write_64(xhci, temp_64, &xhci->ir_set->erst_dequeue); +} + /* * xHCI spec says we can get an interrupt, and if the HC has an error condition, * we might get bad data out of the event ring. Section 4.10.2.7 has a list of @@ -2769,9 +2805,9 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd) union xhci_trb *event_ring_deq; irqreturn_t ret = IRQ_NONE; unsigned long flags; - dma_addr_t deq; u64 temp_64; u32 status; + int event_loop = 0; spin_lock_irqsave(&xhci->lock, flags); /* Check if the xHC generated the interrupt, or the irq is shared */ @@ -2825,24 +2861,14 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd) /* FIXME this should be a delayed service routine * that clears the EHB. */ - while (xhci_handle_event(xhci) > 0) {} - - temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); - /* If necessary, update the HW's version of the event ring deq ptr. */ - if (event_ring_deq != xhci->event_ring->dequeue) { - deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg, - xhci->event_ring->dequeue); - if (deq == 0) - xhci_warn(xhci, "WARN something wrong with SW event " - "ring dequeue ptr.\n"); - /* Update HC event ring dequeue pointer */ - temp_64 &= ERST_PTR_MASK; - temp_64 |= ((u64) deq & (u64) ~ERST_PTR_MASK); + while (xhci_handle_event(xhci) > 0) { + if (event_loop++ < TRBS_PER_SEGMENT / 2) + continue; + xhci_update_erst_dequeue(xhci, event_ring_deq); + event_loop = 0; } - /* Clear the event handler busy flag (RW1C); event ring is empty. */ - temp_64 |= ERST_EHB; - xhci_write_64(xhci, temp_64, &xhci->ir_set->erst_dequeue); + xhci_update_erst_dequeue(xhci, event_ring_deq); ret = IRQ_HANDLED; out: From b35fdb3b859eb06b5a8570fbb80d581db5924803 Mon Sep 17 00:00:00 2001 From: Gaurav Kohli Date: Wed, 8 Jul 2020 17:51:25 +0530 Subject: [PATCH 268/592] binder: fix braces warning in binderfs Add braces to avoid compile time warning of missing braces. Change-Id: I9e9e26bfcf7cdb7ea24a8530989ff4480b6eb757 Signed-off-by: Gaurav Kohli --- drivers/android/binderfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/android/binderfs.c b/drivers/android/binderfs.c index a4f73af4fa4e..4eca0e1fbbd8 100644 --- a/drivers/android/binderfs.c +++ b/drivers/android/binderfs.c @@ -654,7 +654,7 @@ static int binderfs_fill_super(struct super_block *sb, void *data, int silent) int ret; struct binderfs_info *info; struct inode *inode = NULL; - struct binderfs_device device_info = { 0 }; + struct binderfs_device device_info = { { 0 } }; const char *name; size_t len; From de29432dd715835ff206687e2a96caa9f36ccfd0 Mon Sep 17 00:00:00 2001 From: Nitesh Gupta Date: Tue, 28 Jul 2020 20:28:51 +0530 Subject: [PATCH 269/592] msm: mhi_dev: allocate high priority Workqueue for mhi_sm_wq Allocate high priority work queue for mhi_sm_wq such that MHI state change events are handled with priority. Change-Id: I3d95e23b3daafce5a8888e5203caa75f1744351b Signed-off-by: Nitesh Gupta --- drivers/platform/msm/mhi_dev/mhi_sm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/msm/mhi_dev/mhi_sm.c b/drivers/platform/msm/mhi_dev/mhi_sm.c index 62d4fe0bf7de..4d208bb931c1 100644 --- a/drivers/platform/msm/mhi_dev/mhi_sm.c +++ b/drivers/platform/msm/mhi_dev/mhi_sm.c @@ -1102,7 +1102,7 @@ int mhi_dev_sm_init(struct mhi_dev *mhi_dev) /*init debugfs*/ mhi_sm_debugfs_init(); - mhi_sm_ctx->mhi_sm_wq = create_singlethread_workqueue("mhi_sm_wq"); + mhi_sm_ctx->mhi_sm_wq = alloc_workqueue("mhi_sm_wq", WQ_HIGHPRI, 0); if (!mhi_sm_ctx->mhi_sm_wq) { MHI_SM_ERR("Failed to create singlethread_workqueue: sm_wq\n"); res = -ENOMEM; From f242ec26f87d95c4bd239da74e71aeccc7200d05 Mon Sep 17 00:00:00 2001 From: Terence Ho Date: Tue, 28 Jul 2020 11:09:01 -0400 Subject: [PATCH 270/592] msm: ais: Address index out of bounds Fix index out of bounds issue and variable initialization. Change-Id: I8fc3032bbcd68fec48d5ec9e02ba07709ab683c7 Signed-off-by: Terence Ho --- .../media/platform/msm/ais/ais_isp/vfe_hw/ais_vfe_core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/msm/ais/ais_isp/vfe_hw/ais_vfe_core.c b/drivers/media/platform/msm/ais/ais_isp/vfe_hw/ais_vfe_core.c index f55efb259565..00219b70667a 100644 --- a/drivers/media/platform/msm/ais/ais_isp/vfe_hw/ais_vfe_core.c +++ b/drivers/media/platform/msm/ais/ais_isp/vfe_hw/ais_vfe_core.c @@ -1050,7 +1050,7 @@ static int ais_vfe_handle_sof( CAM_DBG(CAM_ISP, "IFE%d SOF RDIs 0x%x", core_info->vfe_idx, work_data->path); - for (path = 0; path <= AIS_IFE_PATH_MAX; path++) { + for (path = 0; path < AIS_IFE_PATH_MAX; path++) { if (!(work_data->path & (1 << path))) continue; @@ -1092,7 +1092,7 @@ static int ais_vfe_handle_error( bus_hw_info = core_info->vfe_hw_info->bus_hw_info; bus_hw_irq_regs = bus_hw_info->common_reg.irq_reg_info.irq_reg_set; - for (path = 0; path <= AIS_IFE_PATH_MAX; path++) { + for (path = 0; path < AIS_IFE_PATH_MAX; path++) { if (!(work_data->path & (1 << path))) continue; @@ -1135,7 +1135,7 @@ static void ais_vfe_bus_handle_client_frame_done( struct ais_vfe_rdi_output *rdi_path = NULL; struct ais_vfe_buffer_t *vfe_buf = NULL; struct ais_vfe_bus_ver2_hw_info *bus_hw_info = NULL; - uint64_t frame_cnt; + uint64_t frame_cnt = 0; uint64_t sof_ts; uint64_t cur_sof_hw_ts; bool last_addr_match = false; From 63f70a95015f3080e72aa34ae8db01e8b733c374 Mon Sep 17 00:00:00 2001 From: Sean Tranchetti Date: Wed, 22 Jul 2020 16:22:20 -0600 Subject: [PATCH 271/592] net: qualcomm: rmnet: validate ipv6 extension header lengths When calculating the length of the IPv6 header chain, lengths of the IPv6 extension headers are not checked against the overall packet lengths and thus it's possible to parse past the end of the packet when the packet is malformed. This adds the necessary bounds checking to ensure that parsing stops if the end of the packet is reached to avoid the following: Unable to handle kernel paging request at virtual address pc : rmnet_frag_ipv6_skip_exthdr+0xc0/0x108 [rmnet_core] lr : rmnet_frag_ipv6_skip_exthdr+0x68/0x108 [rmnet_core] Call trace: rmnet_frag_ipv6_skip_exthdr+0xc0/0x108 [rmnet_core] DATARMNET29e8d137c4+0x1a0/0x3e0 [rmnet_offload] rmnet_frag_ingress_handler+0x294/0x404 [rmnet_core] rmnet_rx_handler+0x1b4/0x284 [rmnet_core] __netif_receive_skb_core+0x740/0xd2c __netif_receive_skb+0x44/0x158 Change-Id: Ib2e2ebce733bd4d14a3dfc175133638b15015277 Signed-off-by: Sean Tranchetti --- drivers/net/ethernet/qualcomm/rmnet/rmnet_descriptor.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_descriptor.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_descriptor.c index 3ee89fdd8c54..2e658278fa70 100644 --- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_descriptor.c +++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_descriptor.c @@ -103,6 +103,7 @@ EXPORT_SYMBOL(rmnet_descriptor_add_frag); int rmnet_frag_ipv6_skip_exthdr(struct rmnet_frag_descriptor *frag_desc, int start, u8 *nexthdrp, __be16 *fragp) { + u32 frag_size = skb_frag_size(&frag_desc->frag); u8 nexthdr = *nexthdrp; *fragp = 0; @@ -114,11 +115,17 @@ int rmnet_frag_ipv6_skip_exthdr(struct rmnet_frag_descriptor *frag_desc, if (nexthdr == NEXTHDR_NONE) return -EINVAL; - hp = rmnet_frag_data_ptr(frag_desc) + start; + if (start >= frag_size) + return -EINVAL; + hp = rmnet_frag_data_ptr(frag_desc) + start; if (nexthdr == NEXTHDR_FRAGMENT) { __be16 *fp; + if (start + offsetof(struct frag_hdr, frag_off) >= + frag_size) + return -EINVAL; + fp = rmnet_frag_data_ptr(frag_desc) + start + offsetof(struct frag_hdr, frag_off); *fragp = *fp; From 448b4c150eb9b2889176da6aaadf6c3d069e4849 Mon Sep 17 00:00:00 2001 From: Mahesh Voorugonda Date: Thu, 16 Jul 2020 15:36:44 +0530 Subject: [PATCH 272/592] ARM: dts: qcom: add video device tree entry for sdm429w Add video device tree node sdm429-vidc for sdm429w. Change-Id: I616c5a2799cfe80e2803b94e9a96202bc21897d3 Signed-off-by: Mahesh Voorugonda --- arch/arm64/boot/dts/qcom/sdm429.dtsi | 37 ++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sdm429.dtsi b/arch/arm64/boot/dts/qcom/sdm429.dtsi index 31218880dc07..27c2b9afcb15 100644 --- a/arch/arm64/boot/dts/qcom/sdm429.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm429.dtsi @@ -705,7 +705,44 @@ qcom,smem-state-names = "qcom,force-stop"; memory-region = <&wcnss_fw_mem>; }; + qcom,venus@1de0000 { + compatible = "qcom,pil-tz-generic"; + reg = <0x1de0000 0x4000>; + vdd-supply = <&venus_gdsc>; + qcom,proxy-reg-names = "vdd"; + + clocks = <&gcc GCC_VENUS0_VCODEC0_CLK>, + <&gcc GCC_VENUS0_AHB_CLK>, + <&gcc GCC_VENUS0_AXI_CLK>, + <&gcc GCC_CRYPTO_CLK>, + <&gcc GCC_CRYPTO_AHB_CLK>, + <&gcc GCC_CRYPTO_AXI_CLK>, + <&gcc CRYPTO_CLK_SRC>; + + clock-names = "core_clk", "iface_clk", "bus_clk", + "scm_core_clk", "scm_iface_clk", + "scm_bus_clk", "scm_core_clk_src"; + + qcom,proxy-clock-names = "core_clk", "iface_clk", + "bus_clk", "scm_core_clk", + "scm_iface_clk", "scm_bus_clk", + "scm_core_clk_src"; + qcom,scm_core_clk_src-freq = <80000000>; + + qcom,msm-bus,name = "pil-venus"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + <63 512 0 0>, + <63 512 0 304000>; + + qcom,mas-crypto = <&mas_crypto>; + qcom,pas-id = <9>; + qcom,proxy-timeout-ms = <100>; + qcom,firmware-name = "venus"; + memory-region = <&venus_mem>; + }; pil_modem: qcom,mss@4080000 { compatible = "qcom,pil-q6v55-mss"; reg = <0x4080000 0x100>, From b7fc809e57cd24bc723136ab7d4210ce9719718b Mon Sep 17 00:00:00 2001 From: Yuanfang Zhang Date: Tue, 28 Jul 2020 18:55:05 +0800 Subject: [PATCH 273/592] ARM: dts: msm: disable gpu_isdb cti for trinket Gpu_isdb cti needs wcss clock to be enabled. gpu clock can't be turned on from kernel. Disable it. Change-Id: If863920410c91049cf980ca36e894278687ddded Signed-off-by: Yuanfang Zhang --- arch/arm64/boot/dts/qcom/trinket-coresight.dtsi | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/trinket-coresight.dtsi b/arch/arm64/boot/dts/qcom/trinket-coresight.dtsi index e991d4159b1a..3c46db0a9c7b 100644 --- a/arch/arm64/boot/dts/qcom/trinket-coresight.dtsi +++ b/arch/arm64/boot/dts/qcom/trinket-coresight.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -2219,6 +2219,7 @@ coresight-name = "coresight-cti-gpu_isdb_cti"; + status = "disabled"; clocks = <&clock_rpmcc RPM_SMD_QDSS_CLK>, <&clock_gpucc GPU_CC_CX_APB_CLK>; clock-names = "apb_pclk", "gpu_apb_clk"; From d91d4e67a489b8aef24be523dbb3621a40739ec4 Mon Sep 17 00:00:00 2001 From: Swetha Chikkaboraiah Date: Wed, 22 Jul 2020 13:54:28 +0530 Subject: [PATCH 274/592] defconfig: For support api_30 kernel changes Enabling Mandatory defconfigs For supporting atoll, sm6150, sm8150, trinket Change-Id: Ifa18ce463268016c5d5713699bac778fe7bf043d Signed-off-by: Swetha Chikkaboraiah --- arch/arm64/configs/vendor/atoll-perf_defconfig | 1 + arch/arm64/configs/vendor/atoll_defconfig | 1 + arch/arm64/configs/vendor/sdmsteppe-perf_defconfig | 1 + arch/arm64/configs/vendor/sdmsteppe_defconfig | 1 + arch/arm64/configs/vendor/sm8150-perf_defconfig | 1 + arch/arm64/configs/vendor/sm8150_defconfig | 1 + arch/arm64/configs/vendor/trinket-perf_defconfig | 1 + arch/arm64/configs/vendor/trinket_defconfig | 1 + 8 files changed, 8 insertions(+) diff --git a/arch/arm64/configs/vendor/atoll-perf_defconfig b/arch/arm64/configs/vendor/atoll-perf_defconfig index fec102ee0204..abdc6b664751 100644 --- a/arch/arm64/configs/vendor/atoll-perf_defconfig +++ b/arch/arm64/configs/vendor/atoll-perf_defconfig @@ -292,6 +292,7 @@ CONFIG_NETDEVICES=y CONFIG_BONDING=y CONFIG_DUMMY=y CONFIG_TUN=y +CONFIG_VETH=y CONFIG_SKY2=y CONFIG_RMNET=y CONFIG_SMSC911X=y diff --git a/arch/arm64/configs/vendor/atoll_defconfig b/arch/arm64/configs/vendor/atoll_defconfig index b9f29521b8f3..e79ae486605e 100644 --- a/arch/arm64/configs/vendor/atoll_defconfig +++ b/arch/arm64/configs/vendor/atoll_defconfig @@ -303,6 +303,7 @@ CONFIG_NETDEVICES=y CONFIG_BONDING=y CONFIG_DUMMY=y CONFIG_TUN=y +CONFIG_VETH=y CONFIG_RMNET=y CONFIG_AT803X_PHY=y CONFIG_MICREL_PHY=y diff --git a/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig b/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig index c60b1cc772a6..44b60d9f2908 100644 --- a/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig +++ b/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig @@ -287,6 +287,7 @@ CONFIG_NETDEVICES=y CONFIG_BONDING=y CONFIG_DUMMY=y CONFIG_TUN=y +CONFIG_VETH=y CONFIG_SKY2=y CONFIG_RMNET=y CONFIG_SMSC911X=y diff --git a/arch/arm64/configs/vendor/sdmsteppe_defconfig b/arch/arm64/configs/vendor/sdmsteppe_defconfig index d1ea546f00d0..b35805ba3b42 100644 --- a/arch/arm64/configs/vendor/sdmsteppe_defconfig +++ b/arch/arm64/configs/vendor/sdmsteppe_defconfig @@ -298,6 +298,7 @@ CONFIG_NETDEVICES=y CONFIG_BONDING=y CONFIG_DUMMY=y CONFIG_TUN=y +CONFIG_VETH=y CONFIG_RMNET=y CONFIG_AT803X_PHY=y CONFIG_MICREL_PHY=y diff --git a/arch/arm64/configs/vendor/sm8150-perf_defconfig b/arch/arm64/configs/vendor/sm8150-perf_defconfig index ae6e24be182f..6ea0a9bac91e 100644 --- a/arch/arm64/configs/vendor/sm8150-perf_defconfig +++ b/arch/arm64/configs/vendor/sm8150-perf_defconfig @@ -298,6 +298,7 @@ CONFIG_NETDEVICES=y CONFIG_BONDING=y CONFIG_DUMMY=y CONFIG_TUN=y +CONFIG_VETH=y CONFIG_SKY2=y CONFIG_RMNET=y CONFIG_SMSC911X=y diff --git a/arch/arm64/configs/vendor/sm8150_defconfig b/arch/arm64/configs/vendor/sm8150_defconfig index 00883b59ca12..7e65278a8e22 100644 --- a/arch/arm64/configs/vendor/sm8150_defconfig +++ b/arch/arm64/configs/vendor/sm8150_defconfig @@ -311,6 +311,7 @@ CONFIG_NETDEVICES=y CONFIG_BONDING=y CONFIG_DUMMY=y CONFIG_TUN=y +CONFIG_VETH=y CONFIG_RMNET=y CONFIG_PPP=y CONFIG_PPP_BSDCOMP=y diff --git a/arch/arm64/configs/vendor/trinket-perf_defconfig b/arch/arm64/configs/vendor/trinket-perf_defconfig index 1af661907f0e..20fa15644623 100644 --- a/arch/arm64/configs/vendor/trinket-perf_defconfig +++ b/arch/arm64/configs/vendor/trinket-perf_defconfig @@ -292,6 +292,7 @@ CONFIG_NETDEVICES=y CONFIG_BONDING=y CONFIG_DUMMY=y CONFIG_TUN=y +CONFIG_VETH=y CONFIG_RMNET=y CONFIG_PPP=y CONFIG_PPP_BSDCOMP=y diff --git a/arch/arm64/configs/vendor/trinket_defconfig b/arch/arm64/configs/vendor/trinket_defconfig index 26e416621815..b29febbd5b16 100644 --- a/arch/arm64/configs/vendor/trinket_defconfig +++ b/arch/arm64/configs/vendor/trinket_defconfig @@ -303,6 +303,7 @@ CONFIG_NETDEVICES=y CONFIG_BONDING=y CONFIG_DUMMY=y CONFIG_TUN=y +CONFIG_VETH=y CONFIG_RMNET=y CONFIG_PPP=y CONFIG_PPP_BSDCOMP=y From 6d2d953b431c14cd8b1cd49909de973affb9c806 Mon Sep 17 00:00:00 2001 From: Swetha Chikkaboraiah Date: Wed, 22 Jul 2020 14:24:31 +0530 Subject: [PATCH 275/592] defconfig: Disable CRYPTO_MD4 config MD4 is a weak cryptography and is not by atoll, sm6150, sm8150, trinket Change-Id: Iacda1379816beaa6f7174306919f26a06cb5cf2a Signed-off-by: Swetha Chikkaboraiah --- arch/arm64/configs/vendor/atoll-perf_defconfig | 1 - arch/arm64/configs/vendor/atoll_defconfig | 1 - arch/arm64/configs/vendor/sdmsteppe-perf_defconfig | 1 - arch/arm64/configs/vendor/sdmsteppe_defconfig | 1 - arch/arm64/configs/vendor/sm8150-perf_defconfig | 1 - arch/arm64/configs/vendor/sm8150_defconfig | 1 - arch/arm64/configs/vendor/trinket-perf_defconfig | 1 - arch/arm64/configs/vendor/trinket_defconfig | 1 - 8 files changed, 8 deletions(-) diff --git a/arch/arm64/configs/vendor/atoll-perf_defconfig b/arch/arm64/configs/vendor/atoll-perf_defconfig index abdc6b664751..fcbe43bb775e 100644 --- a/arch/arm64/configs/vendor/atoll-perf_defconfig +++ b/arch/arm64/configs/vendor/atoll-perf_defconfig @@ -721,7 +721,6 @@ CONFIG_SECURITY_SELINUX=y CONFIG_SECURITY_SMACK=y CONFIG_CRYPTO_GCM=y CONFIG_CRYPTO_XCBC=y -CONFIG_CRYPTO_MD4=y CONFIG_CRYPTO_TWOFISH=y CONFIG_CRYPTO_ANSI_CPRNG=y CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y diff --git a/arch/arm64/configs/vendor/atoll_defconfig b/arch/arm64/configs/vendor/atoll_defconfig index e79ae486605e..c33dde723a30 100644 --- a/arch/arm64/configs/vendor/atoll_defconfig +++ b/arch/arm64/configs/vendor/atoll_defconfig @@ -809,7 +809,6 @@ CONFIG_SECURITY_SELINUX=y CONFIG_SECURITY_SMACK=y CONFIG_CRYPTO_GCM=y CONFIG_CRYPTO_XCBC=y -CONFIG_CRYPTO_MD4=y CONFIG_CRYPTO_TWOFISH=y CONFIG_CRYPTO_ANSI_CPRNG=y CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y diff --git a/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig b/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig index 44b60d9f2908..09eeaa9eee94 100644 --- a/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig +++ b/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig @@ -699,7 +699,6 @@ CONFIG_SECURITY_SELINUX=y CONFIG_SECURITY_SMACK=y CONFIG_CRYPTO_GCM=y CONFIG_CRYPTO_XCBC=y -CONFIG_CRYPTO_MD4=y CONFIG_CRYPTO_TWOFISH=y CONFIG_CRYPTO_ANSI_CPRNG=y CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y diff --git a/arch/arm64/configs/vendor/sdmsteppe_defconfig b/arch/arm64/configs/vendor/sdmsteppe_defconfig index b35805ba3b42..738a7459fb80 100644 --- a/arch/arm64/configs/vendor/sdmsteppe_defconfig +++ b/arch/arm64/configs/vendor/sdmsteppe_defconfig @@ -794,7 +794,6 @@ CONFIG_SECURITY_SELINUX=y CONFIG_SECURITY_SMACK=y CONFIG_CRYPTO_GCM=y CONFIG_CRYPTO_XCBC=y -CONFIG_CRYPTO_MD4=y CONFIG_CRYPTO_TWOFISH=y CONFIG_CRYPTO_ANSI_CPRNG=y CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y diff --git a/arch/arm64/configs/vendor/sm8150-perf_defconfig b/arch/arm64/configs/vendor/sm8150-perf_defconfig index 6ea0a9bac91e..bb81b37ba8e2 100644 --- a/arch/arm64/configs/vendor/sm8150-perf_defconfig +++ b/arch/arm64/configs/vendor/sm8150-perf_defconfig @@ -709,7 +709,6 @@ CONFIG_SECURITY_SELINUX=y CONFIG_SECURITY_SMACK=y CONFIG_CRYPTO_GCM=y CONFIG_CRYPTO_XCBC=y -CONFIG_CRYPTO_MD4=y CONFIG_CRYPTO_TWOFISH=y CONFIG_CRYPTO_ANSI_CPRNG=y CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y diff --git a/arch/arm64/configs/vendor/sm8150_defconfig b/arch/arm64/configs/vendor/sm8150_defconfig index 7e65278a8e22..081777600f4a 100644 --- a/arch/arm64/configs/vendor/sm8150_defconfig +++ b/arch/arm64/configs/vendor/sm8150_defconfig @@ -796,7 +796,6 @@ CONFIG_SECURITY_SELINUX=y CONFIG_SECURITY_SMACK=y CONFIG_CRYPTO_GCM=y CONFIG_CRYPTO_XCBC=y -CONFIG_CRYPTO_MD4=y CONFIG_CRYPTO_TWOFISH=y CONFIG_CRYPTO_ANSI_CPRNG=y CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y diff --git a/arch/arm64/configs/vendor/trinket-perf_defconfig b/arch/arm64/configs/vendor/trinket-perf_defconfig index 20fa15644623..4e2840b8dbec 100644 --- a/arch/arm64/configs/vendor/trinket-perf_defconfig +++ b/arch/arm64/configs/vendor/trinket-perf_defconfig @@ -685,7 +685,6 @@ CONFIG_SECURITY_SELINUX=y CONFIG_SECURITY_SMACK=y CONFIG_CRYPTO_GCM=y CONFIG_CRYPTO_XCBC=y -CONFIG_CRYPTO_MD4=y CONFIG_CRYPTO_TWOFISH=y CONFIG_CRYPTO_ANSI_CPRNG=y CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y diff --git a/arch/arm64/configs/vendor/trinket_defconfig b/arch/arm64/configs/vendor/trinket_defconfig index b29febbd5b16..c8f5e95447f5 100644 --- a/arch/arm64/configs/vendor/trinket_defconfig +++ b/arch/arm64/configs/vendor/trinket_defconfig @@ -773,7 +773,6 @@ CONFIG_SECURITY_SELINUX=y CONFIG_SECURITY_SMACK=y CONFIG_CRYPTO_GCM=y CONFIG_CRYPTO_XCBC=y -CONFIG_CRYPTO_MD4=y CONFIG_CRYPTO_TWOFISH=y CONFIG_CRYPTO_ANSI_CPRNG=y CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y From 5540a650d075d39f65551af65e068428eac066c2 Mon Sep 17 00:00:00 2001 From: Swetha Chikkaboraiah Date: Wed, 22 Jul 2020 15:01:22 +0530 Subject: [PATCH 276/592] defconfig: Enable FS related configs Enable the FS related configs for supporting atoll, sm6150, sm8150, trinket Change-Id: I6b470d3397c3dd4a414655e459f86e128a95c08e Signed-off-by: Swetha Chikkaboraiah --- arch/arm64/configs/vendor/atoll-perf_defconfig | 3 +++ arch/arm64/configs/vendor/atoll_defconfig | 3 +++ arch/arm64/configs/vendor/sdmsteppe-perf_defconfig | 3 +++ arch/arm64/configs/vendor/sdmsteppe_defconfig | 3 +++ arch/arm64/configs/vendor/sm8150-perf_defconfig | 3 +++ arch/arm64/configs/vendor/sm8150_defconfig | 3 +++ arch/arm64/configs/vendor/trinket-perf_defconfig | 3 +++ arch/arm64/configs/vendor/trinket_defconfig | 3 +++ 8 files changed, 24 insertions(+) diff --git a/arch/arm64/configs/vendor/atoll-perf_defconfig b/arch/arm64/configs/vendor/atoll-perf_defconfig index fcbe43bb775e..b1e9f28548a5 100644 --- a/arch/arm64/configs/vendor/atoll-perf_defconfig +++ b/arch/arm64/configs/vendor/atoll-perf_defconfig @@ -671,6 +671,7 @@ CONFIG_ESOC_MDM_DRV=y CONFIG_ESOC_MDM_DBG_ENG=y CONFIG_MSM_TZ_LOG=y CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y CONFIG_EXT4_FS_SECURITY=y CONFIG_EXT4_ENCRYPTION=y CONFIG_EXT4_FS_ENCRYPTION=y @@ -678,6 +679,8 @@ CONFIG_EXT4_FS_ICE_ENCRYPTION=y CONFIG_F2FS_FS=y CONFIG_F2FS_FS_SECURITY=y CONFIG_F2FS_FS_ENCRYPTION=y +CONFIG_FS_VERITY=y +CONFIG_FS_VERITY_BUILTIN_SIGNATURES=y CONFIG_QUOTA=y CONFIG_QUOTA_NETLINK_INTERFACE=y CONFIG_QFMT_V2=y diff --git a/arch/arm64/configs/vendor/atoll_defconfig b/arch/arm64/configs/vendor/atoll_defconfig index c33dde723a30..fbef2f880c30 100644 --- a/arch/arm64/configs/vendor/atoll_defconfig +++ b/arch/arm64/configs/vendor/atoll_defconfig @@ -702,6 +702,7 @@ CONFIG_ESOC_MDM_DRV=y CONFIG_ESOC_MDM_DBG_ENG=y CONFIG_MSM_TZ_LOG=y CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y CONFIG_EXT4_FS_SECURITY=y CONFIG_EXT4_ENCRYPTION=y CONFIG_EXT4_FS_ENCRYPTION=y @@ -709,6 +710,8 @@ CONFIG_EXT4_FS_ICE_ENCRYPTION=y CONFIG_F2FS_FS=y CONFIG_F2FS_FS_SECURITY=y CONFIG_F2FS_FS_ENCRYPTION=y +CONFIG_FS_VERITY=y +CONFIG_FS_VERITY_BUILTIN_SIGNATURES=y CONFIG_QUOTA=y CONFIG_QUOTA_NETLINK_INTERFACE=y CONFIG_QFMT_V2=y diff --git a/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig b/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig index 09eeaa9eee94..f047816a92f1 100644 --- a/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig +++ b/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig @@ -649,6 +649,7 @@ CONFIG_ESOC_MDM_DRV=y CONFIG_ESOC_MDM_DBG_ENG=y CONFIG_MSM_TZ_LOG=y CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y CONFIG_EXT4_FS_SECURITY=y CONFIG_EXT4_ENCRYPTION=y CONFIG_EXT4_FS_ENCRYPTION=y @@ -656,6 +657,8 @@ CONFIG_EXT4_FS_ICE_ENCRYPTION=y CONFIG_F2FS_FS=y CONFIG_F2FS_FS_SECURITY=y CONFIG_F2FS_FS_ENCRYPTION=y +CONFIG_FS_VERITY=y +CONFIG_FS_VERITY_BUILTIN_SIGNATURES=y CONFIG_QUOTA=y CONFIG_QUOTA_NETLINK_INTERFACE=y CONFIG_QFMT_V2=y diff --git a/arch/arm64/configs/vendor/sdmsteppe_defconfig b/arch/arm64/configs/vendor/sdmsteppe_defconfig index 738a7459fb80..08f1335b7e42 100644 --- a/arch/arm64/configs/vendor/sdmsteppe_defconfig +++ b/arch/arm64/configs/vendor/sdmsteppe_defconfig @@ -687,6 +687,7 @@ CONFIG_ESOC_MDM_DRV=y CONFIG_ESOC_MDM_DBG_ENG=y CONFIG_MSM_TZ_LOG=y CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y CONFIG_EXT4_FS_SECURITY=y CONFIG_EXT4_ENCRYPTION=y CONFIG_EXT4_FS_ENCRYPTION=y @@ -694,6 +695,8 @@ CONFIG_EXT4_FS_ICE_ENCRYPTION=y CONFIG_F2FS_FS=y CONFIG_F2FS_FS_SECURITY=y CONFIG_F2FS_FS_ENCRYPTION=y +CONFIG_FS_VERITY=y +CONFIG_FS_VERITY_BUILTIN_SIGNATURES=y CONFIG_QUOTA=y CONFIG_QUOTA_NETLINK_INTERFACE=y CONFIG_QFMT_V2=y diff --git a/arch/arm64/configs/vendor/sm8150-perf_defconfig b/arch/arm64/configs/vendor/sm8150-perf_defconfig index bb81b37ba8e2..8a28cd1b66cb 100644 --- a/arch/arm64/configs/vendor/sm8150-perf_defconfig +++ b/arch/arm64/configs/vendor/sm8150-perf_defconfig @@ -657,6 +657,7 @@ CONFIG_ESOC_MDM_DRV=y CONFIG_ESOC_MDM_DBG_ENG=y CONFIG_MSM_TZ_LOG=y CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y CONFIG_EXT4_FS_SECURITY=y CONFIG_EXT4_ENCRYPTION=y CONFIG_EXT4_FS_ENCRYPTION=y @@ -664,6 +665,8 @@ CONFIG_EXT4_FS_ICE_ENCRYPTION=y CONFIG_F2FS_FS=y CONFIG_F2FS_FS_SECURITY=y CONFIG_F2FS_FS_ENCRYPTION=y +CONFIG_FS_VERITY=y +CONFIG_FS_VERITY_BUILTIN_SIGNATURES=y CONFIG_QUOTA=y CONFIG_QUOTA_NETLINK_INTERFACE=y CONFIG_QFMT_V2=y diff --git a/arch/arm64/configs/vendor/sm8150_defconfig b/arch/arm64/configs/vendor/sm8150_defconfig index 081777600f4a..968babe45d68 100644 --- a/arch/arm64/configs/vendor/sm8150_defconfig +++ b/arch/arm64/configs/vendor/sm8150_defconfig @@ -688,6 +688,7 @@ CONFIG_ESOC_MDM_DRV=y CONFIG_ESOC_MDM_DBG_ENG=y CONFIG_MSM_TZ_LOG=y CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y CONFIG_EXT4_FS_SECURITY=y CONFIG_EXT4_ENCRYPTION=y CONFIG_EXT4_FS_ENCRYPTION=y @@ -695,6 +696,8 @@ CONFIG_EXT4_FS_ICE_ENCRYPTION=y CONFIG_F2FS_FS=y CONFIG_F2FS_FS_SECURITY=y CONFIG_F2FS_FS_ENCRYPTION=y +CONFIG_FS_VERITY=y +CONFIG_FS_VERITY_BUILTIN_SIGNATURES=y CONFIG_QUOTA=y CONFIG_QUOTA_NETLINK_INTERFACE=y CONFIG_QFMT_V2=y diff --git a/arch/arm64/configs/vendor/trinket-perf_defconfig b/arch/arm64/configs/vendor/trinket-perf_defconfig index 4e2840b8dbec..d6b5f618497e 100644 --- a/arch/arm64/configs/vendor/trinket-perf_defconfig +++ b/arch/arm64/configs/vendor/trinket-perf_defconfig @@ -636,10 +636,13 @@ CONFIG_NVMEM_SPMI_SDAM=y CONFIG_SENSORS_SSC=y CONFIG_MSM_TZ_LOG=y CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y CONFIG_EXT4_FS_SECURITY=y CONFIG_F2FS_FS=y CONFIG_F2FS_FS_SECURITY=y CONFIG_F2FS_FS_ENCRYPTION=y +CONFIG_FS_VERITY=y +CONFIG_FS_VERITY_BUILTIN_SIGNATURES=y CONFIG_QUOTA=y CONFIG_QUOTA_NETLINK_INTERFACE=y CONFIG_QFMT_V2=y diff --git a/arch/arm64/configs/vendor/trinket_defconfig b/arch/arm64/configs/vendor/trinket_defconfig index c8f5e95447f5..5132a6da3b89 100644 --- a/arch/arm64/configs/vendor/trinket_defconfig +++ b/arch/arm64/configs/vendor/trinket_defconfig @@ -668,10 +668,13 @@ CONFIG_NVMEM_SPMI_SDAM=y CONFIG_SENSORS_SSC=y CONFIG_MSM_TZ_LOG=y CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y CONFIG_EXT4_FS_SECURITY=y CONFIG_F2FS_FS=y CONFIG_F2FS_FS_SECURITY=y CONFIG_F2FS_FS_ENCRYPTION=y +CONFIG_FS_VERITY=y +CONFIG_FS_VERITY_BUILTIN_SIGNATURES=y CONFIG_QUOTA=y CONFIG_QUOTA_NETLINK_INTERFACE=y CONFIG_QFMT_V2=y From 2293d65183b5ab4323b7c62fe1841a7d991380d5 Mon Sep 17 00:00:00 2001 From: Kiran Gunda Date: Wed, 22 Jul 2020 14:32:28 +0530 Subject: [PATCH 277/592] backlight: qcom-spmi-wled: Add "qcom,sync-dly" property Add "qcom,sync-dly" property to make "LED_SYNC_DELAY" configurable. Change-Id: I934779138817ab15f607896b5a9da341e6b81a2f Signed-off-by: Kiran Gunda --- .../devicetree/bindings/leds/backlight/qcom-spmi-wled.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Documentation/devicetree/bindings/leds/backlight/qcom-spmi-wled.txt b/Documentation/devicetree/bindings/leds/backlight/qcom-spmi-wled.txt index a0447c6d6469..81752a44865c 100644 --- a/Documentation/devicetree/bindings/leds/backlight/qcom-spmi-wled.txt +++ b/Documentation/devicetree/bindings/leds/backlight/qcom-spmi-wled.txt @@ -90,6 +90,14 @@ platforms. The PMIC is connected to the host processor via SPMI bus. 29600, 19600, 18100. Default: 29600 mV +- qcom,sync-dly + Usage: optional + Value type: + Definition: Delay for current sync in us. Values are + 0, 200, 400, 600, 800, 1000, 1200, 1400. + Default: 400 us. + This property is only applicable for WLED4. + - qcom,string-cfg Usage: optional Value type: From 9c097e92e684f70bb5ec6604f2290585c8b38376 Mon Sep 17 00:00:00 2001 From: Ashish Chavan Date: Fri, 17 Jul 2020 14:11:37 +0530 Subject: [PATCH 278/592] power: smb1398: Do not disable FP_FET during IREV condition Allow the charger to recover after a momentary IREV condition by using the configuration-bit to not-disable FP-FET in IREV. Change-Id: I22cad3bbc4bde0a143e3ff6e068e750a2c40e34b Signed-off-by: Ashish Chavan --- drivers/power/supply/qcom/smb1398-charger.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/power/supply/qcom/smb1398-charger.c b/drivers/power/supply/qcom/smb1398-charger.c index 2c1abcdc471c..81be751b6591 100644 --- a/drivers/power/supply/qcom/smb1398-charger.c +++ b/drivers/power/supply/qcom/smb1398-charger.c @@ -99,6 +99,7 @@ #define MISC_CFG0_REG 0x2634 #define DIS_SYNC_DRV_BIT BIT(5) #define SW_EN_SWITCHER_BIT BIT(3) +#define CFG_DIS_FPF_IREV_BIT BIT(1) #define MISC_CFG1_REG 0x2635 #define MISC_CFG1_MASK GENMASK(7, 0) @@ -1947,6 +1948,14 @@ static int smb1398_div2_cp_hw_init(struct smb1398_chip *chip) return rc; } + /* Do not disable FP_FET during IREV conditions */ + rc = smb1398_masked_write(chip, MISC_CFG0_REG, CFG_DIS_FPF_IREV_BIT, 0); + if (rc < 0) { + dev_err(chip->dev, "Couldn't set CFG_DIS_FPF_IREV_BIT, rc=%d\n", + rc); + return rc; + } + /* switcher enable controlled by register */ rc = smb1398_masked_write(chip, MISC_CFG0_REG, SW_EN_SWITCHER_BIT, SW_EN_SWITCHER_BIT); From ff209ee727e8dfb4afdb1069db49982eb0daf823 Mon Sep 17 00:00:00 2001 From: Ashish Chavan Date: Mon, 20 Jul 2020 12:18:59 +0530 Subject: [PATCH 279/592] power: battery: Fix use of uninitialized variable error Fix use of uninitiallized variable error in function get_adapter_icl_based_ilim. Change-Id: I650594d80fda88aca2de399dfa16483f72f88e77 Signed-off-by: Ashish Chavan --- drivers/power/supply/qcom/battery.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/power/supply/qcom/battery.c b/drivers/power/supply/qcom/battery.c index bac728b3871e..0c6a11b6961a 100644 --- a/drivers/power/supply/qcom/battery.c +++ b/drivers/power/supply/qcom/battery.c @@ -201,7 +201,8 @@ static int cp_get_parallel_mode(struct pl_data *chip, int mode) static int get_adapter_icl_based_ilim(struct pl_data *chip) { - int main_icl, adapter_icl = -EINVAL, rc = -EINVAL, final_icl = -EINVAL; + int main_icl = -EINVAL, adapter_icl = -EINVAL, final_icl = -EINVAL; + int rc = -EINVAL; union power_supply_propval pval = {0, }; rc = power_supply_get_property(chip->usb_psy, From 9125af2884b018ea09191b2dcb298816d1487b36 Mon Sep 17 00:00:00 2001 From: Ashish Chavan Date: Fri, 17 Jul 2020 14:11:37 +0530 Subject: [PATCH 280/592] power: smb1398: Update win-uv threshold to 10mV MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When VIN/2 – VOUT < the threshold with debounce time, WIN_UV protection kicks in. Update this threshold to 10mV. Change-Id: I015528b9fb1e4db86c4e1af186aa0f6a912967f2 Signed-off-by: Ashish Chavan --- drivers/power/supply/qcom/smb1398-charger.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/power/supply/qcom/smb1398-charger.c b/drivers/power/supply/qcom/smb1398-charger.c index 81be751b6591..d52d1410d7eb 100644 --- a/drivers/power/supply/qcom/smb1398-charger.c +++ b/drivers/power/supply/qcom/smb1398-charger.c @@ -1908,6 +1908,14 @@ static int smb1398_div2_cp_hw_init(struct smb1398_chip *chip) return rc; } + /* Configure window (Vin/2 - Vout) UV level to 10mV */ + rc = smb1398_masked_write(chip, NOLOCK_SPARE_REG, + DIV2_WIN_UV_SEL_BIT, 0); + if (rc < 0) { + dev_err(chip->dev, "Couldn't set WIN_UV_10_MV rc=%d\n", rc); + return rc; + } + /* Configure master TEMP pin to output Vtemp signal by default */ rc = smb1398_masked_write(chip, SSUPLY_TEMP_CTRL_REG, SEL_OUT_TEMP_MAX_MASK, SEL_OUT_VTEMP); @@ -2241,6 +2249,14 @@ static int smb1398_div2_cp_slave_probe(struct smb1398_chip *chip) return rc; } + /* Configure window (Vin/2 - Vout) UV level to 10mV */ + rc = smb1398_masked_write(chip, NOLOCK_SPARE_REG, + DIV2_WIN_UV_SEL_BIT, 0); + if (rc < 0) { + dev_err(chip->dev, "Couldn't set WIN_UV_10_MV rc=%d\n", rc); + return rc; + } + /* * Disable slave WIN_UV detection, otherwise slave might not be * enabled due to WIN_UV until master drawing very high current. From 25fe865b9c064c4f309e077a701e14f1c3f5cf07 Mon Sep 17 00:00:00 2001 From: Asish Bhattacharya Date: Thu, 16 Jul 2020 17:04:07 +0530 Subject: [PATCH 281/592] dts: sdx: add support for tdm for sa515m card adding configuration for PRI or SEC TDM. Change-Id: I8e3c8c1255787fe9a2b6e902ca958a541becfbd9 Signed-off-by: Asish Bhattacharya --- arch/arm64/boot/dts/qcom/sa515m-ccard.dtsi | 4 ++ arch/arm64/boot/dts/qcom/sdx-audio-lpass.dtsi | 50 +++++++++++++------ 2 files changed, 40 insertions(+), 14 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sa515m-ccard.dtsi b/arch/arm64/boot/dts/qcom/sa515m-ccard.dtsi index 6430b1a47797..2adf53c610e1 100644 --- a/arch/arm64/boot/dts/qcom/sa515m-ccard.dtsi +++ b/arch/arm64/boot/dts/qcom/sa515m-ccard.dtsi @@ -51,7 +51,9 @@ <&afe_proxy_tx>, <&incall_record_rx>, <&incall_record_tx>, <&incall_music_rx>, <&dai_pri_tdm_rx_0>, <&dai_pri_tdm_tx_0>, + <&dai_pri_tdm_rx_1>, <&dai_pri_tdm_tx_1>, <&dai_sec_tdm_rx_0>, <&dai_sec_tdm_tx_0>, + <&dai_sec_tdm_rx_1>, <&dai_sec_tdm_tx_1>, <&dai_sec_auxpcm>, <&incall2_record_rx>, <&incall_music_2_rx>, <&incall_music_dl_rx>; asoc-cpu-names = "msm-dai-q6-auxpcm.1", @@ -63,7 +65,9 @@ "msm-dai-q6-dev.240", "msm-dai-q6-dev.32771", "msm-dai-q6-dev.32772", "msm-dai-q6-dev.32773", "msm-dai-q6-tdm.36864", "msm-dai-q6-tdm.36865", + "msm-dai-q6-tdm.36866", "msm-dai-q6-tdm.36867", "msm-dai-q6-tdm.36880", "msm-dai-q6-tdm.36881", + "msm-dai-q6-tdm.36882", "msm-dai-q6-tdm.36883", "msm-dai-q6-auxpcm.2", "msm-dai-q6-dev.32769", "msm-dai-q6-dev.32770", "msm-dai-q6-dev.32774"; asoc-codec = <&tlv320aic3x_codec>, <&stub_codec>; diff --git a/arch/arm64/boot/dts/qcom/sdx-audio-lpass.dtsi b/arch/arm64/boot/dts/qcom/sdx-audio-lpass.dtsi index dd63984d819f..d33b845500ae 100644 --- a/arch/arm64/boot/dts/qcom/sdx-audio-lpass.dtsi +++ b/arch/arm64/boot/dts/qcom/sdx-audio-lpass.dtsi @@ -216,8 +216,8 @@ qcom,msm-dai-tdm-pri-rx { compatible = "qcom,msm-dai-tdm"; qcom,msm-cpudai-tdm-group-id = <37120>; - qcom,msm-cpudai-tdm-group-num-ports = <1>; - qcom,msm-cpudai-tdm-group-port-id = <36864>; + qcom,msm-cpudai-tdm-group-num-ports = <2>; + qcom,msm-cpudai-tdm-group-port-id = <36864 36866>; qcom,msm-cpudai-tdm-clk-rate = <12288000>; qcom,msm-cpudai-tdm-clk-internal = <1>; qcom,msm-cpudai-tdm-sync-mode = <0>; @@ -232,13 +232,18 @@ qcom,msm-cpudai-tdm-data-align = <0>; }; + dai_pri_tdm_rx_1: qcom,msm-dai-q6-tdm-pri-rx-1 { + compatible = "qcom,msm-dai-q6-tdm"; + qcom,msm-cpudai-tdm-dev-id = <36866>; + qcom,msm-cpudai-tdm-data-align = <0>; + }; }; qcom,msm-dai-tdm-pri-tx { compatible = "qcom,msm-dai-tdm"; qcom,msm-cpudai-tdm-group-id = <37121>; - qcom,msm-cpudai-tdm-group-num-ports = <1>; - qcom,msm-cpudai-tdm-group-port-id = <36865>; + qcom,msm-cpudai-tdm-group-num-ports = <2>; + qcom,msm-cpudai-tdm-group-port-id = <36865 36867>; qcom,msm-cpudai-tdm-clk-rate = <12288000>; qcom,msm-cpudai-tdm-clk-internal = <1>; qcom,msm-cpudai-tdm-sync-mode = <0>; @@ -252,44 +257,61 @@ qcom,msm-cpudai-tdm-dev-id = <36865>; qcom,msm-cpudai-tdm-data-align = <0>; }; + dai_pri_tdm_tx_1: qcom,msm-dai-q6-tdm-pri-tx-1 { + compatible = "qcom,msm-dai-q6-tdm"; + qcom,msm-cpudai-tdm-dev-id = <36867>; + qcom,msm-cpudai-tdm-data-align = <0>; + }; }; qcom,msm-dai-tdm-sec-rx { compatible = "qcom,msm-dai-tdm"; qcom,msm-cpudai-tdm-group-id = <37136>; - qcom,msm-cpudai-tdm-group-num-ports = <1>; - qcom,msm-cpudai-tdm-group-port-id = <36880>; + qcom,msm-cpudai-tdm-group-num-ports = <2>; + qcom,msm-cpudai-tdm-group-port-id = <36880 36882>; qcom,msm-cpudai-tdm-clk-rate = <12288000>; qcom,msm-cpudai-tdm-clk-internal = <1>; - qcom,msm-cpudai-tdm-sync-mode = <1>; - qcom,msm-cpudai-tdm-sync-src = <0>; + qcom,msm-cpudai-tdm-sync-mode = <0>; + qcom,msm-cpudai-tdm-sync-src = <1>; qcom,msm-cpudai-tdm-data-out = <0>; qcom,msm-cpudai-tdm-invert-sync = <0>; - qcom,msm-cpudai-tdm-data-delay = <0>; + qcom,msm-cpudai-tdm-data-delay = <1>; + qcom,msm-cpudai-tdm-clk-attribute = /bits/ 16 <1>; dai_sec_tdm_rx_0: qcom,msm-dai-q6-tdm-sec-rx-0 { compatible = "qcom,msm-dai-q6-tdm"; qcom,msm-cpudai-tdm-dev-id = <36880>; qcom,msm-cpudai-tdm-data-align = <0>; }; + dai_sec_tdm_rx_1: qcom,msm-dai-q6-tdm-sec-rx-1 { + compatible = "qcom,msm-dai-q6-tdm"; + qcom,msm-cpudai-tdm-dev-id = <36882>; + qcom,msm-cpudai-tdm-data-align = <0>; + }; }; qcom,msm-dai-tdm-sec-tx { compatible = "qcom,msm-dai-tdm"; qcom,msm-cpudai-tdm-group-id = <37137>; - qcom,msm-cpudai-tdm-group-num-ports = <1>; - qcom,msm-cpudai-tdm-group-port-id = <36881>; + qcom,msm-cpudai-tdm-group-num-ports = <2>; + qcom,msm-cpudai-tdm-group-port-id = <36881 36883>; qcom,msm-cpudai-tdm-clk-rate = <12288000>; qcom,msm-cpudai-tdm-clk-internal = <1>; - qcom,msm-cpudai-tdm-sync-mode = <1>; - qcom,msm-cpudai-tdm-sync-src = <0>; + qcom,msm-cpudai-tdm-sync-mode = <0>; + qcom,msm-cpudai-tdm-sync-src = <1>; qcom,msm-cpudai-tdm-data-out = <0>; qcom,msm-cpudai-tdm-invert-sync = <0>; - qcom,msm-cpudai-tdm-data-delay = <0>; + qcom,msm-cpudai-tdm-data-delay = <1>; + qcom,msm-cpudai-tdm-clk-attribute = /bits/ 16 <1>; dai_sec_tdm_tx_0: qcom,msm-dai-q6-tdm-sec-tx-0 { compatible = "qcom,msm-dai-q6-tdm"; qcom,msm-cpudai-tdm-dev-id = <36881>; qcom,msm-cpudai-tdm-data-align = <0>; }; + dai_sec_tdm_tx_1: qcom,msm-dai-q6-tdm-sec-tx-1 { + compatible = "qcom,msm-dai-q6-tdm"; + qcom,msm-cpudai-tdm-dev-id = <36883>; + qcom,msm-cpudai-tdm-data-align = <0>; + }; }; qcom,msm-dai-mi2s { From 60e2bd859741212ccb0cc4a5c027e7ea9335b313 Mon Sep 17 00:00:00 2001 From: Tirupathi Reddy Date: Thu, 19 Jul 2018 19:26:05 +0530 Subject: [PATCH 282/592] msm: qpnp-power-on: configure KPDPWR_N S2 for HARD_RESET at TWM entry Configure KPDPWR_N to S2 during TWM entry to make sure that PMIC does a HARD_RESET during TWM if S2 reset is initiated. Change-Id: I4731487a2487af8aca8d5c30835ec6d87ee8fdc8 Signed-off-by: Tirupathi Reddy Signed-off-by: Anirudh Ghayal --- drivers/input/misc/qpnp-power-on.c | 38 ++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/drivers/input/misc/qpnp-power-on.c b/drivers/input/misc/qpnp-power-on.c index d930b6b451b9..e4025a6bbac8 100644 --- a/drivers/input/misc/qpnp-power-on.c +++ b/drivers/input/misc/qpnp-power-on.c @@ -541,6 +541,19 @@ static ssize_t debounce_us_store(struct device *dev, } static DEVICE_ATTR_RW(debounce_us); +static struct qpnp_pon_config * +qpnp_get_cfg(struct qpnp_pon *pon, u32 pon_type) +{ + int i; + + for (i = 0; i < pon->num_pon_config; i++) { + if (pon_type == pon->pon_cfg[i].pon_type) + return &pon->pon_cfg[i]; + } + + return NULL; +} + #define PON_TWM_ENTRY_PBS_BIT BIT(0) static int qpnp_pon_reset_config(struct qpnp_pon *pon, enum pon_power_off_type type) @@ -548,6 +561,7 @@ static int qpnp_pon_reset_config(struct qpnp_pon *pon, int rc; bool disable = false; u16 rst_en_reg; + struct qpnp_pon_config *cfg; /* Ignore the PS_HOLD reset config if TWM ENTRY is enabled */ if (pon->support_twm_config && pon->twm_state == PMIC_TWM_ENABLE) { @@ -558,6 +572,18 @@ static int qpnp_pon_reset_config(struct qpnp_pon *pon, rc); return rc; } + + cfg = qpnp_get_cfg(pon, PON_KPDPWR); + if (cfg) { + /* configure KPDPWR_S2 to Hard reset */ + rc = qpnp_pon_masked_write(pon, cfg->s2_cntl_addr, + QPNP_PON_S2_CNTL_TYPE_MASK, + PON_POWER_OFF_HARD_RESET); + if (rc < 0) + pr_err("Unable to config KPDPWR_N S2 for hard-reset rc=%d\n", + rc); + } + pr_crit("PMIC configured for TWM entry\n"); return 0; } @@ -917,18 +943,6 @@ static int qpnp_pon_store_and_clear_warm_reset(struct qpnp_pon *pon) return 0; } -static struct qpnp_pon_config *qpnp_get_cfg(struct qpnp_pon *pon, u32 pon_type) -{ - int i; - - for (i = 0; i < pon->num_pon_config; i++) { - if (pon_type == pon->pon_cfg[i].pon_type) - return &pon->pon_cfg[i]; - } - - return NULL; -} - static int qpnp_pon_input_dispatch(struct qpnp_pon *pon, u32 pon_type) { struct qpnp_pon_config *cfg = NULL; From 13a74c4a50f9241e2746de4f8f242c3544bf24b8 Mon Sep 17 00:00:00 2001 From: Prudhvi Yarlagadda Date: Wed, 29 Jul 2020 15:02:29 +0530 Subject: [PATCH 283/592] rpmsg: qcom_glink_bgcom: Clean up the channels after SSR Clean up the glink channels properly when a SSR of remote subsystem happens. Change-Id: Ie48ad98960baeca658831bbd59487fd96ee76c23 Signed-off-by: Prudhvi Yarlagadda --- drivers/rpmsg/qcom_glink_bgcom.c | 79 +++++++++++++++++++------------- 1 file changed, 48 insertions(+), 31 deletions(-) diff --git a/drivers/rpmsg/qcom_glink_bgcom.c b/drivers/rpmsg/qcom_glink_bgcom.c index d76658bc031d..09318fa0928e 100644 --- a/drivers/rpmsg/qcom_glink_bgcom.c +++ b/drivers/rpmsg/qcom_glink_bgcom.c @@ -2016,6 +2016,51 @@ static void glink_bgcom_linkup(struct glink_bgcom *glink) GLINK_ERR(glink, "Failed to link up %d\n", ret); } +static int glink_bgcom_remove_device(struct device *dev, void *data) +{ + device_unregister(dev); + + return 0; +} + +static int glink_bgcom_cleanup(struct glink_bgcom *glink) +{ + struct glink_bgcom_channel *channel; + int cid; + int ret; + + GLINK_INFO(glink, "\n"); + + atomic_set(&glink->in_reset, 1); + + kthread_flush_worker(&glink->kworker); + cancel_work_sync(&glink->rx_defer_work); + + ret = device_for_each_child(glink->dev, NULL, + glink_bgcom_remove_device); + if (ret) + dev_warn(glink->dev, "Can't remove GLINK devices: %d\n", ret); + + mutex_lock(&glink->idr_lock); + /* Release any defunct local channels, waiting for close-ack */ + idr_for_each_entry(&glink->lcids, channel, cid) { + /* Wakeup threads waiting for intent*/ + complete(&channel->intent_req_comp); + kref_put(&channel->refcount, glink_bgcom_channel_release); + idr_remove(&glink->lcids, cid); + } + + /* Release any defunct local channels, waiting for close-req */ + idr_for_each_entry(&glink->rcids, channel, cid) { + kref_put(&channel->refcount, glink_bgcom_channel_release); + idr_remove(&glink->rcids, cid); + } + + mutex_unlock(&glink->idr_lock); + + return ret; +} + static void glink_bgcom_event_handler(void *handle, void *priv_data, enum bgcom_event_type event, union bgcom_event_data_type *data) @@ -2066,7 +2111,7 @@ static void glink_bgcom_event_handler(void *handle, break; case BGCOM_EVENT_RESET_OCCURRED: glink->bgcom_status = BGCOM_RESET; - atomic_set(&glink->in_reset, 1); + glink_bgcom_cleanup(glink); break; case BGCOM_EVENT_ERROR_WRITE_FIFO_OVERRUN: case BGCOM_EVENT_ERROR_WRITE_FIFO_BUS_ERR: @@ -2195,18 +2240,9 @@ err_put_dev: } EXPORT_SYMBOL(glink_bgcom_probe); -static int glink_bgcom_remove_device(struct device *dev, void *data) -{ - device_unregister(dev); - - return 0; -} - static int glink_bgcom_remove(struct platform_device *pdev) { struct glink_bgcom *glink = platform_get_drvdata(pdev); - struct glink_bgcom_channel *channel; - int cid; int ret; GLINK_INFO(glink, "\n"); @@ -2215,30 +2251,11 @@ static int glink_bgcom_remove(struct platform_device *pdev) bgcom_close(glink->bgcom_handle); - kthread_flush_worker(&glink->kworker); - kthread_stop(glink->rx_task); - cancel_work_sync(&glink->rx_defer_work); + ret = glink_bgcom_cleanup(glink); - ret = device_for_each_child(glink->dev, NULL, - glink_bgcom_remove_device); - if (ret) - dev_warn(glink->dev, "Can't remove GLINK devices: %d\n", ret); + kthread_stop(glink->rx_task); mutex_lock(&glink->idr_lock); - /* Release any defunct local channels, waiting for close-ack */ - idr_for_each_entry(&glink->lcids, channel, cid) { - /* Wakeup threads waiting for intent*/ - complete(&channel->intent_req_comp); - kref_put(&channel->refcount, glink_bgcom_channel_release); - idr_remove(&glink->lcids, cid); - } - - /* Release any defunct local channels, waiting for close-req */ - idr_for_each_entry(&glink->rcids, channel, cid) { - kref_put(&channel->refcount, glink_bgcom_channel_release); - idr_remove(&glink->rcids, cid); - } - idr_destroy(&glink->lcids); idr_destroy(&glink->rcids); mutex_unlock(&glink->idr_lock); From 61d580d5ac91a63f0a7139070f71ac95e1ed5cdc Mon Sep 17 00:00:00 2001 From: Mohit Aggarwal Date: Wed, 29 Jul 2020 15:38:28 +0530 Subject: [PATCH 284/592] ARM: dts: msm: Add memshare for sdm429 Memshare driver allocates and share the memory with the modem clients for their use. The device tree information for memshare driver on sdm429 are added to specify client details. Change-Id: Ic8c7f5ba755f5bd0a866a7ff576471292d4edad3 Signed-off-by: Mohit Aggarwal --- arch/arm64/boot/dts/qcom/sdm429.dtsi | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sdm429.dtsi b/arch/arm64/boot/dts/qcom/sdm429.dtsi index 31218880dc07..b7dee8657bd4 100644 --- a/arch/arm64/boot/dts/qcom/sdm429.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm429.dtsi @@ -426,6 +426,33 @@ status = "disabled"; }; + qcom,memshare { + compatible = "qcom,memshare"; + + qcom,client_1 { + compatible = "qcom,memshare-peripheral"; + qcom,peripheral-size = <0x200000>; + qcom,client-id = <0>; + qcom,allocate-boot-time; + label = "modem"; + }; + + qcom,client_2 { + compatible = "qcom,memshare-peripheral"; + qcom,peripheral-size = <0x0>; + qcom,client-id = <2>; + label = "modem"; + }; + + mem_client_3_size: qcom,client_3 { + compatible = "qcom,memshare-peripheral"; + qcom,peripheral-size = <0x0>; + qcom,client-id = <1>; + qcom,allocate-on-request; + label = "modem"; + }; + }; + qcom,sps { compatible = "qcom,msm-sps-4k"; qcom,pipe-attr-ee; From 0a34474c492f08a821186e5a5eb0095a1ec77771 Mon Sep 17 00:00:00 2001 From: Yuanfang Zhang Date: Tue, 28 Jul 2020 19:09:59 +0800 Subject: [PATCH 285/592] coresight: cti: Add sys interface to show max trigger number Read the value of CTI devid register and get the value of max trigger number and max channel number. Add sys interface to show them. Change-Id: Ibea77cfd83007f58af1d285f05bbb338141b0dfc Signed-off-by: Tao,Zhang Signed-off-by: Yuanfang Zhang --- drivers/hwtracing/coresight/coresight-cti.c | 22 +++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/drivers/hwtracing/coresight/coresight-cti.c b/drivers/hwtracing/coresight/coresight-cti.c index 486356e527a5..605e76a0f184 100644 --- a/drivers/hwtracing/coresight/coresight-cti.c +++ b/drivers/hwtracing/coresight/coresight-cti.c @@ -63,6 +63,7 @@ do { \ #define ITTRIGOUTACK (0xEF0) #define ITCHIN (0xEF4) #define ITTRIGIN (0xEF8) +#define DEVID (0xFC8) #define CTI_MAX_TRIGGERS (32) #define CTI_MAX_CHANNELS (4) @@ -93,6 +94,8 @@ struct cti_drvdata { struct coresight_cti cti; int refcnt; int cpu; + unsigned int trig_num_max; + unsigned int ch_num_max; bool cti_save; bool cti_hwclk; bool l2_off; @@ -1360,6 +1363,19 @@ static ssize_t cti_store_disable_gate(struct device *dev, } static DEVICE_ATTR(disable_gate, 0200, NULL, cti_store_disable_gate); +static ssize_t show_info_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); + ssize_t size = 0; + + size = scnprintf(&buf[size], PAGE_SIZE, "%d %d\n", + drvdata->trig_num_max, drvdata->ch_num_max); + + return size; +} +static DEVICE_ATTR_RO(show_info); + static struct attribute *cti_attrs[] = { &dev_attr_show_trigin.attr, &dev_attr_show_trigout.attr, @@ -1376,6 +1392,7 @@ static struct attribute *cti_attrs[] = { &dev_attr_show_gate.attr, &dev_attr_enable_gate.attr, &dev_attr_disable_gate.attr, + &dev_attr_show_info.attr, NULL, }; @@ -1416,6 +1433,7 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id) { int ret; int trig; + unsigned int ctidevid; struct device *dev = &adev->dev; struct coresight_platform_data *pdata; struct cti_drvdata *drvdata; @@ -1522,6 +1540,10 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id) cpu_pm_register_notifier(&cti_cpu_pm_notifier); registered++; } + + ctidevid = cti_readl(drvdata, DEVID); + drvdata->trig_num_max = (ctidevid & GENMASK(15, 8)) >> 8; + drvdata->ch_num_max = (ctidevid & GENMASK(21, 16)) >> 16; pm_runtime_put(&adev->dev); dev_dbg(dev, "CTI initialized\n"); return 0; From d4cf52f936b81be3c1a732d8b44c181193034a1b Mon Sep 17 00:00:00 2001 From: Ray Zhang Date: Wed, 29 Jul 2020 19:01:19 +0800 Subject: [PATCH 286/592] Revert "drm/msm/sde: trigger single frame_done evt for vid encoder" This reverts commit ffba31d28364283635e018d1302c904a95fa6295. Change-Id: I66fef6aafe4eb7d1de366a795a484d32ee9bc645 Signed-off-by: Ray Zhang --- drivers/gpu/drm/msm/sde/sde_encoder.c | 13 ++---- .../gpu/drm/msm/sde/sde_encoder_phys_vid.c | 44 +++++++++++++------ 2 files changed, 34 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c index e598ce85fc9e..1cfa67a88d31 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder.c @@ -3662,7 +3662,7 @@ static void sde_encoder_frame_done_callback( { struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc); unsigned int i; - bool trigger = true, is_cmd_mode; + bool trigger = true; enum sde_rm_topology_name topology = SDE_RM_TOPOLOGY_NONE; if (!drm_enc || !sde_enc->cur_master) { @@ -3674,12 +3674,10 @@ static void sde_encoder_frame_done_callback( sde_enc->crtc_frame_event_cb_data.connector = sde_enc->cur_master->connector; - is_cmd_mode = sde_enc->disp_info.capabilities & - MSM_DISPLAY_CAP_CMD_MODE; if (event & (SDE_ENCODER_FRAME_EVENT_DONE | SDE_ENCODER_FRAME_EVENT_ERROR - | SDE_ENCODER_FRAME_EVENT_PANEL_DEAD) && is_cmd_mode) { + | SDE_ENCODER_FRAME_EVENT_PANEL_DEAD)) { if (ready_phys->connector) topology = sde_connector_get_topology_name( ready_phys->connector); @@ -3719,14 +3717,9 @@ static void sde_encoder_frame_done_callback( atomic_set(&sde_enc->frame_done_cnt[i], 0); } } else { - if (sde_enc->crtc_frame_event_cb) { - if (!is_cmd_mode) - sde_encoder_resource_control(drm_enc, - SDE_ENC_RC_EVENT_FRAME_DONE); - + if (sde_enc->crtc_frame_event_cb) sde_enc->crtc_frame_event_cb( &sde_enc->crtc_frame_event_cb_data, event); - } } } diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c index 670c405b6605..426870b57164 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c @@ -594,11 +594,12 @@ static void sde_encoder_phys_vid_vblank_irq(void *arg, int irq_idx) pend_ret_fence_cnt = atomic_read(&phys_enc->pending_retire_fence_cnt); /* signal only for master, where there is a pending kickoff */ - if (sde_encoder_phys_vid_is_master(phys_enc) && - atomic_add_unless(&phys_enc->pending_retire_fence_cnt, -1, 0)) { - event = SDE_ENCODER_FRAME_EVENT_DONE | - SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE | - SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE; + if (sde_encoder_phys_vid_is_master(phys_enc)) { + if (atomic_add_unless(&phys_enc->pending_retire_fence_cnt, + -1, 0)) + event |= SDE_ENCODER_FRAME_EVENT_DONE | + SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE | + SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE; } not_flushed: @@ -948,15 +949,21 @@ static int _sde_encoder_phys_vid_wait_for_vblank( { struct sde_encoder_wait_info wait_info = {0}; int ret = 0; - u32 event = SDE_ENCODER_FRAME_EVENT_ERROR | - SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE | - SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE; + u32 event = 0, event_helper = 0; if (!phys_enc) { pr_err("invalid encoder\n"); return -EINVAL; } + if (!sde_encoder_phys_vid_is_master(phys_enc)) { + /* signal done for slave video encoder, unless it is pp-split */ + if (!_sde_encoder_phys_is_ppsplit(phys_enc) && notify) { + event = SDE_ENCODER_FRAME_EVENT_DONE; + goto end; + } + } + wait_info.wq = &phys_enc->pending_kickoff_wq; wait_info.atomic_cnt = &phys_enc->pending_kickoff_cnt; wait_info.timeout_ms = KICKOFF_TIMEOUT_MS; @@ -965,12 +972,23 @@ static int _sde_encoder_phys_vid_wait_for_vblank( ret = sde_encoder_helper_wait_for_irq(phys_enc, INTR_IDX_VSYNC, &wait_info); - if (notify && (ret == -ETIMEDOUT) && - atomic_add_unless(&phys_enc->pending_retire_fence_cnt, -1, 0) && - phys_enc->parent_ops.handle_frame_done) - phys_enc->parent_ops.handle_frame_done( - phys_enc->parent, phys_enc, event); + event_helper = SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE + | SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE; + if (notify && (ret == -ETIMEDOUT)) { + event = SDE_ENCODER_FRAME_EVENT_ERROR; + if (atomic_add_unless(&phys_enc->pending_retire_fence_cnt, + -1, 0)) + event |= event_helper; + } + +end: + SDE_EVT32(DRMID(phys_enc->parent), event, notify, ret, + ret ? SDE_EVTLOG_FATAL : 0); + if (phys_enc->parent_ops.handle_frame_done && event) + phys_enc->parent_ops.handle_frame_done( + phys_enc->parent, phys_enc, + event); return ret; } From 91ec8f018480d7c7e846430a8433519cf79804e7 Mon Sep 17 00:00:00 2001 From: Ray Zhang Date: Wed, 29 Jul 2020 19:01:24 +0800 Subject: [PATCH 287/592] Revert "drm/msm/sde: avoid frame_done event trigger for idle scenario" This reverts commit ea07f9fa9ca48487d5083f6e57bafb8579e32861. Change-Id: Icb59dc20954a0b59dc36e9abf41e6021f26453ba Signed-off-by: Ray Zhang --- .../gpu/drm/msm/sde/sde_encoder_phys_vid.c | 34 +++++++++++-------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c index 426870b57164..c6c2c99ef496 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c @@ -597,8 +597,7 @@ static void sde_encoder_phys_vid_vblank_irq(void *arg, int irq_idx) if (sde_encoder_phys_vid_is_master(phys_enc)) { if (atomic_add_unless(&phys_enc->pending_retire_fence_cnt, -1, 0)) - event |= SDE_ENCODER_FRAME_EVENT_DONE | - SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE | + event |= SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE | SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE; } @@ -617,10 +616,9 @@ not_flushed: phys_enc); SDE_EVT32_IRQ(DRMID(phys_enc->parent), phys_enc->hw_intf->idx - INTF_0, - old_cnt, atomic_read(&phys_enc->pending_kickoff_cnt), - reset_status ? SDE_EVTLOG_ERROR : 0, + old_cnt, new_cnt, reset_status ? SDE_EVTLOG_ERROR : 0, flush_register, event, - atomic_read(&phys_enc->pending_retire_fence_cnt)); + pend_ret_fence_cnt); /* Signal any waiting atomic commit thread */ wake_up_all(&phys_enc->pending_kickoff_wq); @@ -949,25 +947,27 @@ static int _sde_encoder_phys_vid_wait_for_vblank( { struct sde_encoder_wait_info wait_info = {0}; int ret = 0; - u32 event = 0, event_helper = 0; + u32 event = 0; + u32 event_helper = 0; if (!phys_enc) { pr_err("invalid encoder\n"); return -EINVAL; } + wait_info.wq = &phys_enc->pending_kickoff_wq; + wait_info.atomic_cnt = &phys_enc->pending_kickoff_cnt; + wait_info.timeout_ms = KICKOFF_TIMEOUT_MS; + if (!sde_encoder_phys_vid_is_master(phys_enc)) { /* signal done for slave video encoder, unless it is pp-split */ if (!_sde_encoder_phys_is_ppsplit(phys_enc) && notify) { event = SDE_ENCODER_FRAME_EVENT_DONE; goto end; } + return 0; } - wait_info.wq = &phys_enc->pending_kickoff_wq; - wait_info.atomic_cnt = &phys_enc->pending_kickoff_cnt; - wait_info.timeout_ms = KICKOFF_TIMEOUT_MS; - /* Wait for kickoff to complete */ ret = sde_encoder_helper_wait_for_irq(phys_enc, INTR_IDX_VSYNC, &wait_info); @@ -975,11 +975,15 @@ static int _sde_encoder_phys_vid_wait_for_vblank( event_helper = SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE | SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE; - if (notify && (ret == -ETIMEDOUT)) { - event = SDE_ENCODER_FRAME_EVENT_ERROR; - if (atomic_add_unless(&phys_enc->pending_retire_fence_cnt, - -1, 0)) - event |= event_helper; + if (notify) { + if (ret == -ETIMEDOUT) { + event = SDE_ENCODER_FRAME_EVENT_ERROR; + if (atomic_add_unless( + &phys_enc->pending_retire_fence_cnt, -1, 0)) + event |= event_helper; + } else if (!ret) { + event = SDE_ENCODER_FRAME_EVENT_DONE; + } } end: From 7a4079004d1bfabbf6ef17b083afb2737e4a2229 Mon Sep 17 00:00:00 2001 From: Ray Zhang Date: Wed, 29 Jul 2020 19:01:28 +0800 Subject: [PATCH 288/592] Revert "drm/msm/sde: initialize sde_encoder_wait_info before usage" This reverts commit 4d761a7dbb610d9acd59c77ce24cfb35e82c0701. Change-Id: I98cc3d192874f83608f4c21b57e2e10fc30441bf Signed-off-by: Ray Zhang --- drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c | 8 ++++---- drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c | 2 +- drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c index 3d31c6497f6d..ef0f55041a9f 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c @@ -708,7 +708,7 @@ static int _sde_encoder_phys_cmd_wait_for_idle( { struct sde_encoder_phys_cmd *cmd_enc = to_sde_encoder_phys_cmd(phys_enc); - struct sde_encoder_wait_info wait_info = {0}; + struct sde_encoder_wait_info wait_info = {NULL}; bool recovery_events; int ret; @@ -761,7 +761,7 @@ static int _sde_encoder_phys_cmd_wait_for_autorefresh_done( { struct sde_encoder_phys_cmd *cmd_enc = to_sde_encoder_phys_cmd(phys_enc); - struct sde_encoder_wait_info wait_info = {0}; + struct sde_encoder_wait_info wait_info = {NULL}; int ret = 0; if (!phys_enc) { @@ -1386,7 +1386,7 @@ static int _sde_encoder_phys_cmd_wait_for_wr_ptr( { struct sde_encoder_phys_cmd *cmd_enc = to_sde_encoder_phys_cmd(phys_enc); - struct sde_encoder_wait_info wait_info = {0}; + struct sde_encoder_wait_info wait_info = {NULL}; int ret; bool frame_pending = true; struct sde_hw_ctl *ctl; @@ -1536,7 +1536,7 @@ static int sde_encoder_phys_cmd_wait_for_vblank( { int rc = 0; struct sde_encoder_phys_cmd *cmd_enc; - struct sde_encoder_wait_info wait_info = {0}; + struct sde_encoder_wait_info wait_info = {NULL}; if (!phys_enc) return -EINVAL; diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c index c6c2c99ef496..0f73d4c7bf42 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c @@ -945,7 +945,7 @@ static void sde_encoder_phys_vid_get_hw_resources( static int _sde_encoder_phys_vid_wait_for_vblank( struct sde_encoder_phys *phys_enc, bool notify) { - struct sde_encoder_wait_info wait_info = {0}; + struct sde_encoder_wait_info wait_info; int ret = 0; u32 event = 0; u32 event_helper = 0; diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c index e79450e2b941..12164d37f186 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c @@ -1227,7 +1227,7 @@ static int _sde_encoder_phys_wb_wait_for_commit_done( u32 event = 0; u64 wb_time = 0; int rc = 0; - struct sde_encoder_wait_info wait_info = {0}; + struct sde_encoder_wait_info wait_info; /* Return EWOULDBLOCK since we know the wait isn't necessary */ if (phys_enc->enable_state == SDE_ENC_DISABLED) { From 154dd4c4fc97b2bd1628986276defdb78b38415e Mon Sep 17 00:00:00 2001 From: Ray Zhang Date: Wed, 29 Jul 2020 19:01:31 +0800 Subject: [PATCH 289/592] Revert "ARM: dts: msm: update frame threshold time for atoll" This reverts commit b39742a9027aa743cdb90bfe80c277566df9ca17. Change-Id: I8e6fb2e62118c17c8c3a76acb33c566d595a090f Signed-off-by: Ray Zhang --- arch/arm64/boot/dts/qcom/atoll-sde.dtsi | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/atoll-sde.dtsi b/arch/arm64/boot/dts/qcom/atoll-sde.dtsi index 5455b376e056..31c1f661bda6 100644 --- a/arch/arm64/boot/dts/qcom/atoll-sde.dtsi +++ b/arch/arm64/boot/dts/qcom/atoll-sde.dtsi @@ -419,7 +419,6 @@ compatible = "qcom,dsi-ctrl-hw-v2.4"; label = "dsi-ctrl-0"; cell-index = <0>; - frame-threshold-time-us = <800>; reg = <0xae94000 0x400>, <0xaf08000 0x4>; reg-names = "dsi_ctrl", "disp_cc_base"; From 450ed645537424ce91800d3001cf247e52b63b44 Mon Sep 17 00:00:00 2001 From: Ray Zhang Date: Wed, 29 Jul 2020 19:01:33 +0800 Subject: [PATCH 290/592] Revert "dt-bindings: Add frame threshold property for dsi controller" This reverts commit 33003ffcd787d8c003b0feb744115dc19af045fd. Change-Id: If9b409f3db5885ea789bfdd7d963689732505a46 Signed-off-by: Ray Zhang --- Documentation/devicetree/bindings/display/msm/dsi.txt | 8 -------- 1 file changed, 8 deletions(-) diff --git a/Documentation/devicetree/bindings/display/msm/dsi.txt b/Documentation/devicetree/bindings/display/msm/dsi.txt index d9e3421c34ca..17f9d7516ffb 100644 --- a/Documentation/devicetree/bindings/display/msm/dsi.txt +++ b/Documentation/devicetree/bindings/display/msm/dsi.txt @@ -127,13 +127,6 @@ Optional properties: turns off PHY pmic power supply, phy ldo and DSI Lane ldo during idle screen (footswitch control off) when this property is enabled. - qcom,dsi-phy-regulator-min-datarate-bps: Minimum per lane data rate (bps) to turn on PHY regulator. -- frame-threshold-time-us: For command mode panel, this specifies the idle - time for dsi controller where no active data is - sent to the panel, as controller is done sending - active pixels. If there is no desired DSI clocks - specified, then clocks will be derived from this - threshold time, which has a default value in chipset - based on the CPU processing power. [1] Documentation/devicetree/bindings/clock/clock-bindings.txt [2] Documentation/devicetree/bindings/graph.txt @@ -185,7 +178,6 @@ Example: qcom,sync-dual-dsi; qcom,mdss-mdp-transfer-time-us = <12000>; - frame-threshold-time-us = <800>; pinctrl-names = "default", "sleep"; pinctrl-0 = <&dsi_active>; From f9626a17a2e98e60b6b21c5bde2b29a6d071ecf1 Mon Sep 17 00:00:00 2001 From: Ray Zhang Date: Wed, 29 Jul 2020 19:01:35 +0800 Subject: [PATCH 291/592] Revert "disp: msm: dsi: update dsi pclk in panel mode settings" This reverts commit 64d303015644d2c74d7ea55dffef090762dc9b22. Change-Id: I700651e1259ef607df92447b927ef6de4f41a011 Signed-off-by: Ray Zhang --- drivers/gpu/drm/msm/dsi-staging/dsi_panel.c | 55 +++++++++------------ 1 file changed, 24 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c index dcdcd45c7648..29fd352bdcb6 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c @@ -2555,6 +2555,9 @@ static int dsi_panel_parse_phy_timing(struct dsi_display_mode *mode, u32 len, i; int rc = 0; struct dsi_display_mode_priv_info *priv_info; + u64 h_period, v_period; + u64 refresh_rate = TICKS_IN_MICRO_SECOND; + struct dsi_mode_info *timing = NULL; u64 pixel_clk_khz; if (!mode || !mode->priv_info) @@ -2578,19 +2581,22 @@ static int dsi_panel_parse_phy_timing(struct dsi_display_mode *mode, priv_info->phy_timing_len = len; }; - if (panel_mode == DSI_OP_VIDEO_MODE) { - /* - * For command mode we update the pclk as part of - * function dsi_panel_calc_dsi_transfer_time( ) - * as we set it based on dsi clock or mdp transfer time. - */ - pixel_clk_khz = (DSI_H_TOTAL_DSC(&mode->timing) * - DSI_V_TOTAL(&mode->timing) * - mode->timing.refresh_rate); - do_div(pixel_clk_khz, 1000); - mode->pixel_clk_khz = pixel_clk_khz; + timing = &mode->timing; + + if (panel_mode == DSI_OP_CMD_MODE) { + h_period = DSI_H_ACTIVE_DSC(timing); + v_period = timing->v_active; + do_div(refresh_rate, priv_info->mdp_transfer_time_us); + } else { + h_period = DSI_H_TOTAL_DSC(timing); + v_period = DSI_V_TOTAL(timing); + refresh_rate = timing->refresh_rate; } + pixel_clk_khz = h_period * v_period * refresh_rate; + do_div(pixel_clk_khz, 1000); + mode->pixel_clk_khz = pixel_clk_khz; + return rc; } @@ -3626,19 +3632,16 @@ void dsi_panel_calc_dsi_transfer_time(struct dsi_host_common_cfg *config, struct dsi_display_mode *mode, u32 frame_threshold_us) { u32 frame_time_us, nslices; - u64 min_bitclk_hz, total_active_pixels, bits_per_line, pclk_rate_hz, - dsi_transfer_time_us, pixel_clk_khz; + u64 min_bitclk, total_active_pixels, bits_per_line, + dsi_transfer_time_us; struct msm_display_dsc_info *dsc = mode->timing.dsc; struct dsi_mode_info *timing = &mode->timing; - struct dsi_display_mode *display_mode; /* Packet overlead in bits,2 bytes header + 2 bytes checksum * + 1 byte dcs data command. */ const u32 packet_overhead = 56; - display_mode = container_of(timing, struct dsi_display_mode, timing); - frame_time_us = mult_frac(1000, 1000, (timing->refresh_rate)); if (timing->dsc_enabled) { @@ -3650,22 +3653,22 @@ void dsi_panel_calc_dsi_transfer_time(struct dsi_host_common_cfg *config, packet_overhead) * nslices; bits_per_line = bits_per_line / (config->num_data_lanes); - min_bitclk_hz = (bits_per_line * timing->v_active * + min_bitclk = (bits_per_line * timing->v_active * timing->refresh_rate); } else { total_active_pixels = ((DSI_H_ACTIVE_DSC(timing) * timing->v_active)); /* calculate the actual bitclk needed to transfer the frame */ - min_bitclk_hz = (total_active_pixels * (timing->refresh_rate) * + min_bitclk = (total_active_pixels * (timing->refresh_rate) * (config->bpp)); - do_div(min_bitclk_hz, config->num_data_lanes); + do_div(min_bitclk, config->num_data_lanes); } - timing->min_dsi_clk_hz = min_bitclk_hz; + timing->min_dsi_clk_hz = min_bitclk; if (timing->clk_rate_hz) { /* adjust the transfer time proportionately for bit clk*/ - dsi_transfer_time_us = frame_time_us * min_bitclk_hz; + dsi_transfer_time_us = frame_time_us * min_bitclk; do_div(dsi_transfer_time_us, timing->clk_rate_hz); timing->dsi_transfer_time_us = dsi_transfer_time_us; } else if (mode->priv_info->mdp_transfer_time_us) { @@ -3675,16 +3678,6 @@ void dsi_panel_calc_dsi_transfer_time(struct dsi_host_common_cfg *config, timing->dsi_transfer_time_us = frame_time_us - frame_threshold_us; } - - /* Calculate pclk_khz to update modeinfo */ - pclk_rate_hz = min_bitclk_hz * frame_time_us; - do_div(pclk_rate_hz, timing->dsi_transfer_time_us); - - pixel_clk_khz = pclk_rate_hz * config->num_data_lanes; - do_div(pixel_clk_khz, config->bpp); - display_mode->pixel_clk_khz = pixel_clk_khz; - - display_mode->pixel_clk_khz = display_mode->pixel_clk_khz / 1000; } int dsi_panel_get_mode(struct dsi_panel *panel, From 62b669dfc7465a881984f9251cfbcc8df51f1316 Mon Sep 17 00:00:00 2001 From: Ray Zhang Date: Wed, 29 Jul 2020 19:01:37 +0800 Subject: [PATCH 292/592] Revert "drm/msm/dsi-staging: update frame transfer time calculations" This reverts commit 1f4642125869815ec5800f1d0e56b5d70abeef22. Change-Id: I7408a11c4bbfd8908d66af91a4cba84878efaec1 Signed-off-by: Ray Zhang --- drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c | 11 +---------- drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h | 5 ----- drivers/gpu/drm/msm/dsi-staging/dsi_display.c | 5 +---- drivers/gpu/drm/msm/dsi-staging/dsi_panel.c | 17 +++++++++-------- drivers/gpu/drm/msm/dsi-staging/dsi_panel.h | 2 +- 5 files changed, 12 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c index 7e42b3469451..798ee09ae7bf 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c @@ -1746,7 +1746,7 @@ static int dsi_enable_io_clamp(struct dsi_ctrl *dsi_ctrl, static int dsi_ctrl_dts_parse(struct dsi_ctrl *dsi_ctrl, struct device_node *of_node) { - u32 index = 0, frame_threshold_time_us = 0; + u32 index = 0; int rc = 0; if (!dsi_ctrl || !of_node) { @@ -1775,15 +1775,6 @@ static int dsi_ctrl_dts_parse(struct dsi_ctrl *dsi_ctrl, dsi_ctrl->split_link_supported = of_property_read_bool(of_node, "qcom,split-link-supported"); - rc = of_property_read_u32(of_node, "frame-threshold-time-us", - &frame_threshold_time_us); - if (rc) { - pr_debug("frame-threshold-time not specified, defaulting\n"); - frame_threshold_time_us = 2666; - } - - dsi_ctrl->frame_threshold_time_us = frame_threshold_time_us; - return 0; } diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h index 9198e28475bb..f99693265990 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h @@ -230,9 +230,6 @@ struct dsi_ctrl_interrupts { * @debugfs_root: Root for debugfs entries. * @misr_enable: Frame MISR enable/disable * @misr_cache: Cached Frame MISR value - * @frame_threshold_time_us: Frame threshold time in microseconds, where - * dsi data lane will be idle i.e from pingpong done to - * next TE for command mode. * @phy_isolation_enabled: A boolean property allows to isolate the phy from * dsi controller and run only dsi controller. * @null_insertion_enabled: A boolean property to allow dsi controller to @@ -285,8 +282,6 @@ struct dsi_ctrl { bool misr_enable; u32 misr_cache; - u32 frame_threshold_time_us; - /* Check for spurious interrupts */ unsigned long jiffies_start; unsigned int error_interrupt_count; diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c index d1a23cf37e86..6d14cdf29cc7 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c @@ -6267,7 +6267,6 @@ int dsi_display_get_modes(struct dsi_display *display, struct dsi_display_mode **out_modes) { struct dsi_dfps_capabilities dfps_caps; - struct dsi_display_ctrl *ctrl; struct dsi_host_common_cfg *host = &display->panel->host_config; bool is_split_link, is_cmd_mode; u32 num_dfps_rates, timing_mode_count, display_mode_count; @@ -6281,7 +6280,6 @@ int dsi_display_get_modes(struct dsi_display *display, } *out_modes = NULL; - ctrl = &display->ctrl[0]; mutex_lock(&display->display_lock); @@ -6311,7 +6309,6 @@ int dsi_display_get_modes(struct dsi_display *display, for (mode_idx = 0; mode_idx < timing_mode_count; mode_idx++) { struct dsi_display_mode display_mode; int topology_override = NO_OVERRIDE; - u32 frame_threshold_us = ctrl->ctrl->frame_threshold_time_us; if (display->cmdline_timing == mode_idx) topology_override = display->cmdline_topology; @@ -6336,7 +6333,7 @@ int dsi_display_get_modes(struct dsi_display *display, if (is_cmd_mode) { dsi_panel_calc_dsi_transfer_time( &display->panel->host_config, - &display_mode, frame_threshold_us); + &display_mode.timing); display_mode.priv_info->dsi_transfer_time_us = display_mode.timing.dsi_transfer_time_us; display_mode.priv_info->min_dsi_clk_hz = diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c index 29fd352bdcb6..bc1d8eb01418 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c @@ -35,6 +35,8 @@ #define DSI_PANEL_DEFAULT_LABEL "Default dsi panel" +#define DEFAULT_MDP_TRANSFER_TIME 14000 + #define DEFAULT_PANEL_JITTER_NUMERATOR 2 #define DEFAULT_PANEL_JITTER_DENOMINATOR 1 #define DEFAULT_PANEL_JITTER_ARRAY_SIZE 2 @@ -849,7 +851,7 @@ static int dsi_panel_parse_timing(struct dsi_mode_info *mode, &mode->mdp_transfer_time_us); if (rc) { pr_debug("fallback to default mdp-transfer-time-us\n"); - mode->mdp_transfer_time_us = 0; + mode->mdp_transfer_time_us = DEFAULT_MDP_TRANSFER_TIME; } display_mode->priv_info->mdp_transfer_time_us = mode->mdp_transfer_time_us; @@ -3629,19 +3631,21 @@ void dsi_panel_put_mode(struct dsi_display_mode *mode) } void dsi_panel_calc_dsi_transfer_time(struct dsi_host_common_cfg *config, - struct dsi_display_mode *mode, u32 frame_threshold_us) + struct dsi_mode_info *timing) { u32 frame_time_us, nslices; u64 min_bitclk, total_active_pixels, bits_per_line, dsi_transfer_time_us; - struct msm_display_dsc_info *dsc = mode->timing.dsc; - struct dsi_mode_info *timing = &mode->timing; + struct msm_display_dsc_info *dsc = timing->dsc; /* Packet overlead in bits,2 bytes header + 2 bytes checksum * + 1 byte dcs data command. */ const u32 packet_overhead = 56; + /* Default time between pingpong done to TE in microsecs */ + const u32 max_tx_threshold_time = 2166; + frame_time_us = mult_frac(1000, 1000, (timing->refresh_rate)); if (timing->dsc_enabled) { @@ -3671,12 +3675,9 @@ void dsi_panel_calc_dsi_transfer_time(struct dsi_host_common_cfg *config, dsi_transfer_time_us = frame_time_us * min_bitclk; do_div(dsi_transfer_time_us, timing->clk_rate_hz); timing->dsi_transfer_time_us = dsi_transfer_time_us; - } else if (mode->priv_info->mdp_transfer_time_us) { - timing->dsi_transfer_time_us = - mode->priv_info->mdp_transfer_time_us; } else { timing->dsi_transfer_time_us = frame_time_us - - frame_threshold_us; + max_tx_threshold_time; } } diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h index 7d5a7e8c4715..59d99b0510cc 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h @@ -338,6 +338,6 @@ int dsi_panel_parse_esd_reg_read_configs(struct dsi_panel *panel); void dsi_panel_ext_bridge_put(struct dsi_panel *panel); void dsi_panel_calc_dsi_transfer_time(struct dsi_host_common_cfg *config, - struct dsi_display_mode *mode, u32 frame_threshold_us); + struct dsi_mode_info *timing); #endif /* _DSI_PANEL_H_ */ From 35ffecb3431b650115a6c5a40a23d783c80d74c9 Mon Sep 17 00:00:00 2001 From: Ray Zhang Date: Wed, 29 Jul 2020 19:01:40 +0800 Subject: [PATCH 293/592] Revert "drm/msm/dsi-staging: update dsi clock calculations" This reverts commit fa50032c8ae16fd4c51c8df4437003d13b88aac6. Change-Id: Ida5a997573388afdb3750f27bf71f2e41de8f87e Signed-off-by: Ray Zhang --- drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c | 45 +++++++------ drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h | 2 - drivers/gpu/drm/msm/dsi-staging/dsi_defs.h | 12 ---- drivers/gpu/drm/msm/dsi-staging/dsi_display.c | 28 +------- drivers/gpu/drm/msm/dsi-staging/dsi_panel.c | 65 ------------------- drivers/gpu/drm/msm/dsi-staging/dsi_panel.h | 3 - 6 files changed, 24 insertions(+), 131 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c index 798ee09ae7bf..91ea89bd7ac3 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c @@ -840,24 +840,21 @@ int dsi_ctrl_pixel_format_to_bpp(enum dsi_pixel_format dst_format) } static int dsi_ctrl_update_link_freqs(struct dsi_ctrl *dsi_ctrl, - struct dsi_host_config *config, void *clk_handle, - struct dsi_display_mode *mode) + struct dsi_host_config *config, void *clk_handle) { int rc = 0; u32 num_of_lanes = 0; - u32 bpp, frame_time_us; + u32 bpp; + u64 refresh_rate = TICKS_IN_MICRO_SECOND; u64 h_period, v_period, bit_rate, pclk_rate, bit_rate_per_lane, byte_clk_rate, byte_intf_clk_rate; struct dsi_host_common_cfg *host_cfg = &config->common_config; struct dsi_split_link_config *split_link = &host_cfg->split_link; struct dsi_mode_info *timing = &config->video_timing; u32 bits_per_symbol = 16, num_of_symbols = 7; /* For Cphy */ - u64 dsi_transfer_time_us = mode->priv_info->dsi_transfer_time_us; - u64 min_dsi_clk_hz = mode->priv_info->min_dsi_clk_hz; - /* Get bits per pxl in desitination format */ + /* Get bits per pxl in desitnation format */ bpp = dsi_ctrl_pixel_format_to_bpp(host_cfg->dst_format); - frame_time_us = mult_frac(1000, 1000, (timing->refresh_rate)); if (host_cfg->data_lanes & DSI_DATA_LANE_0) num_of_lanes++; @@ -871,20 +868,25 @@ static int dsi_ctrl_update_link_freqs(struct dsi_ctrl *dsi_ctrl, if (split_link->split_link_enabled) num_of_lanes = split_link->lanes_per_sublink; - config->common_config.num_data_lanes = num_of_lanes; - config->common_config.bpp = bpp; + if (config->bit_clk_rate_hz_override == 0) { + if (config->panel_mode == DSI_OP_CMD_MODE) { + h_period = DSI_H_ACTIVE_DSC(timing); + h_period += timing->overlap_pixels; + v_period = timing->v_active; - if (config->bit_clk_rate_hz_override != 0) { - bit_rate = config->bit_clk_rate_hz_override * num_of_lanes; - } else if (config->panel_mode == DSI_OP_CMD_MODE) { - /* Calculate the bit rate needed to match dsi transfer time */ - bit_rate = min_dsi_clk_hz * frame_time_us; - do_div(bit_rate, dsi_transfer_time_us); - bit_rate = bit_rate * num_of_lanes; + do_div(refresh_rate, timing->mdp_transfer_time_us); + } else { + h_period = DSI_H_TOTAL_DSC(timing); + v_period = DSI_V_TOTAL(timing); + refresh_rate = timing->refresh_rate; + } + bit_rate = h_period * v_period * refresh_rate * bpp; } else { - h_period = DSI_H_TOTAL_DSC(timing); - v_period = DSI_V_TOTAL(timing); - bit_rate = h_period * v_period * timing->refresh_rate * bpp; + bit_rate = config->bit_clk_rate_hz_override * num_of_lanes; + if (host_cfg->phy_type == DSI_PHY_TYPE_CPHY) { + bit_rate *= bits_per_symbol; + do_div(bit_rate, num_of_symbols); + } } pclk_rate = bit_rate; @@ -2933,7 +2935,6 @@ error: * dsi_ctrl_update_host_config() - update dsi host configuration * @dsi_ctrl: DSI controller handle. * @config: DSI host configuration. - * @mode: DSI host mode selected. * @flags: dsi_mode_flags modifying the behavior * * Updates driver with new Host configuration to use for host initialization. @@ -2944,7 +2945,6 @@ error: */ int dsi_ctrl_update_host_config(struct dsi_ctrl *ctrl, struct dsi_host_config *config, - struct dsi_display_mode *mode, int flags, void *clk_handle) { int rc = 0; @@ -2968,8 +2968,7 @@ int dsi_ctrl_update_host_config(struct dsi_ctrl *ctrl, * for dynamic clk switch case link frequence would * be updated dsi_display_dynamic_clk_switch(). */ - rc = dsi_ctrl_update_link_freqs(ctrl, config, clk_handle, - mode); + rc = dsi_ctrl_update_link_freqs(ctrl, config, clk_handle); if (rc) { pr_err("[%s] failed to update link frequencies, rc=%d\n", ctrl->name, rc); diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h index f99693265990..a978beb2aff7 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h @@ -352,7 +352,6 @@ int dsi_ctrl_validate_timing(struct dsi_ctrl *dsi_ctrl, * dsi_ctrl_update_host_config() - update dsi host configuration * @dsi_ctrl: DSI controller handle. * @config: DSI host configuration. - * @mode: DSI host mode selected. * @flags: dsi_mode_flags modifying the behavior * @clk_handle: Clock handle for DSI clocks * @@ -364,7 +363,6 @@ int dsi_ctrl_validate_timing(struct dsi_ctrl *dsi_ctrl, */ int dsi_ctrl_update_host_config(struct dsi_ctrl *dsi_ctrl, struct dsi_host_config *config, - struct dsi_display_mode *mode, int flags, void *clk_handle); /** diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h b/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h index 4cc58112f8f8..e479fa8e0b69 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h @@ -410,10 +410,8 @@ struct dsi_panel_cmd_set { * @v_sync_polarity: Polarity of VSYNC (false is active low). * @refresh_rate: Refresh rate in Hz. * @clk_rate_hz: DSI bit clock rate per lane in Hz. - * @min_dsi_clk_hz: Min DSI bit clock to transfer in vsync time. * @mdp_transfer_time_us: Specifies the mdp transfer time for command mode * panels in microseconds. - * @dsi_transfer_time_us: Specifies dsi transfer time for command mode. * @overlap_pixels: overlap pixels for certain panels. * @dsc_enabled: DSC compression enabled. * @dsc: DSC compression configuration. @@ -435,9 +433,7 @@ struct dsi_mode_info { u32 refresh_rate; u64 clk_rate_hz; - u64 min_dsi_clk_hz; u32 mdp_transfer_time_us; - u32 dsi_transfer_time_us; u32 overlap_pixels; bool dsc_enabled; struct msm_display_dsc_info *dsc; @@ -460,8 +456,6 @@ struct dsi_split_link_config { * struct dsi_host_common_cfg - Host configuration common to video and cmd mode * @dst_format: Destination pixel format. * @data_lanes: Physical data lanes to be enabled. - * @num_data_lanes: Number of physical data lanes. - * @bpp: Number of bits per pixel. * @en_crc_check: Enable CRC checks. * @en_ecc_check: Enable ECC checks. * @te_mode: Source for TE signalling. @@ -491,8 +485,6 @@ struct dsi_split_link_config { struct dsi_host_common_cfg { enum dsi_pixel_format dst_format; enum dsi_data_lanes data_lanes; - u8 num_data_lanes; - u8 bpp; bool en_crc_check; bool en_ecc_check; enum dsi_te_mode te_mode; @@ -597,9 +589,7 @@ struct dsi_host_config { * @panel_prefill_lines: Panel prefill lines for RSC * @mdp_transfer_time_us: Specifies the mdp transfer time for command mode * panels in microseconds. - * @dsi_transfer_time_us: Specifies the dsi transfer time for cmd panels. * @clk_rate_hz: DSI bit clock per lane in hz. - * @min_dsi_clk_hz: Min dsi clk per lane to transfer frame in vsync time. * @overlap_pixels: overlap pixels for certain panels. * @topology: Topology selected for the panel * @dsc: DSC compression info @@ -616,9 +606,7 @@ struct dsi_display_mode_priv_info { u32 panel_jitter_denom; u32 panel_prefill_lines; u32 mdp_transfer_time_us; - u32 dsi_transfer_time_us; u64 clk_rate_hz; - u64 min_dsi_clk_hz; u32 overlap_pixels; struct msm_display_topology topology; diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c index 6d14cdf29cc7..cf9e50a1f80d 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c @@ -4570,7 +4570,7 @@ static int dsi_display_set_mode_sub(struct dsi_display *display, display_for_each_ctrl(i, display) { ctrl = &display->ctrl[i]; rc = dsi_ctrl_update_host_config(ctrl->ctrl, - &display->config, mode, mode->dsi_mode_flags, + &display->config, mode->dsi_mode_flags, display->dsi_clk_handle); if (rc) { pr_err("failed to update ctrl config\n"); @@ -4618,8 +4618,7 @@ static int dsi_display_set_mode_sub(struct dsi_display *display, display_for_each_ctrl(i, display) { ctrl = &display->ctrl[i]; rc = dsi_ctrl_update_host_config(ctrl->ctrl, &display->config, - mode, mode->dsi_mode_flags, - display->dsi_clk_handle); + mode->dsi_mode_flags, display->dsi_clk_handle); if (rc) { pr_err("[%s] failed to update ctrl config, rc=%d\n", display->name, rc); @@ -6329,22 +6328,6 @@ int dsi_display_get_modes(struct dsi_display *display, num_dfps_rates = ((!dfps_caps.dfps_support || is_cmd_mode) ? 1 : dfps_caps.dfps_list_len); - /* Calculate dsi frame transfer time */ - if (is_cmd_mode) { - dsi_panel_calc_dsi_transfer_time( - &display->panel->host_config, - &display_mode.timing); - display_mode.priv_info->dsi_transfer_time_us = - display_mode.timing.dsi_transfer_time_us; - display_mode.priv_info->min_dsi_clk_hz = - display_mode.timing.min_dsi_clk_hz; - - display_mode.priv_info->mdp_transfer_time_us = - display_mode.priv_info->dsi_transfer_time_us; - display_mode.timing.mdp_transfer_time_us = - display_mode.timing.dsi_transfer_time_us; - } - is_split_link = host->split_link.split_link_enabled; sublinks_count = host->split_link.num_sublinks; if (is_split_link && sublinks_count > 1) { @@ -6673,7 +6656,6 @@ int dsi_display_set_mode(struct dsi_display *display, { int rc = 0; struct dsi_display_mode adj_mode; - struct dsi_mode_info timing; if (!display || !mode || !display->panel) { pr_err("Invalid params\n"); @@ -6683,7 +6665,6 @@ int dsi_display_set_mode(struct dsi_display *display, mutex_lock(&display->display_lock); adj_mode = *mode; - timing = adj_mode.timing; adjust_timing_by_ctrl_count(display, &adj_mode); /*For dynamic DSI setting, use specified clock rate */ @@ -6711,11 +6692,6 @@ int dsi_display_set_mode(struct dsi_display *display, } } - pr_info("mdp_transfer_time_us=%d us\n", - adj_mode.priv_info->mdp_transfer_time_us); - pr_info("hactive= %d, vactive= %d, fps=%d", timing.h_active, - timing.v_active, timing.refresh_rate); - memcpy(display->panel->cur_mode, &adj_mode, sizeof(adj_mode)); error: mutex_unlock(&display->display_lock); diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c index bc1d8eb01418..9c97298c74d6 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c @@ -967,8 +967,6 @@ static int dsi_panel_parse_pixel_format(struct dsi_host_common_cfg *host, return rc; } - host->bpp = bpp; - switch (bpp) { case 3: fmt = DSI_PIXEL_FORMAT_RGB111; @@ -1009,7 +1007,6 @@ static int dsi_panel_parse_lane_states(struct dsi_host_common_cfg *host, { int rc = 0; bool lane_enabled; - u32 num_of_lanes = 0; lane_enabled = utils->read_bool(utils->data, "qcom,mdss-dsi-lane-0-state"); @@ -1027,17 +1024,6 @@ static int dsi_panel_parse_lane_states(struct dsi_host_common_cfg *host, "qcom,mdss-dsi-lane-3-state"); host->data_lanes |= (lane_enabled ? DSI_DATA_LANE_3 : 0); - if (host->data_lanes & DSI_DATA_LANE_0) - num_of_lanes++; - if (host->data_lanes & DSI_DATA_LANE_1) - num_of_lanes++; - if (host->data_lanes & DSI_DATA_LANE_2) - num_of_lanes++; - if (host->data_lanes & DSI_DATA_LANE_3) - num_of_lanes++; - - host->num_data_lanes = num_of_lanes; - if (host->data_lanes == 0) { pr_err("[%s] No data lanes are enabled, rc=%d\n", name, rc); rc = -EINVAL; @@ -3630,57 +3616,6 @@ void dsi_panel_put_mode(struct dsi_display_mode *mode) kfree(mode->priv_info); } -void dsi_panel_calc_dsi_transfer_time(struct dsi_host_common_cfg *config, - struct dsi_mode_info *timing) -{ - u32 frame_time_us, nslices; - u64 min_bitclk, total_active_pixels, bits_per_line, - dsi_transfer_time_us; - struct msm_display_dsc_info *dsc = timing->dsc; - - /* Packet overlead in bits,2 bytes header + 2 bytes checksum - * + 1 byte dcs data command. - */ - const u32 packet_overhead = 56; - - /* Default time between pingpong done to TE in microsecs */ - const u32 max_tx_threshold_time = 2166; - - frame_time_us = mult_frac(1000, 1000, (timing->refresh_rate)); - - if (timing->dsc_enabled) { - nslices = (timing->h_active)/(dsc->slice_width); - /* (slice width x bit-per-pixel + packet overhead) x - * number of slices x height x fps / lane - */ - bits_per_line = ((dsc->slice_width * dsc->bpp) + - packet_overhead) * nslices; - bits_per_line = bits_per_line / (config->num_data_lanes); - - min_bitclk = (bits_per_line * timing->v_active * - timing->refresh_rate); - } else { - total_active_pixels = ((DSI_H_ACTIVE_DSC(timing) - * timing->v_active)); - /* calculate the actual bitclk needed to transfer the frame */ - min_bitclk = (total_active_pixels * (timing->refresh_rate) * - (config->bpp)); - do_div(min_bitclk, config->num_data_lanes); - } - - timing->min_dsi_clk_hz = min_bitclk; - - if (timing->clk_rate_hz) { - /* adjust the transfer time proportionately for bit clk*/ - dsi_transfer_time_us = frame_time_us * min_bitclk; - do_div(dsi_transfer_time_us, timing->clk_rate_hz); - timing->dsi_transfer_time_us = dsi_transfer_time_us; - } else { - timing->dsi_transfer_time_us = frame_time_us - - max_tx_threshold_time; - } -} - int dsi_panel_get_mode(struct dsi_panel *panel, u32 index, struct dsi_display_mode *mode, int topology_override) diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h index 59d99b0510cc..4dcaf16020e5 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h @@ -337,7 +337,4 @@ int dsi_panel_parse_esd_reg_read_configs(struct dsi_panel *panel); void dsi_panel_ext_bridge_put(struct dsi_panel *panel); -void dsi_panel_calc_dsi_transfer_time(struct dsi_host_common_cfg *config, - struct dsi_mode_info *timing); - #endif /* _DSI_PANEL_H_ */ From 7dc10af9226fda2d8cd730ad762d5fec0509594d Mon Sep 17 00:00:00 2001 From: Ray Zhang Date: Wed, 29 Jul 2020 19:01:45 +0800 Subject: [PATCH 294/592] Revert "disp: msm: sde: avoid multiple frame-done encoder events" This reverts commit 12f7276790ead798971ac9a3b1a8c989a70a397d. Change-Id: I511bf3d6e3597fb757ce1faf09dca5d13ce17704 Signed-off-by: Ray Zhang --- drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c index ef0f55041a9f..2e31261902b8 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c @@ -183,7 +183,10 @@ static void _sde_encoder_phys_cmd_update_intf_cfg( static void sde_encoder_phys_cmd_pp_tx_done_irq(void *arg, int irq_idx) { struct sde_encoder_phys *phys_enc = arg; - u32 event = 0; + unsigned long lock_flags; + int new_cnt; + u32 event = SDE_ENCODER_FRAME_EVENT_DONE | + SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE; if (!phys_enc || !phys_enc->hw_pp) return; @@ -192,17 +195,16 @@ static void sde_encoder_phys_cmd_pp_tx_done_irq(void *arg, int irq_idx) /* notify all synchronous clients first, then asynchronous clients */ if (phys_enc->parent_ops.handle_frame_done && - atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0)) { - event = SDE_ENCODER_FRAME_EVENT_DONE | - SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE; - spin_lock(phys_enc->enc_spinlock); + atomic_read(&phys_enc->pending_kickoff_cnt)) phys_enc->parent_ops.handle_frame_done(phys_enc->parent, phys_enc, event); - spin_unlock(phys_enc->enc_spinlock); - } + + spin_lock_irqsave(phys_enc->enc_spinlock, lock_flags); + new_cnt = atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0); + spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags); SDE_EVT32_IRQ(DRMID(phys_enc->parent), - phys_enc->hw_pp->idx - PINGPONG_0, event); + phys_enc->hw_pp->idx - PINGPONG_0, new_cnt, event); /* Signal any waiting atomic commit thread */ wake_up_all(&phys_enc->pending_kickoff_wq); From 49954e04af6807f941faa1da46b673ca08ac335a Mon Sep 17 00:00:00 2001 From: Ray Zhang Date: Wed, 29 Jul 2020 19:01:51 +0800 Subject: [PATCH 295/592] Revert "disp: msm: sde: signal retire fence in wr_ptr timeout" This reverts commit 5eb64992b711c5edb2fdd6bee31f38e9dc3ae2b4. Change-Id: Ica7f1bf42d564d62a0f26042ab745969b16af000 Signed-off-by: Ray Zhang --- .../gpu/drm/msm/sde/sde_encoder_phys_cmd.c | 34 ++++++------------- 1 file changed, 11 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c index 2e31261902b8..15123d6ee7b1 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c @@ -1392,7 +1392,6 @@ static int _sde_encoder_phys_cmd_wait_for_wr_ptr( int ret; bool frame_pending = true; struct sde_hw_ctl *ctl; - unsigned long lock_flags; if (!phys_enc || !phys_enc->hw_ctl) { SDE_ERROR("invalid argument(s)\n"); @@ -1423,29 +1422,18 @@ static int _sde_encoder_phys_cmd_wait_for_wr_ptr( ret = 0; /* - * There can be few cases of ESD where CTL_START is cleared but - * wr_ptr irq doesn't come. Signaling retire fence in these - * cases to avoid freeze and dangling pending_retire_fence_cnt + * Signaling the retire fence at wr_ptr timeout + * to allow the next commit and avoid device freeze. + * As wr_ptr timeout can occurs due to no read ptr, + * updating pending_rd_ptr_cnt here may not cover all + * cases. Hence signaling the retire fence. */ - if (!ret) { - u32 signal_retire_event = - SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE; - - SDE_EVT32(DRMID(phys_enc->parent), - SDE_EVTLOG_FUNC_CASE1); - - if (sde_encoder_phys_cmd_is_master(phys_enc) && - atomic_add_unless( - &phys_enc->pending_retire_fence_cnt, -1, 0)) { - spin_lock_irqsave(phys_enc->enc_spinlock, - lock_flags); - phys_enc->parent_ops.handle_frame_done( - phys_enc->parent, phys_enc, - signal_retire_event); - spin_unlock_irqrestore(phys_enc->enc_spinlock, - lock_flags); - } - } + if (sde_encoder_phys_cmd_is_master(phys_enc) && + atomic_add_unless(&phys_enc->pending_retire_fence_cnt, + -1, 0)) + phys_enc->parent_ops.handle_frame_done( + phys_enc->parent, phys_enc, + SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE); } cmd_enc->wr_ptr_wait_success = (ret == 0) ? true : false; From 35e852bdedde1a0487e0dbb4c86051ae63b89a2c Mon Sep 17 00:00:00 2001 From: Ray Zhang Date: Wed, 29 Jul 2020 19:01:54 +0800 Subject: [PATCH 296/592] Revert "disp: msm: sde: handle another case for lost pp-done interrupt" This reverts commit b57ddc535025c74b45b35c5ce32e4dfdb37d2a6a. Change-Id: I91695150ef90576daa77a9206792d8d6c085e0ab Signed-off-by: Ray Zhang --- .../gpu/drm/msm/sde/sde_encoder_phys_cmd.c | 22 +++++-------------- drivers/gpu/drm/msm/sde/sde_hw_ctl.h | 2 -- 2 files changed, 5 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c index 15123d6ee7b1..fd7897d587b8 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c @@ -1341,11 +1341,10 @@ static int sde_encoder_phys_cmd_prepare_for_kickoff( } SDE_DEBUG_CMDENC(cmd_enc, "pp %d\n", phys_enc->hw_pp->idx - PINGPONG_0); - phys_enc->frame_trigger_mode = params->frame_trigger_mode; SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0, atomic_read(&phys_enc->pending_kickoff_cnt), - atomic_read(&cmd_enc->autorefresh.kickoff_cnt), - phys_enc->frame_trigger_mode); + atomic_read(&cmd_enc->autorefresh.kickoff_cnt)); + phys_enc->frame_trigger_mode = params->frame_trigger_mode; if (phys_enc->frame_trigger_mode == FRAME_DONE_WAIT_DEFAULT) { /* @@ -1467,8 +1466,6 @@ static int sde_encoder_phys_cmd_wait_for_commit_done( { int rc = 0, i, pending_cnt; struct sde_encoder_phys_cmd *cmd_enc; - u32 scheduler_status = INVALID_CTL_STATUS; - struct sde_hw_ctl *ctl; if (!phys_enc) return -EINVAL; @@ -1484,22 +1481,14 @@ static int sde_encoder_phys_cmd_wait_for_commit_done( if (cmd_enc->autorefresh.cfg.enable) rc = _sde_encoder_phys_cmd_wait_for_autorefresh_done( phys_enc); - - ctl = phys_enc->hw_ctl; - if (ctl && ctl->ops.get_scheduler_status) - scheduler_status = ctl->ops.get_scheduler_status(ctl); } /* wait for posted start or serialize trigger */ - pending_cnt = atomic_read(&phys_enc->pending_kickoff_cnt); - if ((pending_cnt > 1) || - (pending_cnt && (scheduler_status & BIT(0))) || + if ((atomic_read(&phys_enc->pending_kickoff_cnt) > 1) || (!rc && phys_enc->frame_trigger_mode == - FRAME_DONE_WAIT_SERIALIZE)) + FRAME_DONE_WAIT_SERIALIZE)) goto wait_for_idle; - return rc; - wait_for_idle: pending_cnt = atomic_read(&phys_enc->pending_kickoff_cnt); for (i = 0; i < pending_cnt; i++) @@ -1510,8 +1499,7 @@ wait_for_idle: phys_enc->hw_pp->idx - PINGPONG_0, phys_enc->frame_trigger_mode, atomic_read(&phys_enc->pending_kickoff_cnt), - phys_enc->enable_state, - cmd_enc->wr_ptr_wait_success, scheduler_status, rc); + phys_enc->enable_state, rc); SDE_ERROR("pp:%d failed wait_for_idle: %d\n", phys_enc->hw_pp->idx - PINGPONG_0, rc); if (phys_enc->enable_state == SDE_ENC_ERR_NEEDS_HW_RESET) diff --git a/drivers/gpu/drm/msm/sde/sde_hw_ctl.h b/drivers/gpu/drm/msm/sde/sde_hw_ctl.h index dc1a65c7b058..1cef1f2ef58f 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_ctl.h +++ b/drivers/gpu/drm/msm/sde/sde_hw_ctl.h @@ -19,8 +19,6 @@ #include "sde_hw_sspp.h" #include "sde_hw_blk.h" -#define INVALID_CTL_STATUS 0xfffff88e - /** * sde_ctl_mode_sel: Interface mode selection * SDE_CTL_MODE_SEL_VID: Video mode interface From e0d082202f1c505178c28efb2c1a08332531fecc Mon Sep 17 00:00:00 2001 From: Ray Zhang Date: Wed, 29 Jul 2020 19:01:56 +0800 Subject: [PATCH 297/592] Revert "disp: msm: sde: avoid encoder power-collapse with pending frames" This reverts commit 6c6d649c3ea0d59250ab22b3dec383f7f57ad976. Change-Id: I81dd0254079f97b5bab8f20bc0b7b78cf9c3e571 Signed-off-by: Ray Zhang --- drivers/gpu/drm/msm/sde/sde_encoder.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c index 1cfa67a88d31..fee86ae93330 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder.c @@ -2696,7 +2696,7 @@ static int sde_encoder_resource_control(struct drm_encoder *drm_enc, SDE_EVTLOG_ERROR); mutex_unlock(&sde_enc->rc_lock); return 0; - } else if (sde_crtc_frame_pending(sde_enc->crtc)) { + } else if (sde_crtc_frame_pending(sde_enc->crtc) > 1) { SDE_DEBUG_ENC(sde_enc, "skip idle entry"); SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state, sde_crtc_frame_pending(sde_enc->crtc), From 30f0ba586b1bd31effc7342b37c8194845afcdfb Mon Sep 17 00:00:00 2001 From: Ray Zhang Date: Wed, 29 Jul 2020 19:02:03 +0800 Subject: [PATCH 298/592] Revert "disp: msm: sde: fix handling the missing pp-done interrupt cases" This reverts commit ff76cdcca5deb223d71be208e8d2a02315401a15. Change-Id: I9b6458a6af20d383722764f2f4f28ec71e62b661 Signed-off-by: Ray Zhang --- .../gpu/drm/msm/sde/sde_encoder_phys_cmd.c | 56 +++++-------------- 1 file changed, 14 insertions(+), 42 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c index fd7897d587b8..1ac7b23bd233 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c @@ -663,60 +663,38 @@ static bool _sde_encoder_phys_cmd_is_ongoing_pptx( return false; } -static bool _sde_encoder_phys_cmd_is_scheduler_idle( +static int _sde_encoder_phys_cmd_wait_for_idle( struct sde_encoder_phys *phys_enc) { - bool wr_ptr_wait_success = true; - unsigned long lock_flags; - bool ret = false; struct sde_encoder_phys_cmd *cmd_enc = to_sde_encoder_phys_cmd(phys_enc); - struct sde_hw_ctl *ctl = phys_enc->hw_ctl; + struct sde_encoder_wait_info wait_info; + bool recovery_events; + int ret; + struct sde_hw_ctl *ctl; + bool wr_ptr_wait_success = true; + + if (!phys_enc) { + SDE_ERROR("invalid encoder\n"); + return -EINVAL; + } + + ctl = phys_enc->hw_ctl; if (sde_encoder_phys_cmd_is_master(phys_enc)) wr_ptr_wait_success = cmd_enc->wr_ptr_wait_success; - /* - * Handle cases where a pp-done interrupt is missed - * due to irq latency with POSTED start - */ if (wr_ptr_wait_success && (phys_enc->frame_trigger_mode == FRAME_DONE_WAIT_POSTED_START) && ctl->ops.get_scheduler_status && (ctl->ops.get_scheduler_status(ctl) & BIT(0)) && atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0) && phys_enc->parent_ops.handle_frame_done) { - - spin_lock_irqsave(phys_enc->enc_spinlock, lock_flags); phys_enc->parent_ops.handle_frame_done( phys_enc->parent, phys_enc, SDE_ENCODER_FRAME_EVENT_DONE | SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE); - spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags); - - SDE_EVT32(DRMID(phys_enc->parent), - phys_enc->hw_pp->idx - PINGPONG_0, - phys_enc->hw_intf->idx - INTF_0, - atomic_read(&phys_enc->pending_kickoff_cnt)); - - ret = true; - } - - return ret; -} - -static int _sde_encoder_phys_cmd_wait_for_idle( - struct sde_encoder_phys *phys_enc) -{ - struct sde_encoder_phys_cmd *cmd_enc = - to_sde_encoder_phys_cmd(phys_enc); - struct sde_encoder_wait_info wait_info = {NULL}; - bool recovery_events; - int ret; - - if (!phys_enc) { - SDE_ERROR("invalid encoder\n"); - return -EINVAL; + return 0; } if (atomic_read(&phys_enc->pending_kickoff_cnt) > 1) @@ -732,15 +710,9 @@ static int _sde_encoder_phys_cmd_wait_for_idle( if (_sde_encoder_phys_is_ppsplit_slave(phys_enc)) return 0; - if (_sde_encoder_phys_cmd_is_scheduler_idle(phys_enc)) - return 0; - ret = sde_encoder_helper_wait_for_irq(phys_enc, INTR_IDX_PINGPONG, &wait_info); if (ret == -ETIMEDOUT) { - if (_sde_encoder_phys_cmd_is_scheduler_idle(phys_enc)) - return 0; - _sde_encoder_phys_cmd_handle_ppdone_timeout(phys_enc, recovery_events); } else if (!ret) { From 1b84702208768dc631a064c0d43d5b4068dd5a0f Mon Sep 17 00:00:00 2001 From: Ray Zhang Date: Wed, 29 Jul 2020 19:02:08 +0800 Subject: [PATCH 299/592] Revert "disp: msm: sde: wait for specific pp_done instead of zero" This reverts commit 1cb8e403b4552d974e0a902c935de274de63a154. Change-Id: I7934a30d838225e517bfd4b7256e86a2838c1bcc Signed-off-by: Ray Zhang --- drivers/gpu/drm/msm/sde/sde_encoder.c | 9 +++------ drivers/gpu/drm/msm/sde/sde_encoder_phys.h | 2 -- drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c | 16 ++++------------ 3 files changed, 7 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c index fee86ae93330..b869a2d01262 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder.c @@ -444,16 +444,13 @@ static int _sde_encoder_wait_timeout(int32_t drm_id, int32_t hw_id, do { rc = wait_event_timeout(*(info->wq), - atomic_read(info->atomic_cnt) == info->count_check, - wait_time_jiffies); + atomic_read(info->atomic_cnt) == 0, wait_time_jiffies); cur_ktime = ktime_get(); SDE_EVT32(drm_id, hw_id, rc, ktime_to_ms(cur_ktime), - timeout_ms, atomic_read(info->atomic_cnt), - info->count_check); + timeout_ms, atomic_read(info->atomic_cnt)); /* If we timed out, counter is valid and time is less, wait again */ - } while ((atomic_read(info->atomic_cnt) != info->count_check) && - (rc == 0) && + } while (atomic_read(info->atomic_cnt) && (rc == 0) && (ktime_compare_safe(exp_ktime, cur_ktime) > 0)); return rc; diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h index accab600df16..8ffb00f43320 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h @@ -472,13 +472,11 @@ struct sde_enc_phys_init_params { * sde_encoder_wait_info - container for passing arguments to irq wait functions * @wq: wait queue structure * @atomic_cnt: wait until atomic_cnt equals zero - * @count_check: wait for specific atomic_cnt instead of zero. * @timeout_ms: timeout value in milliseconds */ struct sde_encoder_wait_info { wait_queue_head_t *wq; atomic_t *atomic_cnt; - u32 count_check; s64 timeout_ms; }; diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c index 1ac7b23bd233..6d127bd06264 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c @@ -672,7 +672,6 @@ static int _sde_encoder_phys_cmd_wait_for_idle( bool recovery_events; int ret; struct sde_hw_ctl *ctl; - bool wr_ptr_wait_success = true; if (!phys_enc) { SDE_ERROR("invalid encoder\n"); @@ -680,11 +679,7 @@ static int _sde_encoder_phys_cmd_wait_for_idle( } ctl = phys_enc->hw_ctl; - - if (sde_encoder_phys_cmd_is_master(phys_enc)) - wr_ptr_wait_success = cmd_enc->wr_ptr_wait_success; - - if (wr_ptr_wait_success && + if (cmd_enc->wr_ptr_wait_success && (phys_enc->frame_trigger_mode == FRAME_DONE_WAIT_POSTED_START) && ctl->ops.get_scheduler_status && (ctl->ops.get_scheduler_status(ctl) & BIT(0)) && @@ -697,9 +692,6 @@ static int _sde_encoder_phys_cmd_wait_for_idle( return 0; } - if (atomic_read(&phys_enc->pending_kickoff_cnt) > 1) - wait_info.count_check = 1; - wait_info.wq = &phys_enc->pending_kickoff_wq; wait_info.atomic_cnt = &phys_enc->pending_kickoff_cnt; wait_info.timeout_ms = KICKOFF_TIMEOUT_MS; @@ -735,7 +727,7 @@ static int _sde_encoder_phys_cmd_wait_for_autorefresh_done( { struct sde_encoder_phys_cmd *cmd_enc = to_sde_encoder_phys_cmd(phys_enc); - struct sde_encoder_wait_info wait_info = {NULL}; + struct sde_encoder_wait_info wait_info; int ret = 0; if (!phys_enc) { @@ -1359,7 +1351,7 @@ static int _sde_encoder_phys_cmd_wait_for_wr_ptr( { struct sde_encoder_phys_cmd *cmd_enc = to_sde_encoder_phys_cmd(phys_enc); - struct sde_encoder_wait_info wait_info = {NULL}; + struct sde_encoder_wait_info wait_info; int ret; bool frame_pending = true; struct sde_hw_ctl *ctl; @@ -1486,7 +1478,7 @@ static int sde_encoder_phys_cmd_wait_for_vblank( { int rc = 0; struct sde_encoder_phys_cmd *cmd_enc; - struct sde_encoder_wait_info wait_info = {NULL}; + struct sde_encoder_wait_info wait_info; if (!phys_enc) return -EINVAL; From 2871352949c1a221034d2333efac51d5bf83337d Mon Sep 17 00:00:00 2001 From: Ray Zhang Date: Wed, 29 Jul 2020 19:03:18 +0800 Subject: [PATCH 300/592] Revert "disp: msm: sde: fix release fence signaling in error cases" This reverts commit fb0adea1cd59f8dfec5c50cd21181d2752cb2e4b. Change-Id: I665bd6137124969ea316ad5f68e32951750111df Signed-off-by: Ray Zhang --- drivers/gpu/drm/msm/sde/sde_encoder.c | 4 +- drivers/gpu/drm/msm/sde/sde_encoder_phys.h | 3 +- .../gpu/drm/msm/sde/sde_encoder_phys_cmd.c | 59 +++++++++---------- 3 files changed, 31 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c index b869a2d01262..fe05a401a2fa 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder.c @@ -3455,7 +3455,6 @@ static void sde_encoder_virt_disable(struct drm_encoder *drm_enc) sde_enc->phys_encs[i]->cont_splash_single_flush = 0; sde_enc->phys_encs[i]->connector = NULL; } - atomic_set(&sde_enc->frame_done_cnt[i], 0); } sde_enc->cur_master = NULL; @@ -3681,7 +3680,8 @@ static void sde_encoder_frame_done_callback( /* One of the physical encoders has become idle */ for (i = 0; i < sde_enc->num_phys_encs; i++) { - if (sde_enc->phys_encs[i] == ready_phys) { + if ((sde_enc->phys_encs[i] == ready_phys) || + (event & SDE_ENCODER_FRAME_EVENT_ERROR)) { SDE_EVT32_VERBOSE(DRMID(drm_enc), i, atomic_read( &sde_enc->frame_done_cnt[i])); diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h index 8ffb00f43320..53d6cf5fcf3d 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h @@ -379,12 +379,12 @@ struct sde_encoder_phys_cmd_autorefresh { * struct sde_encoder_phys_cmd - sub-class of sde_encoder_phys to handle command * mode specific operations * @base: Baseclass physical encoder structure + * @intf_idx: Intf Block index used by this phys encoder * @stream_sel: Stream selection for multi-stream interfaces * @pp_timeout_report_cnt: number of pingpong done irq timeout errors * @autorefresh: autorefresh feature state * @pending_vblank_cnt: Atomic counter tracking pending wait for VBLANK * @pending_vblank_wq: Wait queue for blocking until VBLANK received - * @wr_ptr_wait_success: log wr_ptr_wait success for release fence trigger */ struct sde_encoder_phys_cmd { struct sde_encoder_phys base; @@ -393,7 +393,6 @@ struct sde_encoder_phys_cmd { struct sde_encoder_phys_cmd_autorefresh autorefresh; atomic_t pending_vblank_cnt; wait_queue_head_t pending_vblank_wq; - bool wr_ptr_wait_success; }; /** diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c index 6d127bd06264..197b34a297c8 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c @@ -481,18 +481,20 @@ static int _sde_encoder_phys_cmd_handle_ppdone_timeout( conn = phys_enc->connector; sde_conn = to_sde_connector(conn); - /* decrement the kickoff_cnt before checking for ESD status */ - if (!atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0)) + if (atomic_read(&phys_enc->pending_kickoff_cnt) == 0) return 0; cmd_enc->pp_timeout_report_cnt++; - pending_kickoff_cnt = atomic_read(&phys_enc->pending_kickoff_cnt) + 1; + pending_kickoff_cnt = atomic_read(&phys_enc->pending_kickoff_cnt); SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0, cmd_enc->pp_timeout_report_cnt, pending_kickoff_cnt, frame_event); + /* decrement the kickoff_cnt before checking for ESD status */ + atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0); + /* check if panel is still sending TE signal or not */ if (sde_connector_esd_status(phys_enc->connector) || sde_conn->panel_dead) @@ -670,28 +672,13 @@ static int _sde_encoder_phys_cmd_wait_for_idle( to_sde_encoder_phys_cmd(phys_enc); struct sde_encoder_wait_info wait_info; bool recovery_events; - int ret; - struct sde_hw_ctl *ctl; + int ret, i, pending_cnt; if (!phys_enc) { SDE_ERROR("invalid encoder\n"); return -EINVAL; } - ctl = phys_enc->hw_ctl; - if (cmd_enc->wr_ptr_wait_success && - (phys_enc->frame_trigger_mode == FRAME_DONE_WAIT_POSTED_START) && - ctl->ops.get_scheduler_status && - (ctl->ops.get_scheduler_status(ctl) & BIT(0)) && - atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0) && - phys_enc->parent_ops.handle_frame_done) { - phys_enc->parent_ops.handle_frame_done( - phys_enc->parent, phys_enc, - SDE_ENCODER_FRAME_EVENT_DONE | - SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE); - return 0; - } - wait_info.wq = &phys_enc->pending_kickoff_wq; wait_info.atomic_cnt = &phys_enc->pending_kickoff_cnt; wait_info.timeout_ms = KICKOFF_TIMEOUT_MS; @@ -705,7 +692,9 @@ static int _sde_encoder_phys_cmd_wait_for_idle( ret = sde_encoder_helper_wait_for_irq(phys_enc, INTR_IDX_PINGPONG, &wait_info); if (ret == -ETIMEDOUT) { - _sde_encoder_phys_cmd_handle_ppdone_timeout(phys_enc, + pending_cnt = atomic_read(&phys_enc->pending_kickoff_cnt); + for (i = 0; i < pending_cnt; i++) + _sde_encoder_phys_cmd_handle_ppdone_timeout(phys_enc, recovery_events); } else if (!ret) { if (cmd_enc->pp_timeout_report_cnt && recovery_events) { @@ -1397,9 +1386,19 @@ static int _sde_encoder_phys_cmd_wait_for_wr_ptr( phys_enc->parent_ops.handle_frame_done( phys_enc->parent, phys_enc, SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE); - } + } else if ((ret == 0) && + (phys_enc->frame_trigger_mode == FRAME_DONE_WAIT_POSTED_START) && + atomic_read(&phys_enc->pending_kickoff_cnt) && + ctl->ops.get_scheduler_status && + (ctl->ops.get_scheduler_status(ctl) & BIT(0)) && + phys_enc->parent_ops.handle_frame_done) { + atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0); - cmd_enc->wr_ptr_wait_success = (ret == 0) ? true : false; + phys_enc->parent_ops.handle_frame_done( + phys_enc->parent, phys_enc, + SDE_ENCODER_FRAME_EVENT_DONE | + SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE); + } return ret; } @@ -1428,7 +1427,7 @@ static int sde_encoder_phys_cmd_wait_for_tx_complete( static int sde_encoder_phys_cmd_wait_for_commit_done( struct sde_encoder_phys *phys_enc) { - int rc = 0, i, pending_cnt; + int rc = 0; struct sde_encoder_phys_cmd *cmd_enc; if (!phys_enc) @@ -1441,12 +1440,12 @@ static int sde_encoder_phys_cmd_wait_for_commit_done( rc = _sde_encoder_phys_cmd_wait_for_wr_ptr(phys_enc); if (rc == -ETIMEDOUT) goto wait_for_idle; - - if (cmd_enc->autorefresh.cfg.enable) - rc = _sde_encoder_phys_cmd_wait_for_autorefresh_done( - phys_enc); } + if (!rc && sde_encoder_phys_cmd_is_master(phys_enc) && + cmd_enc->autorefresh.cfg.enable) + rc = _sde_encoder_phys_cmd_wait_for_autorefresh_done(phys_enc); + /* wait for posted start or serialize trigger */ if ((atomic_read(&phys_enc->pending_kickoff_cnt) > 1) || (!rc && phys_enc->frame_trigger_mode == @@ -1454,16 +1453,14 @@ static int sde_encoder_phys_cmd_wait_for_commit_done( goto wait_for_idle; wait_for_idle: - pending_cnt = atomic_read(&phys_enc->pending_kickoff_cnt); - for (i = 0; i < pending_cnt; i++) - rc |= sde_encoder_wait_for_event(phys_enc->parent, - MSM_ENC_TX_COMPLETE); + rc = _sde_encoder_phys_cmd_wait_for_idle(phys_enc); if (rc) { SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0, phys_enc->frame_trigger_mode, atomic_read(&phys_enc->pending_kickoff_cnt), phys_enc->enable_state, rc); + atomic_set(&phys_enc->pending_kickoff_cnt, 0); SDE_ERROR("pp:%d failed wait_for_idle: %d\n", phys_enc->hw_pp->idx - PINGPONG_0, rc); if (phys_enc->enable_state == SDE_ENC_ERR_NEEDS_HW_RESET) From 22bfc32c97357661f4cf738accd0d62f21edb723 Mon Sep 17 00:00:00 2001 From: Ray Zhang Date: Wed, 29 Jul 2020 19:03:21 +0800 Subject: [PATCH 301/592] Revert "disp: msm: sde: reset ctl during wr_ptr_irq timeout" This reverts commit 3b888b448f09fef4aa8d275019c9a58796182432. Change-Id: I80df2a1aa9f1e20244c9bcbd1286864f19469ca3 Signed-off-by: Ray Zhang --- drivers/gpu/drm/msm/sde/sde_encoder.c | 23 ++++++++++++--- drivers/gpu/drm/msm/sde/sde_encoder_phys.h | 6 ---- .../gpu/drm/msm/sde/sde_encoder_phys_cmd.c | 29 ++++++------------- 3 files changed, 28 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c index fe05a401a2fa..13aadfd4975a 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder.c @@ -4626,11 +4626,21 @@ static void _helper_flush_dsc(struct sde_encoder_virt *sde_enc) } } -void sde_encoder_helper_needs_hw_reset(struct drm_encoder *drm_enc) +static void _sde_encoder_needs_hw_reset(struct drm_encoder *drm_enc, + int ln_cnt1) { struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc); struct sde_encoder_phys *phys; - int i; + int ln_cnt2, i; + + /* query line count before cur_master is updated */ + if (sde_enc->cur_master && sde_enc->cur_master->ops.get_wr_line_count) + ln_cnt2 = sde_enc->cur_master->ops.get_wr_line_count( + sde_enc->cur_master); + else + ln_cnt2 = -EINVAL; + + SDE_EVT32(DRMID(drm_enc), ln_cnt1, ln_cnt2); for (i = 0; i < sde_enc->num_phys_encs; i++) { phys = sde_enc->phys_encs[i]; @@ -4648,7 +4658,7 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, struct sde_crtc *sde_crtc; struct msm_drm_private *priv = NULL; bool needs_hw_reset = false; - int i, rc, ret = 0; + int ln_cnt1 = -EINVAL, i, rc, ret = 0; struct msm_display_info *disp_info; if (!drm_enc || !params || !drm_enc->dev || @@ -4665,6 +4675,11 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, SDE_DEBUG_ENC(sde_enc, "\n"); SDE_EVT32(DRMID(drm_enc)); + /* save this for later, in case of errors */ + if (sde_enc->cur_master && sde_enc->cur_master->ops.get_wr_line_count) + ln_cnt1 = sde_enc->cur_master->ops.get_wr_line_count( + sde_enc->cur_master); + if (sde_enc->cur_master && sde_enc->cur_master->connector && disp_info->capabilities & MSM_DISPLAY_CAP_CMD_MODE) sde_enc->frame_trigger_mode = sde_connector_get_property( @@ -4707,7 +4722,7 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, /* if any phys needs reset, reset all phys, in-order */ if (needs_hw_reset) - sde_encoder_helper_needs_hw_reset(drm_enc); + _sde_encoder_needs_hw_reset(drm_enc, ln_cnt1); _sde_encoder_update_master(drm_enc, params); diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h index 53d6cf5fcf3d..e5f7ea0192d9 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h @@ -516,12 +516,6 @@ void sde_encoder_phys_setup_cdm(struct sde_encoder_phys *phys_enc, struct drm_framebuffer *fb, const struct sde_format *format, struct sde_rect *wb_roi); -/** - * sde_encoder_helper_needs_hw_reset - hw reset helper function - * @drm_enc: Pointer to drm encoder structure - */ -void sde_encoder_helper_needs_hw_reset(struct drm_encoder *drm_enc); - /** * sde_encoder_helper_trigger_flush - control flush helper function * This helper function may be optionally specified by physical diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c index 197b34a297c8..ffa1d04597e3 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c @@ -1436,11 +1436,8 @@ static int sde_encoder_phys_cmd_wait_for_commit_done( cmd_enc = to_sde_encoder_phys_cmd(phys_enc); /* only required for master controller */ - if (sde_encoder_phys_cmd_is_master(phys_enc)) { + if (sde_encoder_phys_cmd_is_master(phys_enc)) rc = _sde_encoder_phys_cmd_wait_for_wr_ptr(phys_enc); - if (rc == -ETIMEDOUT) - goto wait_for_idle; - } if (!rc && sde_encoder_phys_cmd_is_master(phys_enc) && cmd_enc->autorefresh.cfg.enable) @@ -1449,22 +1446,14 @@ static int sde_encoder_phys_cmd_wait_for_commit_done( /* wait for posted start or serialize trigger */ if ((atomic_read(&phys_enc->pending_kickoff_cnt) > 1) || (!rc && phys_enc->frame_trigger_mode == - FRAME_DONE_WAIT_SERIALIZE)) - goto wait_for_idle; - -wait_for_idle: - rc = _sde_encoder_phys_cmd_wait_for_idle(phys_enc); - if (rc) { - SDE_EVT32(DRMID(phys_enc->parent), - phys_enc->hw_pp->idx - PINGPONG_0, - phys_enc->frame_trigger_mode, - atomic_read(&phys_enc->pending_kickoff_cnt), - phys_enc->enable_state, rc); - atomic_set(&phys_enc->pending_kickoff_cnt, 0); - SDE_ERROR("pp:%d failed wait_for_idle: %d\n", - phys_enc->hw_pp->idx - PINGPONG_0, rc); - if (phys_enc->enable_state == SDE_ENC_ERR_NEEDS_HW_RESET) - sde_encoder_helper_needs_hw_reset(phys_enc->parent); + FRAME_DONE_WAIT_SERIALIZE)) { + rc = _sde_encoder_phys_cmd_wait_for_idle(phys_enc); + if (rc) { + atomic_set(&phys_enc->pending_kickoff_cnt, 0); + SDE_EVT32(DRMID(phys_enc->parent), + phys_enc->hw_pp->idx - PINGPONG_0); + SDE_ERROR("failed wait_for_idle: %d\n", rc); + } } return rc; From bfaa231d00ed999f0d2a943cea12af0db8c7b4c8 Mon Sep 17 00:00:00 2001 From: Ray Zhang Date: Wed, 29 Jul 2020 19:03:24 +0800 Subject: [PATCH 302/592] Revert "disp: msm: sde: use wr_ptr interrupt instead of ctl_start" This reverts commit 6e3e245002886311be48bb1b8a17ba4100ab8a48. Change-Id: I2a239708eb72d03daf51c0efd7fcf0ca096ae6c5 Signed-off-by: Ray Zhang --- drivers/gpu/drm/msm/sde/sde_crtc.c | 28 ++- drivers/gpu/drm/msm/sde/sde_encoder.c | 17 ++ drivers/gpu/drm/msm/sde/sde_encoder.h | 11 +- drivers/gpu/drm/msm/sde/sde_encoder_phys.h | 22 +- .../gpu/drm/msm/sde/sde_encoder_phys_cmd.c | 196 +++++++++++++----- drivers/gpu/drm/msm/sde/sde_hw_intf.c | 1 - drivers/gpu/drm/msm/sde/sde_hw_mdss.h | 2 - drivers/gpu/drm/msm/sde/sde_hw_pingpong.c | 1 - 8 files changed, 210 insertions(+), 68 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c index f5a537007d09..035eed949d2e 100644 --- a/drivers/gpu/drm/msm/sde/sde_crtc.c +++ b/drivers/gpu/drm/msm/sde/sde_crtc.c @@ -944,6 +944,26 @@ static bool sde_crtc_mode_fixup(struct drm_crtc *crtc, return true; } +static int _sde_crtc_get_ctlstart_timeout(struct drm_crtc *crtc) +{ + struct drm_encoder *encoder; + int rc = 0; + + if (!crtc || !crtc->dev) + return 0; + + list_for_each_entry(encoder, + &crtc->dev->mode_config.encoder_list, head) { + if (encoder->crtc != crtc) + continue; + + if (sde_encoder_get_intf_mode(encoder) == INTF_MODE_CMD) + rc += sde_encoder_get_ctlstart_timeout_state(encoder); + } + + return rc; +} + static void _sde_crtc_setup_blend_cfg(struct sde_crtc_mixer *mixer, struct sde_plane_state *pstate, struct sde_format *format) { @@ -3742,7 +3762,13 @@ static void sde_crtc_atomic_begin(struct drm_crtc *crtc, if (unlikely(!sde_crtc->num_mixers)) goto end; - _sde_crtc_blend_setup(crtc, old_state, true); + if (_sde_crtc_get_ctlstart_timeout(crtc)) { + _sde_crtc_blend_setup(crtc, old_state, false); + SDE_ERROR("border fill only commit after ctlstart timeout\n"); + } else { + _sde_crtc_blend_setup(crtc, old_state, true); + } + _sde_crtc_dest_scaler_setup(crtc); /* cancel the idle notify delayed work */ diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c index 13aadfd4975a..7b04b6d019d7 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder.c @@ -3757,6 +3757,23 @@ int sde_encoder_idle_request(struct drm_encoder *drm_enc) return 0; } +int sde_encoder_get_ctlstart_timeout_state(struct drm_encoder *drm_enc) +{ + struct sde_encoder_virt *sde_enc = NULL; + int i, count = 0; + + if (!drm_enc) + return 0; + + sde_enc = to_sde_encoder_virt(drm_enc); + + for (i = 0; i < sde_enc->num_phys_encs; i++) { + count += atomic_read(&sde_enc->phys_encs[i]->ctlstart_timeout); + atomic_set(&sde_enc->phys_encs[i]->ctlstart_timeout, 0); + } + + return count; +} /** * _sde_encoder_trigger_flush - trigger flush for a physical encoder * drm_enc: Pointer to drm encoder structure diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.h b/drivers/gpu/drm/msm/sde/sde_encoder.h index 2f626dfadeb4..69b3ad28bb01 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder.h +++ b/drivers/gpu/drm/msm/sde/sde_encoder.h @@ -171,11 +171,11 @@ void sde_encoder_kickoff(struct drm_encoder *encoder, bool is_error); * @encoder: encoder pointer * @event: event to wait for * MSM_ENC_COMMIT_DONE - Wait for hardware to have flushed the current pending - * frames to hardware at a vblank or wr_ptr_start + * frames to hardware at a vblank or ctl_start * Encoders will map this differently depending on the * panel type. * vid mode -> vsync_irq - * cmd mode -> wr_ptr_start_irq + * cmd mode -> ctl_start * MSM_ENC_TX_COMPLETE - Wait for the hardware to transfer all the pixels to * the panel. Encoders will map this differently * depending on the panel type. @@ -345,4 +345,11 @@ void sde_encoder_control_idle_pc(struct drm_encoder *enc, bool enable); */ int sde_encoder_in_cont_splash(struct drm_encoder *enc); +/** + * sde_encoder_get_ctlstart_timeout_state - checks if ctl start timeout happened + * @drm_enc: Pointer to drm encoder structure + * @Return: non zero value if ctl start timeout occurred + */ +int sde_encoder_get_ctlstart_timeout_state(struct drm_encoder *enc); + #endif /* __SDE_ENCODER_H__ */ diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h index e5f7ea0192d9..841ffb9f7407 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h @@ -197,9 +197,9 @@ struct sde_encoder_phys_ops { /** * enum sde_intr_idx - sde encoder interrupt index * @INTR_IDX_VSYNC: Vsync interrupt for video mode panel - * @INTR_IDX_PINGPONG: Pingpong done interrupt for cmd mode panel - * @INTR_IDX_UNDERRUN: Underrun interrupt for video and cmd mode panel - * @INTR_IDX_RDPTR: Readpointer done interrupt for cmd mode panel + * @INTR_IDX_PINGPONG: Pingpong done unterrupt for cmd mode panel + * @INTR_IDX_UNDERRUN: Underrun unterrupt for video and cmd mode panel + * @INTR_IDX_RDPTR: Readpointer done unterrupt for cmd mode panel * @INTR_IDX_WB_DONE: Writeback done interrupt for WB * @INTR_IDX_PP1_OVFL: Pingpong overflow interrupt on PP1 for Concurrent WB * @INTR_IDX_PP2_OVFL: Pingpong overflow interrupt on PP2 for Concurrent WB @@ -208,7 +208,6 @@ struct sde_encoder_phys_ops { * @INTR_IDX_PP5_OVFL: Pingpong overflow interrupt on PP5 for Concurrent WB * @INTR_IDX_AUTOREFRESH_DONE: Autorefresh done for cmd mode panel meaning * autorefresh has triggered a double buffer flip - * @INTR_IDX_WRPTR: Writepointer start interrupt for cmd mode panel */ enum sde_intr_idx { INTR_IDX_VSYNC, @@ -223,7 +222,6 @@ enum sde_intr_idx { INTR_IDX_PP3_OVFL, INTR_IDX_PP4_OVFL, INTR_IDX_PP5_OVFL, - INTR_IDX_WRPTR, INTR_IDX_MAX, }; @@ -285,9 +283,12 @@ struct sde_encoder_irq { * vs. the number of done/vblank irqs. Should hover * between 0-2 Incremented when a new kickoff is * scheduled. Decremented in irq handler + * @pending_ctlstart_cnt: Atomic counter tracking the number of ctl start + * pending. * @pending_retire_fence_cnt: Atomic counter tracking the pending retire * fences that have to be signalled. * @pending_kickoff_wq: Wait queue for blocking until kickoff completes + * @ctlstart_timeout: Indicates if ctl start timeout occurred * @irq: IRQ tracking structures * @has_intf_te: Interface TE configuration support * @cont_splash_single_flush Variable to check if single flush is enabled. @@ -329,8 +330,10 @@ struct sde_encoder_phys { atomic_t wbirq_refcount; atomic_t vsync_cnt; atomic_t underrun_cnt; + atomic_t pending_ctlstart_cnt; atomic_t pending_kickoff_cnt; atomic_t pending_retire_fence_cnt; + atomic_t ctlstart_timeout; wait_queue_head_t pending_kickoff_wq; struct sde_encoder_irq irq[INTR_IDX_MAX]; bool has_intf_te; @@ -343,6 +346,7 @@ struct sde_encoder_phys { static inline int sde_encoder_phys_inc_pending(struct sde_encoder_phys *phys) { + atomic_inc_return(&phys->pending_ctlstart_cnt); return atomic_inc_return(&phys->pending_kickoff_cnt); } @@ -383,16 +387,24 @@ struct sde_encoder_phys_cmd_autorefresh { * @stream_sel: Stream selection for multi-stream interfaces * @pp_timeout_report_cnt: number of pingpong done irq timeout errors * @autorefresh: autorefresh feature state + * @pending_rd_ptr_cnt: atomic counter to indicate if retire fence can be + * signaled at the next rd_ptr_irq + * @rd_ptr_timestamp: last rd_ptr_irq timestamp * @pending_vblank_cnt: Atomic counter tracking pending wait for VBLANK * @pending_vblank_wq: Wait queue for blocking until VBLANK received + * @ctl_start_threshold: A threshold in microseconds allows command mode + * engine to trigger the retire fence without waiting for rd_ptr. */ struct sde_encoder_phys_cmd { struct sde_encoder_phys base; int stream_sel; int pp_timeout_report_cnt; struct sde_encoder_phys_cmd_autorefresh autorefresh; + atomic_t pending_rd_ptr_cnt; + ktime_t rd_ptr_timestamp; atomic_t pending_vblank_cnt; wait_queue_head_t pending_vblank_wq; + u32 ctl_start_threshold; }; /** diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c index ffa1d04597e3..a1c1a2afaf93 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c @@ -44,6 +44,12 @@ #define SDE_ENC_WR_PTR_START_TIMEOUT_US 20000 +/* + * Threshold for signalling retire fences in cases where + * CTL_START_IRQ is received just after RD_PTR_IRQ + */ +#define SDE_ENC_CTL_START_THRESHOLD_US 500 + #define SDE_ENC_MAX_POLL_TIMEOUT_US 2000 static inline int _sde_encoder_phys_cmd_get_idle_timeout( @@ -206,6 +212,23 @@ static void sde_encoder_phys_cmd_pp_tx_done_irq(void *arg, int irq_idx) SDE_EVT32_IRQ(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0, new_cnt, event); + /* + * Reduce the refcount for the retire fence as well as for the ctl_start + * if the counters are greater than zero. Signal retire fence if there + * was a retire fence count pending and kickoff count is zero. + */ + if (sde_encoder_phys_cmd_is_master(phys_enc) && (new_cnt == 0)) { + while (atomic_add_unless(&phys_enc->pending_retire_fence_cnt, + -1, 0)) { + if (phys_enc->parent_ops.handle_frame_done) + phys_enc->parent_ops.handle_frame_done( + phys_enc->parent, phys_enc, + SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE); + atomic_add_unless(&phys_enc->pending_ctlstart_cnt, + -1, 0); + } + } + /* Signal any waiting atomic commit thread */ wake_up_all(&phys_enc->pending_kickoff_wq); SDE_ATRACE_END("pp_done_irq"); @@ -240,6 +263,7 @@ static void sde_encoder_phys_cmd_te_rd_ptr_irq(void *arg, int irq_idx) { struct sde_encoder_phys *phys_enc = arg; struct sde_encoder_phys_cmd *cmd_enc; + u32 event = 0; if (!phys_enc || !phys_enc->hw_pp || !phys_enc->hw_intf) return; @@ -247,46 +271,94 @@ static void sde_encoder_phys_cmd_te_rd_ptr_irq(void *arg, int irq_idx) SDE_ATRACE_BEGIN("rd_ptr_irq"); cmd_enc = to_sde_encoder_phys_cmd(phys_enc); + /** + * signal only for master, when the ctl_start irq is + * done and incremented the pending_rd_ptr_cnt. + */ + if (sde_encoder_phys_cmd_is_master(phys_enc) + && atomic_add_unless(&cmd_enc->pending_rd_ptr_cnt, -1, 0) + && atomic_add_unless( + &phys_enc->pending_retire_fence_cnt, -1, 0)) { + + event = SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE; + if (phys_enc->parent_ops.handle_frame_done) + phys_enc->parent_ops.handle_frame_done( + phys_enc->parent, phys_enc, event); + } + SDE_EVT32_IRQ(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0, phys_enc->hw_intf->idx - INTF_0, - 0xfff); + event, 0xfff); if (phys_enc->parent_ops.handle_vblank_virt) phys_enc->parent_ops.handle_vblank_virt(phys_enc->parent, phys_enc); + cmd_enc->rd_ptr_timestamp = ktime_get(); + atomic_add_unless(&cmd_enc->pending_vblank_cnt, -1, 0); wake_up_all(&cmd_enc->pending_vblank_wq); SDE_ATRACE_END("rd_ptr_irq"); } -static void sde_encoder_phys_cmd_wr_ptr_irq(void *arg, int irq_idx) +static void sde_encoder_phys_cmd_ctl_start_irq(void *arg, int irq_idx) { struct sde_encoder_phys *phys_enc = arg; + struct sde_encoder_phys_cmd *cmd_enc; struct sde_hw_ctl *ctl; u32 event = 0; + s64 time_diff_us; if (!phys_enc || !phys_enc->hw_ctl) return; - SDE_ATRACE_BEGIN("wr_ptr_irq"); + SDE_ATRACE_BEGIN("ctl_start_irq"); + cmd_enc = to_sde_encoder_phys_cmd(phys_enc); ctl = phys_enc->hw_ctl; + atomic_add_unless(&phys_enc->pending_ctlstart_cnt, -1, 0); + atomic_set(&phys_enc->ctlstart_timeout, 0); - if (atomic_add_unless(&phys_enc->pending_retire_fence_cnt, -1, 0)) { - event = SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE; - if (phys_enc->parent_ops.handle_frame_done) - phys_enc->parent_ops.handle_frame_done( + time_diff_us = ktime_us_delta(ktime_get(), cmd_enc->rd_ptr_timestamp); + + /* handle retire fence based on only master */ + if (sde_encoder_phys_cmd_is_master(phys_enc) + && atomic_read(&phys_enc->pending_retire_fence_cnt)) { + /** + * Handle rare cases where the ctl_start_irq is received + * after rd_ptr_irq. If it falls within a threshold, it is + * guaranteed the frame would be picked up in the current TE. + * Signal retire fence immediately in such case. The threshold + * timer adds extra line time duration based on lowest panel + * fps for qsync enabled case. + */ + if ((time_diff_us <= cmd_enc->ctl_start_threshold) + && atomic_add_unless( + &phys_enc->pending_retire_fence_cnt, -1, 0)) { + + event = SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE; + + if (phys_enc->parent_ops.handle_frame_done) + phys_enc->parent_ops.handle_frame_done( phys_enc->parent, phys_enc, event); + + /** + * In ideal cases, ctl_start_irq is received before the + * rd_ptr_irq, so set the atomic flag to indicate the event + * and rd_ptr_irq will handle signalling the retire fence + */ + } else { + atomic_inc(&cmd_enc->pending_rd_ptr_cnt); + } } SDE_EVT32_IRQ(DRMID(phys_enc->parent), ctl->idx - CTL_0, - event, 0xfff); + time_diff_us, event, 0xfff); - /* Signal any waiting wr_ptr interrupt */ + /* Signal any waiting ctl start interrupt */ wake_up_all(&phys_enc->pending_kickoff_wq); - SDE_ATRACE_END("wr_ptr_irq"); + SDE_ATRACE_END("ctl_start_irq"); } static void sde_encoder_phys_cmd_underrun_irq(void *arg, int irq_idx) @@ -360,13 +432,6 @@ static void _sde_encoder_phys_cmd_setup_irq_hw_idx( else irq->hw_idx = phys_enc->hw_pp->idx; - irq = &phys_enc->irq[INTR_IDX_WRPTR]; - irq->irq_idx = -EINVAL; - if (phys_enc->has_intf_te) - irq->hw_idx = phys_enc->hw_intf->idx; - else - irq->hw_idx = phys_enc->hw_pp->idx; - mutex_unlock(phys_enc->vblank_ctl_lock); } @@ -487,6 +552,17 @@ static int _sde_encoder_phys_cmd_handle_ppdone_timeout( cmd_enc->pp_timeout_report_cnt++; pending_kickoff_cnt = atomic_read(&phys_enc->pending_kickoff_cnt); + if (sde_encoder_phys_cmd_is_master(phys_enc)) { + /* trigger the retire fence if it was missed */ + if (atomic_add_unless(&phys_enc->pending_retire_fence_cnt, + -1, 0)) + phys_enc->parent_ops.handle_frame_done( + phys_enc->parent, + phys_enc, + SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE); + atomic_add_unless(&phys_enc->pending_ctlstart_cnt, -1, 0); + } + SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0, cmd_enc->pp_timeout_report_cnt, pending_kickoff_cnt, @@ -828,11 +904,12 @@ void sde_encoder_phys_cmd_irq_control(struct sde_encoder_phys *phys_enc, if (enable) { sde_encoder_helper_register_irq(phys_enc, INTR_IDX_PINGPONG); + sde_encoder_helper_register_irq(phys_enc, INTR_IDX_UNDERRUN); sde_encoder_phys_cmd_control_vblank_irq(phys_enc, true); if (sde_encoder_phys_cmd_is_master(phys_enc)) { sde_encoder_helper_register_irq(phys_enc, - INTR_IDX_WRPTR); + INTR_IDX_CTL_START); sde_encoder_helper_register_irq(phys_enc, INTR_IDX_AUTOREFRESH_DONE); } @@ -840,11 +917,12 @@ void sde_encoder_phys_cmd_irq_control(struct sde_encoder_phys *phys_enc, } else { if (sde_encoder_phys_cmd_is_master(phys_enc)) { sde_encoder_helper_unregister_irq(phys_enc, - INTR_IDX_WRPTR); + INTR_IDX_CTL_START); sde_encoder_helper_unregister_irq(phys_enc, INTR_IDX_AUTOREFRESH_DONE); } + sde_encoder_helper_unregister_irq(phys_enc, INTR_IDX_UNDERRUN); sde_encoder_phys_cmd_control_vblank_irq(phys_enc, false); sde_encoder_helper_unregister_irq(phys_enc, INTR_IDX_PINGPONG); } @@ -1000,7 +1078,9 @@ static void sde_encoder_phys_cmd_tearcheck_config( tc_cfg.sync_threshold_continue = DEFAULT_TEARCHECK_SYNC_THRESH_CONTINUE; tc_cfg.start_pos = mode->vdisplay; tc_cfg.rd_ptr_irq = mode->vdisplay + 1; - tc_cfg.wr_ptr_irq = 1; + + cmd_enc->ctl_start_threshold = (extra_frame_trigger_time / 1000) + + SDE_ENC_CTL_START_THRESHOLD_US; SDE_DEBUG_CMDENC(cmd_enc, "tc %d intf %d vsync_clk_speed_hz %u vtotal %u vrefresh %u\n", @@ -1008,11 +1088,10 @@ static void sde_encoder_phys_cmd_tearcheck_config( phys_enc->hw_intf->idx - INTF_0, vsync_hz, mode->vtotal, mode->vrefresh); SDE_DEBUG_CMDENC(cmd_enc, - "tc %d intf %d enable %u start_pos %u rd_ptr_irq %u wr_ptr_irq %u\n", + "tc %d intf %d enable %u start_pos %u rd_ptr_irq %u\n", phys_enc->hw_pp->idx - PINGPONG_0, phys_enc->hw_intf->idx - INTF_0, - tc_enable, tc_cfg.start_pos, tc_cfg.rd_ptr_irq, - tc_cfg.wr_ptr_irq); + tc_enable, tc_cfg.start_pos, tc_cfg.rd_ptr_irq); SDE_DEBUG_CMDENC(cmd_enc, "tc %d intf %d hw_vsync_mode %u vsync_count %u vsync_init_val %u\n", phys_enc->hw_pp->idx - PINGPONG_0, @@ -1020,11 +1099,12 @@ static void sde_encoder_phys_cmd_tearcheck_config( tc_cfg.hw_vsync_mode, tc_cfg.vsync_count, tc_cfg.vsync_init_val); SDE_DEBUG_CMDENC(cmd_enc, - "tc %d intf %d cfgheight %u thresh_start %u thresh_cont %u\n", + "tc %d intf %d cfgheight %u thresh_start %u thresh_cont %u ctl_start_threshold:%d\n", phys_enc->hw_pp->idx - PINGPONG_0, phys_enc->hw_intf->idx - INTF_0, tc_cfg.sync_cfg_height, - tc_cfg.sync_threshold_start, tc_cfg.sync_threshold_continue); + tc_cfg.sync_threshold_start, tc_cfg.sync_threshold_continue, + cmd_enc->ctl_start_threshold); if (phys_enc->has_intf_te) { phys_enc->hw_intf->ops.setup_tearcheck(phys_enc->hw_intf, @@ -1220,6 +1300,7 @@ static void sde_encoder_phys_cmd_disable(struct sde_encoder_phys *phys_enc) SDE_ERROR("invalid encoder\n"); return; } + atomic_set(&phys_enc->ctlstart_timeout, 0); SDE_DEBUG_CMDENC(cmd_enc, "pp %d intf %d state %d\n", phys_enc->hw_pp->idx - PINGPONG_0, phys_enc->hw_intf->idx - INTF_0, @@ -1297,7 +1378,6 @@ static int sde_encoder_phys_cmd_prepare_for_kickoff( SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0, atomic_read(&phys_enc->pending_kickoff_cnt), atomic_read(&cmd_enc->autorefresh.kickoff_cnt)); - phys_enc->frame_trigger_mode = params->frame_trigger_mode; if (phys_enc->frame_trigger_mode == FRAME_DONE_WAIT_DEFAULT) { /* @@ -1326,7 +1406,11 @@ static int sde_encoder_phys_cmd_prepare_for_kickoff( phys_enc->hw_pp->ops.update_tearcheck( phys_enc->hw_pp, &tc_cfg); - SDE_EVT32(DRMID(phys_enc->parent), tc_cfg.sync_threshold_start); + cmd_enc->ctl_start_threshold = + (extra_frame_trigger_time / 1000) + + SDE_ENC_CTL_START_THRESHOLD_US; + SDE_EVT32(DRMID(phys_enc->parent), + tc_cfg.sync_threshold_start, cmd_enc->ctl_start_threshold); } SDE_DEBUG_CMDENC(cmd_enc, "pp:%d pending_cnt %d\n", @@ -1335,7 +1419,7 @@ static int sde_encoder_phys_cmd_prepare_for_kickoff( return ret; } -static int _sde_encoder_phys_cmd_wait_for_wr_ptr( +static int _sde_encoder_phys_cmd_wait_for_ctl_start( struct sde_encoder_phys *phys_enc) { struct sde_encoder_phys_cmd *cmd_enc = @@ -1352,14 +1436,14 @@ static int _sde_encoder_phys_cmd_wait_for_wr_ptr( ctl = phys_enc->hw_ctl; wait_info.wq = &phys_enc->pending_kickoff_wq; - wait_info.atomic_cnt = &phys_enc->pending_retire_fence_cnt; + wait_info.atomic_cnt = &phys_enc->pending_ctlstart_cnt; wait_info.timeout_ms = KICKOFF_TIMEOUT_MS; /* slave encoder doesn't enable for ppsplit */ if (_sde_encoder_phys_is_ppsplit_slave(phys_enc)) return 0; - ret = sde_encoder_helper_wait_for_irq(phys_enc, INTR_IDX_WRPTR, + ret = sde_encoder_helper_wait_for_irq(phys_enc, INTR_IDX_CTL_START, &wait_info); if (ret == -ETIMEDOUT) { struct sde_hw_ctl *ctl = phys_enc->hw_ctl; @@ -1369,23 +1453,29 @@ static int _sde_encoder_phys_cmd_wait_for_wr_ptr( if (frame_pending) SDE_ERROR_CMDENC(cmd_enc, - "wr_ptr interrupt wait failed\n"); + "ctl start interrupt wait failed\n"); else ret = 0; - /* - * Signaling the retire fence at wr_ptr timeout - * to allow the next commit and avoid device freeze. - * As wr_ptr timeout can occurs due to no read ptr, - * updating pending_rd_ptr_cnt here may not cover all - * cases. Hence signaling the retire fence. - */ - if (sde_encoder_phys_cmd_is_master(phys_enc) && - atomic_add_unless(&phys_enc->pending_retire_fence_cnt, - -1, 0)) - phys_enc->parent_ops.handle_frame_done( - phys_enc->parent, phys_enc, - SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE); + if (sde_encoder_phys_cmd_is_master(phys_enc)) { + /* + * Signaling the retire fence at ctl start timeout + * to allow the next commit and avoid device freeze. + * As ctl start timeout can occurs due to no read ptr, + * updating pending_rd_ptr_cnt here may not cover all + * cases. Hence signaling the retire fence. + */ + if (atomic_add_unless( + &phys_enc->pending_retire_fence_cnt, -1, 0)) + phys_enc->parent_ops.handle_frame_done( + phys_enc->parent, + phys_enc, + SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE); + atomic_add_unless( + &phys_enc->pending_ctlstart_cnt, -1, 0); + atomic_inc_return(&phys_enc->ctlstart_timeout); + } + } else if ((ret == 0) && (phys_enc->frame_trigger_mode == FRAME_DONE_WAIT_POSTED_START) && atomic_read(&phys_enc->pending_kickoff_cnt) && @@ -1437,7 +1527,7 @@ static int sde_encoder_phys_cmd_wait_for_commit_done( /* only required for master controller */ if (sde_encoder_phys_cmd_is_master(phys_enc)) - rc = _sde_encoder_phys_cmd_wait_for_wr_ptr(phys_enc); + rc = _sde_encoder_phys_cmd_wait_for_ctl_start(phys_enc); if (!rc && sde_encoder_phys_cmd_is_master(phys_enc) && cmd_enc->autorefresh.cfg.enable) @@ -1670,6 +1760,7 @@ struct sde_encoder_phys *sde_encoder_phys_cmd_init( phys_enc->enc_spinlock = p->enc_spinlock; phys_enc->vblank_ctl_lock = p->vblank_ctl_lock; cmd_enc->stream_sel = 0; + cmd_enc->ctl_start_threshold = SDE_ENC_CTL_START_THRESHOLD_US; phys_enc->enable_state = SDE_ENC_DISABLED; sde_encoder_phys_cmd_init_ops(&phys_enc->ops); phys_enc->comp_type = p->comp_type; @@ -1691,7 +1782,7 @@ struct sde_encoder_phys *sde_encoder_phys_cmd_init( irq->name = "ctl_start"; irq->intr_type = SDE_IRQ_TYPE_CTL_START; irq->intr_idx = INTR_IDX_CTL_START; - irq->cb.func = NULL; + irq->cb.func = sde_encoder_phys_cmd_ctl_start_irq; irq = &phys_enc->irq[INTR_IDX_PINGPONG]; irq->name = "pp_done"; @@ -1727,20 +1818,13 @@ struct sde_encoder_phys *sde_encoder_phys_cmd_init( irq->intr_idx = INTR_IDX_AUTOREFRESH_DONE; irq->cb.func = sde_encoder_phys_cmd_autorefresh_done_irq; - irq = &phys_enc->irq[INTR_IDX_WRPTR]; - irq->intr_idx = INTR_IDX_WRPTR; - irq->name = "wr_ptr"; - - if (phys_enc->has_intf_te) - irq->intr_type = SDE_IRQ_TYPE_INTF_TEAR_WR_PTR; - else - irq->intr_type = SDE_IRQ_TYPE_PING_PONG_WR_PTR; - irq->cb.func = sde_encoder_phys_cmd_wr_ptr_irq; - atomic_set(&phys_enc->vblank_refcount, 0); atomic_set(&phys_enc->pending_kickoff_cnt, 0); + atomic_set(&phys_enc->pending_ctlstart_cnt, 0); atomic_set(&phys_enc->pending_retire_fence_cnt, 0); + atomic_set(&cmd_enc->pending_rd_ptr_cnt, 0); atomic_set(&cmd_enc->pending_vblank_cnt, 0); + atomic_set(&phys_enc->ctlstart_timeout, 0); init_waitqueue_head(&phys_enc->pending_kickoff_wq); init_waitqueue_head(&cmd_enc->pending_vblank_wq); atomic_set(&cmd_enc->autorefresh.kickoff_cnt, 0); diff --git a/drivers/gpu/drm/msm/sde/sde_hw_intf.c b/drivers/gpu/drm/msm/sde/sde_hw_intf.c index e318395635a9..21b671164786 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_intf.c +++ b/drivers/gpu/drm/msm/sde/sde_hw_intf.c @@ -497,7 +497,6 @@ static int sde_hw_intf_setup_te_config(struct sde_hw_intf *intf, SDE_REG_WRITE(c, INTF_TEAR_SYNC_CONFIG_HEIGHT, te->sync_cfg_height); SDE_REG_WRITE(c, INTF_TEAR_VSYNC_INIT_VAL, te->vsync_init_val); SDE_REG_WRITE(c, INTF_TEAR_RD_PTR_IRQ, te->rd_ptr_irq); - SDE_REG_WRITE(c, INTF_TEAR_WR_PTR_IRQ, te->wr_ptr_irq); SDE_REG_WRITE(c, INTF_TEAR_START_POS, te->start_pos); SDE_REG_WRITE(c, INTF_TEAR_SYNC_THRESH, ((te->sync_threshold_continue << 16) | diff --git a/drivers/gpu/drm/msm/sde/sde_hw_mdss.h b/drivers/gpu/drm/msm/sde/sde_hw_mdss.h index 49be98dd3c2a..bd3ef45df834 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_mdss.h +++ b/drivers/gpu/drm/msm/sde/sde_hw_mdss.h @@ -647,7 +647,6 @@ struct sde_splash_data { * needs to be above the read pointer * @start_pos: The position from which the start_threshold value is added * @rd_ptr_irq: The read pointer line at which interrupt has to be generated - * @wr_ptr_irq: The write pointer line at which interrupt has to be generated * @hw_vsync_mode: Sync with external frame sync input */ struct sde_hw_tear_check { @@ -658,7 +657,6 @@ struct sde_hw_tear_check { u32 sync_threshold_continue; u32 start_pos; u32 rd_ptr_irq; - u32 wr_ptr_irq; u8 hw_vsync_mode; }; diff --git a/drivers/gpu/drm/msm/sde/sde_hw_pingpong.c b/drivers/gpu/drm/msm/sde/sde_hw_pingpong.c index 308fd5f6ee46..64c1a90f5952 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_pingpong.c +++ b/drivers/gpu/drm/msm/sde/sde_hw_pingpong.c @@ -183,7 +183,6 @@ static int sde_hw_pp_setup_te_config(struct sde_hw_pingpong *pp, SDE_REG_WRITE(c, PP_SYNC_CONFIG_HEIGHT, te->sync_cfg_height); SDE_REG_WRITE(c, PP_VSYNC_INIT_VAL, te->vsync_init_val); SDE_REG_WRITE(c, PP_RD_PTR_IRQ, te->rd_ptr_irq); - SDE_REG_WRITE(c, PP_WR_PTR_IRQ, te->wr_ptr_irq); SDE_REG_WRITE(c, PP_START_POS, te->start_pos); SDE_REG_WRITE(c, PP_SYNC_THRESH, ((te->sync_threshold_continue << 16) | From 783862fb44f02bd21b768aa8fa5708b71c5af4b1 Mon Sep 17 00:00:00 2001 From: Ray Zhang Date: Wed, 29 Jul 2020 19:03:27 +0800 Subject: [PATCH 303/592] Revert "drm/msm/sde: trigger frame done if ctl is idle" This reverts commit d2288839b4798d824d93a9e0c5c6fb7eea4aa3d4. Change-Id: I66f6f38621cdaa0835d4effe9e4dea2dd3fbefe1 Signed-off-by: Ray Zhang --- drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c | 14 -------------- drivers/gpu/drm/msm/sde/sde_hw_ctl.c | 9 --------- drivers/gpu/drm/msm/sde/sde_hw_ctl.h | 7 ------- 3 files changed, 30 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c index a1c1a2afaf93..d546ee2b34cf 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c @@ -1427,13 +1427,11 @@ static int _sde_encoder_phys_cmd_wait_for_ctl_start( struct sde_encoder_wait_info wait_info; int ret; bool frame_pending = true; - struct sde_hw_ctl *ctl; if (!phys_enc || !phys_enc->hw_ctl) { SDE_ERROR("invalid argument(s)\n"); return -EINVAL; } - ctl = phys_enc->hw_ctl; wait_info.wq = &phys_enc->pending_kickoff_wq; wait_info.atomic_cnt = &phys_enc->pending_ctlstart_cnt; @@ -1476,18 +1474,6 @@ static int _sde_encoder_phys_cmd_wait_for_ctl_start( atomic_inc_return(&phys_enc->ctlstart_timeout); } - } else if ((ret == 0) && - (phys_enc->frame_trigger_mode == FRAME_DONE_WAIT_POSTED_START) && - atomic_read(&phys_enc->pending_kickoff_cnt) && - ctl->ops.get_scheduler_status && - (ctl->ops.get_scheduler_status(ctl) & BIT(0)) && - phys_enc->parent_ops.handle_frame_done) { - atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0); - - phys_enc->parent_ops.handle_frame_done( - phys_enc->parent, phys_enc, - SDE_ENCODER_FRAME_EVENT_DONE | - SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE); } return ret; diff --git a/drivers/gpu/drm/msm/sde/sde_hw_ctl.c b/drivers/gpu/drm/msm/sde/sde_hw_ctl.c index 39a0c620fbfa..d5818034653f 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_ctl.c +++ b/drivers/gpu/drm/msm/sde/sde_hw_ctl.c @@ -31,7 +31,6 @@ #define CTL_PREPARE 0x0d0 #define CTL_SW_RESET 0x030 #define CTL_SW_RESET_OVERRIDE 0x060 -#define CTL_STATUS 0x064 #define CTL_LAYER_EXTN_OFFSET 0x40 #define CTL_ROT_TOP 0x0C0 #define CTL_ROT_FLUSH 0x0C4 @@ -710,13 +709,6 @@ static u32 sde_hw_ctl_get_reset_status(struct sde_hw_ctl *ctx) return (u32)SDE_REG_READ(&ctx->hw, CTL_SW_RESET); } -static u32 sde_hw_ctl_get_scheduler_status(struct sde_hw_ctl *ctx) -{ - if (!ctx) - return 0; - return (u32)SDE_REG_READ(&ctx->hw, CTL_STATUS); -} - static int sde_hw_ctl_reset_control(struct sde_hw_ctl *ctx) { struct sde_hw_blk_reg_map *c; @@ -1281,7 +1273,6 @@ static void _setup_ctl_ops(struct sde_hw_ctl_ops *ops, sde_hw_ctl_update_bitmask_periph_v1; ops->get_ctl_intf = sde_hw_ctl_get_intf_v1; ops->reset_post_disable = sde_hw_ctl_reset_post_disable; - ops->get_scheduler_status = sde_hw_ctl_get_scheduler_status; } else { ops->update_pending_flush = sde_hw_ctl_update_pending_flush; ops->trigger_flush = sde_hw_ctl_trigger_flush; diff --git a/drivers/gpu/drm/msm/sde/sde_hw_ctl.h b/drivers/gpu/drm/msm/sde/sde_hw_ctl.h index 1cef1f2ef58f..6c7d293f7839 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_ctl.h +++ b/drivers/gpu/drm/msm/sde/sde_hw_ctl.h @@ -296,13 +296,6 @@ struct sde_hw_ctl_ops { */ u32 (*get_reset)(struct sde_hw_ctl *ctx); - /** - * get_scheduler_reset - check ctl scheduler status bit - * @ctx : ctl path ctx pointer - * Returns: current value of ctl scheduler and idle status - */ - u32 (*get_scheduler_status)(struct sde_hw_ctl *ctx); - /** * hard_reset - force reset on ctl_path * @ctx : ctl path ctx pointer From 2f22bf2ce93ae76de83f53527e228a879f886219 Mon Sep 17 00:00:00 2001 From: Ray Zhang Date: Wed, 29 Jul 2020 19:03:29 +0800 Subject: [PATCH 304/592] Revert "drm/msm/sde: avoid frame done event during autorefresh" This reverts commit 45ca9aa53a350108c2aea19ad0fa30522e7f0910. Change-Id: I15e8c4001c84f102663f7ef406c6befffcbd0522 Signed-off-by: Ray Zhang --- drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c index d546ee2b34cf..8fd37447bb8c 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c @@ -200,8 +200,7 @@ static void sde_encoder_phys_cmd_pp_tx_done_irq(void *arg, int irq_idx) SDE_ATRACE_BEGIN("pp_done_irq"); /* notify all synchronous clients first, then asynchronous clients */ - if (phys_enc->parent_ops.handle_frame_done && - atomic_read(&phys_enc->pending_kickoff_cnt)) + if (phys_enc->parent_ops.handle_frame_done) phys_enc->parent_ops.handle_frame_done(phys_enc->parent, phys_enc, event); From 1f3a469d893006a3322f1c606916ce1f2768a073 Mon Sep 17 00:00:00 2001 From: Ajay Agarwal Date: Wed, 29 Jul 2020 21:24:33 +0530 Subject: [PATCH 305/592] usb: dwc3-msm: Set proper ssphy flag during peripheral bus suspend 'Commit fb34a13a6d5c ("usb: dwc3: Add support for 4 PHYs for dual port controller")' updated the SSPHY flags with DEVICE_IN_SS_MODE bit in dwc3_msm_is_host_superspeed function. This was moved from dwc3_msm_suspend function but flag update for device mode was not taken care of. This leads to improper fields in the AUTONOMOUS_MODE_CTRL register and SSPHY irq gets fired as soon as we go into low power mode and enable the ss_phy_irq. Fix this by updating the ssphy flags with DEVICE_IN_SS_MODE bit based on speed in dwc3_msm_is_dev_superspeed function. Change-Id: Ie669ff2ae80b87ace624cfcefeefb34b8a4cc0a0 Signed-off-by: Ajay Agarwal --- drivers/usb/dwc3/dwc3-msm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index 9bfad4bfbb02..8765629a22aa 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -496,8 +496,10 @@ static inline bool dwc3_msm_is_dev_superspeed(struct dwc3_msm *mdwc) speed = dwc3_msm_read_reg(mdwc->base, DWC3_DSTS) & DWC3_DSTS_CONNECTSPD; if ((speed & DWC3_DSTS_SUPERSPEED) || - (speed & DWC3_DSTS_SUPERSPEED_PLUS)) + (speed & DWC3_DSTS_SUPERSPEED_PLUS)) { + mdwc->ss_phy->flags |= DEVICE_IN_SS_MODE; return true; + } return false; } From 23b3f29a1fadfbc5253a71e733d25ac9956549f7 Mon Sep 17 00:00:00 2001 From: Kiran Gunda Date: Mon, 15 Jun 2020 16:50:03 +0530 Subject: [PATCH 306/592] backlight: qcom-wled: Add "qcom,sync-dly" device tree property Add "qcom,sync-dly" DT property to make the "LED_IDAC_SYNC_DELAY" register configurable. Change-Id: I3dd82cc13924adef834e28716655d9c9e817073a Signed-off-by: Kiran Gunda --- drivers/video/backlight/qcom-spmi-wled.c | 27 +++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/drivers/video/backlight/qcom-spmi-wled.c b/drivers/video/backlight/qcom-spmi-wled.c index 830ac900038a..1f21f15ab0b9 100644 --- a/drivers/video/backlight/qcom-spmi-wled.c +++ b/drivers/video/backlight/qcom-spmi-wled.c @@ -1,6 +1,6 @@ /* Copyright (c) 2015, Sony Mobile Communications, AB. * - * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -91,6 +91,7 @@ #define WLED_SINK_REG_STR_MOD_EN BIT(7) #define WLED_SINK_SYNC_DLY_REG(n) (0x51 + (n * 0x10)) +#define WLED_SINK_SYNC_DLY_MASK GENMASK(2, 0) #define WLED_SINK_FS_CURR_REG(n) (0x52 + (n * 0x10)) #define WLED_SINK_FS_MASK GENMASK(3, 0) @@ -207,6 +208,7 @@ struct wled_config { int string_cfg; int mod_sel; int cabc_sel; + int sync_dly; bool en_cabc; bool ext_pfet_sc_pro_en; bool auto_calib_enabled; @@ -1254,6 +1256,14 @@ static int wled4_setup(struct wled *wled) if (rc < 0) return rc; + addr = wled->sink_addr + + WLED_SINK_SYNC_DLY_REG(i); + rc = regmap_update_bits(wled->regmap, addr, + WLED_SINK_SYNC_DLY_MASK, + wled->cfg.sync_dly); + if (rc < 0) + return rc; + temp = i + WLED_SINK_CURR_SINK_SHFT; sink_en |= 1 << temp; } @@ -1339,6 +1349,7 @@ static const struct wled_config wled4_config_defaults = { .fs_current = 10, .ovp = 1, .switch_freq = 11, + .sync_dly = 2, .string_cfg = 0xf, .mod_sel = -EINVAL, .cabc_sel = -EINVAL, @@ -1404,6 +1415,15 @@ static const struct wled_var_cfg wled4_ovp_cfg = { .size = ARRAY_SIZE(wled4_ovp_values), }; +static const u32 wled4_sync_dly_values[] = { + 0, 200, 400, 600, 800, 1000, 1200, 1400, +}; + +static const struct wled_var_cfg wled4_sync_dly_cfg = { + .values = wled4_sync_dly_values, + .size = ARRAY_SIZE(wled4_sync_dly_values), +}; + static inline u32 wled5_ovp_values_fn(u32 idx) { /* @@ -2126,6 +2146,11 @@ static int wled_configure(struct wled *wled, struct device *dev) .val_ptr = &cfg->string_cfg, .cfg = &wled_string_cfg, }, + { + .name = "qcom,sync-dly", + .val_ptr = &cfg->sync_dly, + .cfg = &wled4_sync_dly_cfg, + }, }; const struct wled_u32_opts wled5_opts[] = { From c5cca0bfc0e0e4cb4854373ab55960891f17c063 Mon Sep 17 00:00:00 2001 From: Kiran Gunda Date: Wed, 22 Jul 2020 14:44:54 +0530 Subject: [PATCH 307/592] ARM: dts: msm: Configure "qcom,sync-dly" to 800us for SDM660 Leaving LED_SYNC_DLY register to a default value of 200us leads to OVP interrupts randomly during the brightness change. The legacy driver configured this to 800us which does not exhibit the OVP behavior.. Hence, configure the sync delay value to 800us. Change-Id: I84407a325dbcb51f77d53c6499f10df2f1b27d2a Signed-off-by: Kiran Gunda --- arch/arm64/boot/dts/qcom/pm660l.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/qcom/pm660l.dtsi b/arch/arm64/boot/dts/qcom/pm660l.dtsi index cee370cb5a54..5640a5b9126e 100644 --- a/arch/arm64/boot/dts/qcom/pm660l.dtsi +++ b/arch/arm64/boot/dts/qcom/pm660l.dtsi @@ -163,6 +163,7 @@ label = "backlight"; qcom,pmic-revid = <&pm660l_revid>; qcom,auto-calibration; + qcom,sync-dly = <800>; status = "ok"; }; From 32cd282d2b2aeef10120056194dfe2294a83af23 Mon Sep 17 00:00:00 2001 From: Ray Zhang Date: Wed, 29 Jul 2020 19:03:32 +0800 Subject: [PATCH 308/592] Revert "drm/msm/sde: add connector property for frame trigger mode" This reverts commit ae77a32db2f69461c9ef04fa94370128cb6b65ee. Change-Id: Iab587241076d1ffcc9e9904507292540377b8085 Signed-off-by: Ray Zhang --- drivers/gpu/drm/msm/msm_drv.h | 1 - drivers/gpu/drm/msm/sde/sde_connector.c | 243 +++++++++++------------- drivers/gpu/drm/msm/sde/sde_encoder.c | 54 +++--- 3 files changed, 133 insertions(+), 165 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index b415efd4ef6b..fb4d64fd1f17 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -199,7 +199,6 @@ enum msm_mdp_conn_property { CONNECTOR_PROP_LP, CONNECTOR_PROP_FB_TRANSLATION_MODE, CONNECTOR_PROP_QSYNC_MODE, - CONNECTOR_PROP_CMD_FRAME_TRIGGER_MODE, /* total # of properties */ CONNECTOR_PROP_COUNT diff --git a/drivers/gpu/drm/msm/sde/sde_connector.c b/drivers/gpu/drm/msm/sde/sde_connector.c index 2cddea4605b1..d0f36c7a00bf 100644 --- a/drivers/gpu/drm/msm/sde/sde_connector.c +++ b/drivers/gpu/drm/msm/sde/sde_connector.c @@ -64,12 +64,6 @@ static const struct drm_prop_enum_list e_qsync_mode[] = { {SDE_RM_QSYNC_ONE_SHOT_MODE, "one_shot"}, }; -static const struct drm_prop_enum_list e_frame_trigger_mode[] = { - {FRAME_DONE_WAIT_DEFAULT, "default"}, - {FRAME_DONE_WAIT_SERIALIZE, "serialize_frame_trigger"}, - {FRAME_DONE_WAIT_POSTED_START, "posted_start"}, -}; - static int sde_backlight_device_update_status(struct backlight_device *bd) { int brightness; @@ -1210,12 +1204,6 @@ static int sde_connector_atomic_set_property(struct drm_connector *connector, c_conn->bl_scale_ad = val; c_conn->bl_scale_dirty = true; break; - case CONNECTOR_PROP_HDR_METADATA: - rc = _sde_connector_set_ext_hdr_info(c_conn, - c_state, (void __user *)(uintptr_t)val); - if (rc) - SDE_ERROR_CONN(c_conn, "cannot set hdr info %d\n", rc); - break; case CONNECTOR_PROP_QSYNC_MODE: msm_property_set_dirty(&c_conn->property_info, &c_state->property_state, idx); @@ -1224,6 +1212,13 @@ static int sde_connector_atomic_set_property(struct drm_connector *connector, break; } + if (idx == CONNECTOR_PROP_HDR_METADATA) { + rc = _sde_connector_set_ext_hdr_info(c_conn, + c_state, (void __user *)(uintptr_t)val); + if (rc) + SDE_ERROR_CONN(c_conn, "cannot set hdr info %d\n", rc); + } + /* check for custom property handling */ if (!rc && c_conn->ops.set_property) { rc = c_conn->ops.set_property(connector, @@ -2130,122 +2125,6 @@ exit: return rc; } -static int _sde_connector_install_properties(struct drm_device *dev, - struct sde_kms *sde_kms, struct sde_connector *c_conn, - int connector_type, void *display, - struct msm_display_info *display_info) -{ - struct dsi_display *dsi_display; - int rc; - - msm_property_install_blob(&c_conn->property_info, "capabilities", - DRM_MODE_PROP_IMMUTABLE, CONNECTOR_PROP_SDE_INFO); - - rc = sde_connector_set_blob_data(&c_conn->base, - NULL, CONNECTOR_PROP_SDE_INFO); - if (rc) { - SDE_ERROR_CONN(c_conn, - "failed to setup connector info, rc = %d\n", rc); - return rc; - } - - msm_property_install_blob(&c_conn->property_info, "mode_properties", - DRM_MODE_PROP_IMMUTABLE, CONNECTOR_PROP_MODE_INFO); - - if (connector_type == DRM_MODE_CONNECTOR_DSI) { - dsi_display = (struct dsi_display *)(display); - if (dsi_display && dsi_display->panel && - dsi_display->panel->hdr_props.hdr_enabled == true) { - msm_property_install_blob(&c_conn->property_info, - "hdr_properties", - DRM_MODE_PROP_IMMUTABLE, - CONNECTOR_PROP_HDR_INFO); - - msm_property_set_blob(&c_conn->property_info, - &c_conn->blob_hdr, - &dsi_display->panel->hdr_props, - sizeof(dsi_display->panel->hdr_props), - CONNECTOR_PROP_HDR_INFO); - } - } - - msm_property_install_volatile_range( - &c_conn->property_info, "sde_drm_roi_v1", 0x0, - 0, ~0, 0, CONNECTOR_PROP_ROI_V1); - - /* install PP_DITHER properties */ - _sde_connector_install_dither_property(dev, sde_kms, c_conn); - - if (connector_type == DRM_MODE_CONNECTOR_DisplayPort) { - struct drm_msm_ext_hdr_properties hdr = {0}; - - msm_property_install_blob(&c_conn->property_info, - "ext_hdr_properties", - DRM_MODE_PROP_IMMUTABLE, - CONNECTOR_PROP_EXT_HDR_INFO); - - /* set default values to avoid reading uninitialized data */ - msm_property_set_blob(&c_conn->property_info, - &c_conn->blob_ext_hdr, - &hdr, - sizeof(hdr), - CONNECTOR_PROP_EXT_HDR_INFO); - } - - msm_property_install_volatile_range(&c_conn->property_info, - "hdr_metadata", 0x0, 0, ~0, 0, CONNECTOR_PROP_HDR_METADATA); - - msm_property_install_volatile_range(&c_conn->property_info, - "RETIRE_FENCE", 0x0, 0, ~0, 0, CONNECTOR_PROP_RETIRE_FENCE); - - msm_property_install_range(&c_conn->property_info, "autorefresh", - 0x0, 0, AUTOREFRESH_MAX_FRAME_CNT, 0, - CONNECTOR_PROP_AUTOREFRESH); - - if (connector_type == DRM_MODE_CONNECTOR_DSI) { - if (sde_kms->catalog->has_qsync && display_info->qsync_min_fps) - msm_property_install_enum(&c_conn->property_info, - "qsync_mode", 0, 0, e_qsync_mode, - ARRAY_SIZE(e_qsync_mode), - CONNECTOR_PROP_QSYNC_MODE); - - if (display_info->capabilities & MSM_DISPLAY_CAP_CMD_MODE) - msm_property_install_enum(&c_conn->property_info, - "frame_trigger_mode", 0, 0, - e_frame_trigger_mode, - ARRAY_SIZE(e_frame_trigger_mode), - CONNECTOR_PROP_CMD_FRAME_TRIGGER_MODE); - } - - msm_property_install_range(&c_conn->property_info, "bl_scale", - 0x0, 0, MAX_BL_SCALE_LEVEL, MAX_BL_SCALE_LEVEL, - CONNECTOR_PROP_BL_SCALE); - - msm_property_install_range(&c_conn->property_info, "ad_bl_scale", - 0x0, 0, MAX_AD_BL_SCALE_LEVEL, MAX_AD_BL_SCALE_LEVEL, - CONNECTOR_PROP_AD_BL_SCALE); - - c_conn->bl_scale_dirty = false; - c_conn->bl_scale = MAX_BL_SCALE_LEVEL; - c_conn->bl_scale_ad = MAX_AD_BL_SCALE_LEVEL; - - /* enum/bitmask properties */ - msm_property_install_enum(&c_conn->property_info, "topology_name", - DRM_MODE_PROP_IMMUTABLE, 0, e_topology_name, - ARRAY_SIZE(e_topology_name), - CONNECTOR_PROP_TOPOLOGY_NAME); - msm_property_install_enum(&c_conn->property_info, "topology_control", - 0, 1, e_topology_control, - ARRAY_SIZE(e_topology_control), - CONNECTOR_PROP_TOPOLOGY_CONTROL); - msm_property_install_enum(&c_conn->property_info, "LP", - 0, 0, e_power_mode, - ARRAY_SIZE(e_power_mode), - CONNECTOR_PROP_LP); - - return 0; -} - struct drm_connector *sde_connector_init(struct drm_device *dev, struct drm_encoder *encoder, struct drm_panel *panel, @@ -2257,6 +2136,7 @@ struct drm_connector *sde_connector_init(struct drm_device *dev, struct msm_drm_private *priv; struct sde_kms *sde_kms; struct sde_connector *c_conn = NULL; + struct dsi_display *dsi_display; struct msm_display_info display_info; int rc; @@ -2364,6 +2244,42 @@ struct drm_connector *sde_connector_init(struct drm_device *dev, } } + msm_property_install_blob(&c_conn->property_info, + "capabilities", + DRM_MODE_PROP_IMMUTABLE, + CONNECTOR_PROP_SDE_INFO); + + rc = sde_connector_set_blob_data(&c_conn->base, + NULL, + CONNECTOR_PROP_SDE_INFO); + if (rc) { + SDE_ERROR_CONN(c_conn, + "failed to setup connector info, rc = %d\n", rc); + goto error_cleanup_fence; + } + + msm_property_install_blob(&c_conn->property_info, + "mode_properties", + DRM_MODE_PROP_IMMUTABLE, + CONNECTOR_PROP_MODE_INFO); + + if (connector_type == DRM_MODE_CONNECTOR_DSI) { + dsi_display = (struct dsi_display *)(display); + if (dsi_display && dsi_display->panel && + dsi_display->panel->hdr_props.hdr_enabled == true) { + msm_property_install_blob(&c_conn->property_info, + "hdr_properties", + DRM_MODE_PROP_IMMUTABLE, + CONNECTOR_PROP_HDR_INFO); + + msm_property_set_blob(&c_conn->property_info, + &c_conn->blob_hdr, + &dsi_display->panel->hdr_props, + sizeof(dsi_display->panel->hdr_props), + CONNECTOR_PROP_HDR_INFO); + } + } + rc = sde_connector_get_info(&c_conn->base, &display_info); if (!rc && (connector_type == DRM_MODE_CONNECTOR_DSI) && (display_info.capabilities & MSM_DISPLAY_CAP_VID_MODE)) @@ -2372,10 +2288,73 @@ struct drm_connector *sde_connector_init(struct drm_device *dev, sde_connector_handle_disp_recovery, c_conn); - rc = _sde_connector_install_properties(dev, sde_kms, c_conn, - connector_type, display, &display_info); - if (rc) - goto error_cleanup_fence; + msm_property_install_volatile_range( + &c_conn->property_info, "sde_drm_roi_v1", 0x0, + 0, ~0, 0, CONNECTOR_PROP_ROI_V1); + + /* install PP_DITHER properties */ + _sde_connector_install_dither_property(dev, sde_kms, c_conn); + + if (connector_type == DRM_MODE_CONNECTOR_DisplayPort) { + struct drm_msm_ext_hdr_properties hdr = {0}; + + c_conn->hdr_capable = true; + + msm_property_install_blob(&c_conn->property_info, + "ext_hdr_properties", + DRM_MODE_PROP_IMMUTABLE, + CONNECTOR_PROP_EXT_HDR_INFO); + + /* set default values to avoid reading uninitialized data */ + msm_property_set_blob(&c_conn->property_info, + &c_conn->blob_ext_hdr, + &hdr, + sizeof(hdr), + CONNECTOR_PROP_EXT_HDR_INFO); + } + + msm_property_install_volatile_range(&c_conn->property_info, + "hdr_metadata", 0x0, 0, ~0, 0, CONNECTOR_PROP_HDR_METADATA); + + msm_property_install_volatile_range(&c_conn->property_info, + "RETIRE_FENCE", 0x0, 0, ~0, 0, CONNECTOR_PROP_RETIRE_FENCE); + + msm_property_install_range(&c_conn->property_info, "autorefresh", + 0x0, 0, AUTOREFRESH_MAX_FRAME_CNT, 0, + CONNECTOR_PROP_AUTOREFRESH); + + if (connector_type == DRM_MODE_CONNECTOR_DSI && + sde_kms->catalog->has_qsync && + display_info.qsync_min_fps) + msm_property_install_enum(&c_conn->property_info, "qsync_mode", + 0, 0, e_qsync_mode, ARRAY_SIZE(e_qsync_mode), + CONNECTOR_PROP_QSYNC_MODE); + + msm_property_install_range(&c_conn->property_info, "bl_scale", + 0x0, 0, MAX_BL_SCALE_LEVEL, MAX_BL_SCALE_LEVEL, + CONNECTOR_PROP_BL_SCALE); + + msm_property_install_range(&c_conn->property_info, "ad_bl_scale", + 0x0, 0, MAX_AD_BL_SCALE_LEVEL, MAX_AD_BL_SCALE_LEVEL, + CONNECTOR_PROP_AD_BL_SCALE); + + c_conn->bl_scale_dirty = false; + c_conn->bl_scale = MAX_BL_SCALE_LEVEL; + c_conn->bl_scale_ad = MAX_AD_BL_SCALE_LEVEL; + + /* enum/bitmask properties */ + msm_property_install_enum(&c_conn->property_info, "topology_name", + DRM_MODE_PROP_IMMUTABLE, 0, e_topology_name, + ARRAY_SIZE(e_topology_name), + CONNECTOR_PROP_TOPOLOGY_NAME); + msm_property_install_enum(&c_conn->property_info, "topology_control", + 0, 1, e_topology_control, + ARRAY_SIZE(e_topology_control), + CONNECTOR_PROP_TOPOLOGY_CONTROL); + msm_property_install_enum(&c_conn->property_info, "LP", + 0, 0, e_power_mode, + ARRAY_SIZE(e_power_mode), + CONNECTOR_PROP_LP); rc = msm_property_install_get_status(&c_conn->property_info); if (rc) { diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c index 7b04b6d019d7..402e52e118a8 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder.c @@ -4643,29 +4643,6 @@ static void _helper_flush_dsc(struct sde_encoder_virt *sde_enc) } } -static void _sde_encoder_needs_hw_reset(struct drm_encoder *drm_enc, - int ln_cnt1) -{ - struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc); - struct sde_encoder_phys *phys; - int ln_cnt2, i; - - /* query line count before cur_master is updated */ - if (sde_enc->cur_master && sde_enc->cur_master->ops.get_wr_line_count) - ln_cnt2 = sde_enc->cur_master->ops.get_wr_line_count( - sde_enc->cur_master); - else - ln_cnt2 = -EINVAL; - - SDE_EVT32(DRMID(drm_enc), ln_cnt1, ln_cnt2); - - for (i = 0; i < sde_enc->num_phys_encs; i++) { - phys = sde_enc->phys_encs[i]; - if (phys && phys->ops.hw_reset) - phys->ops.hw_reset(phys); - } -} - int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, struct sde_encoder_kickoff_params *params) { @@ -4675,7 +4652,9 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, struct sde_crtc *sde_crtc; struct msm_drm_private *priv = NULL; bool needs_hw_reset = false; - int ln_cnt1 = -EINVAL, i, rc, ret = 0; + uint32_t ln_cnt1, ln_cnt2; + unsigned int i; + int rc, ret = 0; struct msm_display_info *disp_info; if (!drm_enc || !params || !drm_enc->dev || @@ -4696,12 +4675,8 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, if (sde_enc->cur_master && sde_enc->cur_master->ops.get_wr_line_count) ln_cnt1 = sde_enc->cur_master->ops.get_wr_line_count( sde_enc->cur_master); - - if (sde_enc->cur_master && sde_enc->cur_master->connector && - disp_info->capabilities & MSM_DISPLAY_CAP_CMD_MODE) - sde_enc->frame_trigger_mode = sde_connector_get_property( - sde_enc->cur_master->connector->state, - CONNECTOR_PROP_CMD_FRAME_TRIGGER_MODE); + else + ln_cnt1 = -EINVAL; /* prepare for next kickoff, may include waiting on previous kickoff */ SDE_ATRACE_BEGIN("sde_encoder_prepare_for_kickoff"); @@ -4738,8 +4713,23 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, } /* if any phys needs reset, reset all phys, in-order */ - if (needs_hw_reset) - _sde_encoder_needs_hw_reset(drm_enc, ln_cnt1); + if (needs_hw_reset) { + /* query line count before cur_master is updated */ + if (sde_enc->cur_master && + sde_enc->cur_master->ops.get_wr_line_count) + ln_cnt2 = sde_enc->cur_master->ops.get_wr_line_count( + sde_enc->cur_master); + else + ln_cnt2 = -EINVAL; + + SDE_EVT32(DRMID(drm_enc), ln_cnt1, ln_cnt2, + SDE_EVTLOG_FUNC_CASE1); + for (i = 0; i < sde_enc->num_phys_encs; i++) { + phys = sde_enc->phys_encs[i]; + if (phys && phys->ops.hw_reset) + phys->ops.hw_reset(phys); + } + } _sde_encoder_update_master(drm_enc, params); From 2d9700c868591006f257c8970637a6342df22cc8 Mon Sep 17 00:00:00 2001 From: Ray Zhang Date: Wed, 29 Jul 2020 19:03:35 +0800 Subject: [PATCH 309/592] Revert "drm/msm/sde: delay reset frame by a frame for posted trigger" This reverts commit 6773daeb3dc897a8c039d0093a7ec52ed3bbebb9. Change-Id: Iaf291607ff50fad4f70f4a2f2d749ffd06556eb8 Signed-off-by: Ray Zhang --- drivers/gpu/drm/msm/sde/sde_crtc.c | 18 +++++++++--------- drivers/gpu/drm/msm/sde/sde_crtc.h | 26 -------------------------- drivers/gpu/drm/msm/sde/sde_encoder.c | 3 --- drivers/gpu/drm/msm/sde/sde_encoder.h | 2 -- drivers/gpu/drm/msm/sde/sde_kms.c | 1 - 5 files changed, 9 insertions(+), 41 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c index 035eed949d2e..663cb76b0c79 100644 --- a/drivers/gpu/drm/msm/sde/sde_crtc.c +++ b/drivers/gpu/drm/msm/sde/sde_crtc.c @@ -4094,13 +4094,14 @@ static void _sde_crtc_remove_pipe_flush(struct drm_crtc *crtc) } /** - * sde_crtc_reset_hw - attempt hardware reset on errors + * _sde_crtc_reset_hw - attempt hardware reset on errors * @crtc: Pointer to DRM crtc instance * @old_state: Pointer to crtc state for previous commit * @recovery_events: Whether or not recovery events are enabled * Returns: Zero if current commit should still be attempted */ -int sde_crtc_reset_hw(struct drm_crtc *crtc, struct drm_crtc_state *old_state, +static int _sde_crtc_reset_hw(struct drm_crtc *crtc, + struct drm_crtc_state *old_state, bool recovery_events) { struct drm_plane *plane_halt[MAX_PLANES]; @@ -4298,10 +4299,9 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc, struct msm_drm_private *priv; struct sde_kms *sde_kms; struct sde_crtc_state *cstate; - bool is_error, reset_req; + bool is_error, reset_req, recovery_events; unsigned long flags; enum sde_crtc_idle_pc_state idle_pc_state; - struct sde_encoder_kickoff_params params = { 0 }; if (!crtc) { SDE_ERROR("invalid argument\n"); @@ -4335,6 +4335,7 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc, idle_pc_state = sde_crtc_get_property(cstate, CRTC_PROP_IDLE_PC_STATE); list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + struct sde_encoder_kickoff_params params = { 0 }; if (encoder->crtc != crtc) continue; @@ -4349,6 +4350,9 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc, if (sde_encoder_prepare_for_kickoff(encoder, ¶ms)) reset_req = true; + recovery_events = + sde_encoder_recovery_events_enabled(encoder); + if (idle_pc_state != IDLE_PC_NONE) sde_encoder_control_idle_pc(encoder, (idle_pc_state == IDLE_PC_ENABLE) ? true : false); @@ -4359,11 +4363,7 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc, * preparing for the kickoff */ if (reset_req) { - sde_crtc->frame_trigger_mode = params.frame_trigger_mode; - if (sde_crtc->frame_trigger_mode - != FRAME_DONE_WAIT_POSTED_START && - sde_crtc_reset_hw(crtc, old_state, - params.recovery_events_enabled)) + if (_sde_crtc_reset_hw(crtc, old_state, recovery_events)) is_error = true; } diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.h b/drivers/gpu/drm/msm/sde/sde_crtc.h index d3d875f08492..4676a140267c 100644 --- a/drivers/gpu/drm/msm/sde/sde_crtc.h +++ b/drivers/gpu/drm/msm/sde/sde_crtc.h @@ -227,7 +227,6 @@ struct sde_crtc_fps_info { * @rp_lock : serialization lock for resource pool * @rp_head : list of active resource pool * @plane_mask_old: keeps track of the planes used in the previous commit - * @frame_trigger_mode: frame trigger mode */ struct sde_crtc { struct drm_crtc base; @@ -306,7 +305,6 @@ struct sde_crtc { /* blob for histogram data */ struct drm_property_blob *hist_blob; - enum frame_trigger_mode_type frame_trigger_mode; }; #define to_sde_crtc(x) container_of(x, struct sde_crtc, base) @@ -544,30 +542,6 @@ static inline int sde_crtc_frame_pending(struct drm_crtc *crtc) return atomic_read(&sde_crtc->frame_pending); } -/** - * sde_crtc_reset_hw - attempt hardware reset on errors - * @crtc: Pointer to DRM crtc instance - * @old_state: Pointer to crtc state for previous commit - * @recovery_events: Whether or not recovery events are enabled - * Returns: Zero if current commit should still be attempted - */ -int sde_crtc_reset_hw(struct drm_crtc *crtc, struct drm_crtc_state *old_state, - bool recovery_events); - -/** - * sde_crtc_request_frame_reset - requests for next frame reset - * @crtc: Pointer to drm crtc object - */ -static inline int sde_crtc_request_frame_reset(struct drm_crtc *crtc) -{ - struct sde_crtc *sde_crtc = to_sde_crtc(crtc); - - if (sde_crtc->frame_trigger_mode == FRAME_DONE_WAIT_POSTED_START) - sde_crtc_reset_hw(crtc, crtc->state, false); - - return 0; -} - /** * sde_crtc_vblank - enable or disable vblanks for this crtc * @crtc: Pointer to drm crtc object diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c index 402e52e118a8..f1d288ef7da8 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder.c @@ -4683,9 +4683,6 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, for (i = 0; i < sde_enc->num_phys_encs; i++) { phys = sde_enc->phys_encs[i]; params->is_primary = sde_enc->disp_info.is_primary; - params->frame_trigger_mode = sde_enc->frame_trigger_mode; - params->recovery_events_enabled = - sde_enc->recovery_events_enabled; if (phys) { if (phys->ops.prepare_for_kickoff) { rc = phys->ops.prepare_for_kickoff( diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.h b/drivers/gpu/drm/msm/sde/sde_encoder.h index 69b3ad28bb01..7fa700e2910a 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder.h +++ b/drivers/gpu/drm/msm/sde/sde_encoder.h @@ -60,14 +60,12 @@ struct sde_encoder_hw_resources { * @affected_displays: bitmask, bit set means the ROI of the commit lies within * the bounds of the physical display at the bit index * @recovery_events_enabled: indicates status of client for recoovery events - * @frame_trigger_mode: indicates frame trigger mode */ struct sde_encoder_kickoff_params { u32 inline_rotate_prefill; u32 is_primary; unsigned long affected_displays; bool recovery_events_enabled; - enum frame_trigger_mode_type frame_trigger_mode; }; /** diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c index 3dc379caa327..9da771981d2e 100644 --- a/drivers/gpu/drm/msm/sde/sde_kms.c +++ b/drivers/gpu/drm/msm/sde/sde_kms.c @@ -1220,7 +1220,6 @@ static void sde_kms_wait_for_commit_done(struct msm_kms *kms, ret = sde_encoder_wait_for_event(encoder, MSM_ENC_COMMIT_DONE); if (ret && ret != -EWOULDBLOCK) { SDE_ERROR("wait for commit done returned %d\n", ret); - sde_crtc_request_frame_reset(crtc); break; } From 2c3a2b7badd45648e9429e568f889319b21c49a6 Mon Sep 17 00:00:00 2001 From: Ray Zhang Date: Wed, 29 Jul 2020 19:03:37 +0800 Subject: [PATCH 310/592] Revert "drm/msm/sde: support posted frame trigger for cmd mode" This reverts commit 8e94c21b1d0acd8ab386edefdee299e960d02b86. Change-Id: I0398b7563aa91d70eab7a6a4a772168b9eb601ca Signed-off-by: Ray Zhang --- drivers/gpu/drm/msm/sde/sde_encoder.c | 7 -- drivers/gpu/drm/msm/sde/sde_encoder.h | 1 - drivers/gpu/drm/msm/sde/sde_encoder_phys.h | 6 +- .../gpu/drm/msm/sde/sde_encoder_phys_cmd.c | 84 ++++++++----------- drivers/gpu/drm/msm/sde/sde_kms.h | 14 ---- 5 files changed, 37 insertions(+), 75 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c index f1d288ef7da8..e83b3063c99a 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder.c @@ -221,8 +221,6 @@ enum sde_enc_rc_states { * @topology: topology of the display * @vblank_enabled: boolean to track userspace vblank vote * @idle_pc_restore: flag to indicate idle_pc_restore happened - * @frame_trigger_mode: frame trigger mode indication for command - * mode display * @rsc_config: rsc configuration for display vtotal, fps, etc. * @cur_conn_roi: current connector roi * @prv_conn_roi: previous connector roi to optimize if unchanged @@ -285,7 +283,6 @@ struct sde_encoder_virt { struct msm_display_topology topology; bool vblank_enabled; bool idle_pc_restore; - enum frame_trigger_mode_type frame_trigger_mode; struct sde_rsc_cmd_config rsc_config; struct sde_rect cur_conn_roi; @@ -3319,7 +3316,6 @@ static void sde_encoder_virt_enable(struct drm_encoder *drm_enc) phys->comp_type = comp_info->comp_type; phys->comp_ratio = comp_info->comp_ratio; phys->wide_bus_en = mode_info.wide_bus_en; - phys->frame_trigger_mode = sde_enc->frame_trigger_mode; if (phys->comp_type == MSM_DISPLAY_COMPRESSION_DSC) { phys->dsc_extra_pclk_cycle_cnt = @@ -5156,9 +5152,6 @@ static int _sde_encoder_init_debugfs(struct drm_encoder *drm_enc) debugfs_create_bool("idle_power_collapse", 0600, sde_enc->debugfs_root, &sde_enc->idle_pc_enabled); - debugfs_create_u32("frame_trigger_mode", 0600, sde_enc->debugfs_root, - &sde_enc->frame_trigger_mode); - for (i = 0; i < sde_enc->num_phys_encs; i++) if (sde_enc->phys_encs[i] && sde_enc->phys_encs[i]->ops.late_register) diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.h b/drivers/gpu/drm/msm/sde/sde_encoder.h index 7fa700e2910a..3ce8c9c24517 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder.h +++ b/drivers/gpu/drm/msm/sde/sde_encoder.h @@ -23,7 +23,6 @@ #include "msm_prop.h" #include "sde_hw_mdss.h" -#include "sde_kms.h" #define SDE_ENCODER_FRAME_EVENT_DONE BIT(0) #define SDE_ENCODER_FRAME_EVENT_ERROR BIT(1) diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h index 841ffb9f7407..1ef374e37a3f 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h @@ -296,8 +296,6 @@ struct sde_encoder_irq { * @in_clone_mode Indicates if encoder is in clone mode ref@CWB * @vfp_cached: cached vertical front porch to be used for * programming ROT and MDP fetch start - * @frame_trigger_mode: frame trigger mode indication for command - * mode display */ struct sde_encoder_phys { struct drm_encoder *parent; @@ -341,7 +339,6 @@ struct sde_encoder_phys { bool cont_splash_enabled; bool in_clone_mode; int vfp_cached; - enum frame_trigger_mode_type frame_trigger_mode; }; static inline int sde_encoder_phys_inc_pending(struct sde_encoder_phys *phys) @@ -385,6 +382,8 @@ struct sde_encoder_phys_cmd_autorefresh { * @base: Baseclass physical encoder structure * @intf_idx: Intf Block index used by this phys encoder * @stream_sel: Stream selection for multi-stream interfaces + * @serialize_wait4pp: serialize wait4pp feature waits for pp_done interrupt + * after ctl_start instead of before next frame kickoff * @pp_timeout_report_cnt: number of pingpong done irq timeout errors * @autorefresh: autorefresh feature state * @pending_rd_ptr_cnt: atomic counter to indicate if retire fence can be @@ -398,6 +397,7 @@ struct sde_encoder_phys_cmd_autorefresh { struct sde_encoder_phys_cmd { struct sde_encoder_phys base; int stream_sel; + bool serialize_wait4pp; int pp_timeout_report_cnt; struct sde_encoder_phys_cmd_autorefresh autorefresh; atomic_t pending_rd_ptr_cnt; diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c index 8fd37447bb8c..e3f55f500691 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c @@ -199,6 +199,24 @@ static void sde_encoder_phys_cmd_pp_tx_done_irq(void *arg, int irq_idx) SDE_ATRACE_BEGIN("pp_done_irq"); + /* handle rare cases where the ctl_start_irq is not received */ + if (sde_encoder_phys_cmd_is_master(phys_enc)) { + /* + * Reduce the refcount for the retire fence as well + * as for the ctl_start if the counters are greater + * than zero. If there was a retire fence count pending, + * then signal the RETIRE FENCE here. + */ + if (atomic_add_unless(&phys_enc->pending_retire_fence_cnt, + -1, 0)) + phys_enc->parent_ops.handle_frame_done( + phys_enc->parent, + phys_enc, + SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE); + atomic_add_unless(&phys_enc->pending_ctlstart_cnt, -1, 0); + atomic_set(&phys_enc->ctlstart_timeout, 0); + } + /* notify all synchronous clients first, then asynchronous clients */ if (phys_enc->parent_ops.handle_frame_done) phys_enc->parent_ops.handle_frame_done(phys_enc->parent, @@ -211,23 +229,6 @@ static void sde_encoder_phys_cmd_pp_tx_done_irq(void *arg, int irq_idx) SDE_EVT32_IRQ(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0, new_cnt, event); - /* - * Reduce the refcount for the retire fence as well as for the ctl_start - * if the counters are greater than zero. Signal retire fence if there - * was a retire fence count pending and kickoff count is zero. - */ - if (sde_encoder_phys_cmd_is_master(phys_enc) && (new_cnt == 0)) { - while (atomic_add_unless(&phys_enc->pending_retire_fence_cnt, - -1, 0)) { - if (phys_enc->parent_ops.handle_frame_done) - phys_enc->parent_ops.handle_frame_done( - phys_enc->parent, phys_enc, - SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE); - atomic_add_unless(&phys_enc->pending_ctlstart_cnt, - -1, 0); - } - } - /* Signal any waiting atomic commit thread */ wake_up_all(&phys_enc->pending_kickoff_wq); SDE_ATRACE_END("pp_done_irq"); @@ -544,10 +545,6 @@ static int _sde_encoder_phys_cmd_handle_ppdone_timeout( conn = phys_enc->connector; sde_conn = to_sde_connector(conn); - - if (atomic_read(&phys_enc->pending_kickoff_cnt) == 0) - return 0; - cmd_enc->pp_timeout_report_cnt++; pending_kickoff_cnt = atomic_read(&phys_enc->pending_kickoff_cnt); @@ -747,7 +744,7 @@ static int _sde_encoder_phys_cmd_wait_for_idle( to_sde_encoder_phys_cmd(phys_enc); struct sde_encoder_wait_info wait_info; bool recovery_events; - int ret, i, pending_cnt; + int ret; if (!phys_enc) { SDE_ERROR("invalid encoder\n"); @@ -767,9 +764,7 @@ static int _sde_encoder_phys_cmd_wait_for_idle( ret = sde_encoder_helper_wait_for_irq(phys_enc, INTR_IDX_PINGPONG, &wait_info); if (ret == -ETIMEDOUT) { - pending_cnt = atomic_read(&phys_enc->pending_kickoff_cnt); - for (i = 0; i < pending_cnt; i++) - _sde_encoder_phys_cmd_handle_ppdone_timeout(phys_enc, + _sde_encoder_phys_cmd_handle_ppdone_timeout(phys_enc, recovery_events); } else if (!ret) { if (cmd_enc->pp_timeout_report_cnt && recovery_events) { @@ -1365,7 +1360,7 @@ static int sde_encoder_phys_cmd_prepare_for_kickoff( struct sde_hw_tear_check tc_cfg = {0}; struct sde_encoder_phys_cmd *cmd_enc = to_sde_encoder_phys_cmd(phys_enc); - int ret = 0; + int ret; u32 extra_frame_trigger_time; if (!phys_enc || !phys_enc->hw_pp) { @@ -1378,19 +1373,17 @@ static int sde_encoder_phys_cmd_prepare_for_kickoff( atomic_read(&phys_enc->pending_kickoff_cnt), atomic_read(&cmd_enc->autorefresh.kickoff_cnt)); - if (phys_enc->frame_trigger_mode == FRAME_DONE_WAIT_DEFAULT) { - /* - * Mark kickoff request as outstanding. If there are more than - * one outstanding frame, then we have to wait for the previous - * frame to complete - */ - ret = _sde_encoder_phys_cmd_wait_for_idle(phys_enc); - if (ret) { - atomic_set(&phys_enc->pending_kickoff_cnt, 0); - SDE_EVT32(DRMID(phys_enc->parent), + /* + * Mark kickoff request as outstanding. If there are more than one, + * outstanding, then we have to wait for the previous one to complete + */ + ret = _sde_encoder_phys_cmd_wait_for_idle(phys_enc); + if (ret) { + /* force pending_kickoff_cnt 0 to discard failed kickoff */ + atomic_set(&phys_enc->pending_kickoff_cnt, 0); + SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0); - SDE_ERROR("failed wait_for_idle: %d\n", ret); - } + SDE_ERROR("failed wait_for_idle: %d\n", ret); } if (sde_connector_is_qsync_updated(phys_enc->connector)) { @@ -1518,18 +1511,9 @@ static int sde_encoder_phys_cmd_wait_for_commit_done( cmd_enc->autorefresh.cfg.enable) rc = _sde_encoder_phys_cmd_wait_for_autorefresh_done(phys_enc); - /* wait for posted start or serialize trigger */ - if ((atomic_read(&phys_enc->pending_kickoff_cnt) > 1) || - (!rc && phys_enc->frame_trigger_mode == - FRAME_DONE_WAIT_SERIALIZE)) { - rc = _sde_encoder_phys_cmd_wait_for_idle(phys_enc); - if (rc) { - atomic_set(&phys_enc->pending_kickoff_cnt, 0); - SDE_EVT32(DRMID(phys_enc->parent), - phys_enc->hw_pp->idx - PINGPONG_0); - SDE_ERROR("failed wait_for_idle: %d\n", rc); - } - } + /* required for both controllers */ + if (!rc && cmd_enc->serialize_wait4pp) + sde_encoder_phys_cmd_prepare_for_kickoff(phys_enc, NULL); return rc; } diff --git a/drivers/gpu/drm/msm/sde/sde_kms.h b/drivers/gpu/drm/msm/sde/sde_kms.h index d11393fa8890..b390c4af3c9e 100644 --- a/drivers/gpu/drm/msm/sde/sde_kms.h +++ b/drivers/gpu/drm/msm/sde/sde_kms.h @@ -169,20 +169,6 @@ enum sde_kms_sui_misr_state { SUI_MISR_DISABLE_REQ }; -/* - * @FRAME_DONE_WAIT_DEFAULT: waits for frame N pp_done interrupt before - * triggering frame N+1. - * @FRAME_DONE_WAIT_SERIALIZE: serialize pp_done and ctl_start irq for frame - * N without next frame trigger wait. - * @FRAME_DONE_WAIT_POSTED_START: Do not wait for pp_done interrupt for any - * frame. Wait will trigger only for error case. - */ -enum frame_trigger_mode_type { - FRAME_DONE_WAIT_DEFAULT, - FRAME_DONE_WAIT_SERIALIZE, - FRAME_DONE_WAIT_POSTED_START, -}; - /** * struct sde_kms_smmu_state_data: stores the smmu state and transition type * @state: current state of smmu context banks From 4e341a1185f4bd9bf7ed7265e84c039f4dff6fd0 Mon Sep 17 00:00:00 2001 From: Ray Zhang Date: Wed, 29 Jul 2020 19:03:40 +0800 Subject: [PATCH 311/592] Revert "drm/msm/sde: use atomic counter for pending frame done" This reverts commit 3a50ed281867384ff32d52ba96ae94e19d31230e. Change-Id: I7b24aa318f9cb1b26d47ca84facf78a6b95f8022 Signed-off-by: Ray Zhang --- drivers/gpu/drm/msm/sde/sde_encoder.c | 90 ++++++++++++++------------- 1 file changed, 46 insertions(+), 44 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c index e83b3063c99a..f455f24da622 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder.c @@ -197,8 +197,9 @@ enum sde_enc_rc_states { * @debugfs_root: Debug file system root file node * @enc_lock: Lock around physical encoder create/destroy and access. - * @frame_done_cnt: Atomic counter for tracking which phy_enc is - * done with frame processing. + * @frame_busy_mask: Bitmask tracking which phys_enc we are still + * busy processing current command. + * Bit0 = phys_encs[0] etc. * @crtc_frame_event_cb: callback handler for frame event * @crtc_frame_event_cb_data: callback handler private data * @vsync_event_timer: vsync timer @@ -259,7 +260,7 @@ struct sde_encoder_virt { struct dentry *debugfs_root; struct mutex enc_lock; - atomic_t frame_done_cnt[MAX_PHYS_ENCODERS_PER_VIRTUAL]; + DECLARE_BITMAP(frame_busy_mask, MAX_PHYS_ENCODERS_PER_VIRTUAL); void (*crtc_frame_event_cb)(void *, u32 event); struct sde_crtc_frame_event_cb_data crtc_frame_event_cb_data; @@ -2447,16 +2448,6 @@ static int sde_encoder_resource_control(struct drm_encoder *drm_enc, return -EINVAL; } - /* - * schedule off work item only when there are no - * frames pending - */ - if (sde_crtc_frame_pending(sde_enc->crtc) > 1) { - SDE_DEBUG_ENC(sde_enc, "skip schedule work"); - SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state, - SDE_EVTLOG_FUNC_CASE2); - return 0; - } if (sde_enc->crtc->index >= ARRAY_SIZE(priv->disp_thread)) { SDE_ERROR("invalid crtc index :%u\n", sde_enc->crtc->index); @@ -2478,6 +2469,17 @@ static int sde_encoder_resource_control(struct drm_encoder *drm_enc, return -EINVAL; } + /* + * schedule off work item only when there are no + * frames pending + */ + if (sde_crtc_frame_pending(sde_enc->crtc) > 1) { + SDE_DEBUG_ENC(sde_enc, "skip schedule work"); + SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state, + SDE_EVTLOG_FUNC_CASE2); + return 0; + } + /* schedule delayed off work if autorefresh is disabled */ if (sde_enc->cur_master && sde_enc->cur_master->ops.is_autorefresh_enabled) @@ -2690,10 +2692,17 @@ static int sde_encoder_resource_control(struct drm_encoder *drm_enc, SDE_EVTLOG_ERROR); mutex_unlock(&sde_enc->rc_lock); return 0; - } else if (sde_crtc_frame_pending(sde_enc->crtc) > 1) { - SDE_DEBUG_ENC(sde_enc, "skip idle entry"); + } + + /* + * if we are in ON but a frame was just kicked off, + * ignore the IDLE event, it's probably a stale timer event + */ + if (sde_enc->frame_busy_mask[0]) { + SDE_ERROR_ENC(sde_enc, + "sw_event:%d, rc:%d frame pending\n", + sw_event, sde_enc->rc_state); SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state, - sde_crtc_frame_pending(sde_enc->crtc), SDE_EVTLOG_ERROR); mutex_unlock(&sde_enc->rc_lock); return 0; @@ -3654,8 +3663,6 @@ static void sde_encoder_frame_done_callback( { struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc); unsigned int i; - bool trigger = true; - enum sde_rm_topology_name topology = SDE_RM_TOPOLOGY_NONE; if (!drm_enc || !sde_enc->cur_master) { SDE_ERROR("invalid param: drm_enc %lx, cur_master %lx\n", @@ -3670,35 +3677,26 @@ static void sde_encoder_frame_done_callback( if (event & (SDE_ENCODER_FRAME_EVENT_DONE | SDE_ENCODER_FRAME_EVENT_ERROR | SDE_ENCODER_FRAME_EVENT_PANEL_DEAD)) { - if (ready_phys->connector) - topology = sde_connector_get_topology_name( - ready_phys->connector); + + if (!sde_enc->frame_busy_mask[0]) { + /** + * suppress frame_done without waiter, + * likely autorefresh + */ + SDE_EVT32(DRMID(drm_enc), event, ready_phys->intf_idx); + return; + } /* One of the physical encoders has become idle */ for (i = 0; i < sde_enc->num_phys_encs; i++) { - if ((sde_enc->phys_encs[i] == ready_phys) || - (event & SDE_ENCODER_FRAME_EVENT_ERROR)) { + if (sde_enc->phys_encs[i] == ready_phys) { + clear_bit(i, sde_enc->frame_busy_mask); SDE_EVT32_VERBOSE(DRMID(drm_enc), i, - atomic_read( - &sde_enc->frame_done_cnt[i])); - if (!atomic_add_unless( - &sde_enc->frame_done_cnt[i], 1, 1)) { - SDE_EVT32(DRMID(drm_enc), event, - ready_phys->intf_idx, - SDE_EVTLOG_ERROR); - SDE_ERROR_ENC(sde_enc, - "intf idx:%d, event:%d\n", - ready_phys->intf_idx, event); - return; - } + sde_enc->frame_busy_mask[0]); } - - if (topology != SDE_RM_TOPOLOGY_PPSPLIT && - atomic_read(&sde_enc->frame_done_cnt[i]) != 1) - trigger = false; } - if (trigger) { + if (!sde_enc->frame_busy_mask[0]) { sde_encoder_resource_control(drm_enc, SDE_ENC_RC_EVENT_FRAME_DONE); @@ -3706,8 +3704,6 @@ static void sde_encoder_frame_done_callback( sde_enc->crtc_frame_event_cb( &sde_enc->crtc_frame_event_cb_data, event); - for (i = 0; i < sde_enc->num_phys_encs; i++) - atomic_set(&sde_enc->frame_done_cnt[i], 0); } } else { if (sde_enc->crtc_frame_event_cb) @@ -4019,6 +4015,14 @@ static void _sde_encoder_kickoff_phys(struct sde_encoder_virt *sde_enc) if (phys->connector) topology = sde_connector_get_topology_name( phys->connector); + /* + * don't wait on ppsplit slaves or skipped encoders because + * they dont receive irqs + */ + if (!(topology == SDE_RM_TOPOLOGY_PPSPLIT && + phys->split_role == ENC_ROLE_SLAVE) && + phys->split_role != ENC_ROLE_SKIP) + set_bit(i, sde_enc->frame_busy_mask); if (!phys->ops.needs_single_flush || !phys->ops.needs_single_flush(phys)) { @@ -5483,8 +5487,6 @@ struct drm_encoder *sde_encoder_init_with_ops( sde_enc->cur_master = NULL; spin_lock_init(&sde_enc->enc_spinlock); mutex_init(&sde_enc->vblank_ctl_lock); - for (i = 0; i < MAX_PHYS_ENCODERS_PER_VIRTUAL; i++) - atomic_set(&sde_enc->frame_done_cnt[i], 0); drm_enc = &sde_enc->base; drm_encoder_init(dev, drm_enc, &sde_encoder_funcs, drm_enc_mode, NULL); drm_encoder_helper_add(drm_enc, &sde_encoder_helper_funcs); From 7bb103a6eb57602eed2878c5774eb47b5700cff4 Mon Sep 17 00:00:00 2001 From: Naveen Yadav Date: Mon, 13 Jul 2020 17:09:56 +0530 Subject: [PATCH 312/592] clk: qcom: npucc: Update NPU Q6 frequency for ATOLL As per the hardware recommendation update the q6 PLL to use double the frequency and use the RCG pre divider. Change-Id: Ic9ebafa881046d8b0155674fe97ae63a5598e466 Signed-off-by: Naveen Yadav --- drivers/clk/qcom/npucc-atoll.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/clk/qcom/npucc-atoll.c b/drivers/clk/qcom/npucc-atoll.c index b2be104de7f6..a58d96d0c017 100644 --- a/drivers/clk/qcom/npucc-atoll.c +++ b/drivers/clk/qcom/npucc-atoll.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -357,13 +357,13 @@ static struct clk_rcg2 npu_cc_core_clk_src = { }; static const struct freq_tbl ftbl_npu_dsp_core_clk_src[] = { - F(250000000, P_NPU_Q6SS_PLL_OUT_MAIN, 1, 0, 0), - F(300000000, P_NPU_Q6SS_PLL_OUT_MAIN, 1, 0, 0), - F(400000000, P_NPU_Q6SS_PLL_OUT_MAIN, 1, 0, 0), - F(500000000, P_NPU_Q6SS_PLL_OUT_MAIN, 1, 0, 0), - F(600000000, P_NPU_Q6SS_PLL_OUT_MAIN, 1, 0, 0), - F(660000000, P_NPU_Q6SS_PLL_OUT_MAIN, 1, 0, 0), - F(800000000, P_NPU_Q6SS_PLL_OUT_MAIN, 1, 0, 0), + F(250000000, P_NPU_Q6SS_PLL_OUT_MAIN, 2, 0, 0), + F(300000000, P_NPU_Q6SS_PLL_OUT_MAIN, 2, 0, 0), + F(400000000, P_NPU_Q6SS_PLL_OUT_MAIN, 2, 0, 0), + F(500000000, P_NPU_Q6SS_PLL_OUT_MAIN, 2, 0, 0), + F(600000000, P_NPU_Q6SS_PLL_OUT_MAIN, 2, 0, 0), + F(660000000, P_NPU_Q6SS_PLL_OUT_MAIN, 2, 0, 0), + F(800000000, P_NPU_Q6SS_PLL_OUT_MAIN, 2, 0, 0), { } }; From 0758e6afed40d50fb81956db1d49512c8bed488e Mon Sep 17 00:00:00 2001 From: Bhasker Reddy Komatireddy Date: Thu, 23 Jul 2020 18:04:21 +0530 Subject: [PATCH 313/592] Revert "ARM: dts: msm: add display related dt nodes on QCS410 device" This reverts commit fe6253da0606f2394205b4445073bdfa919080f8. Change-Id: Ib9b6dec4451116c4ca3a54d7650ba8d819727c28 Signed-off-by: Bhasker Reddy Komatireddy --- arch/arm64/boot/dts/qcom/qcs410-iot.dtsi | 127 ----------------------- 1 file changed, 127 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/qcs410-iot.dtsi b/arch/arm64/boot/dts/qcom/qcs410-iot.dtsi index 078a863d63d6..374d1f73eff9 100644 --- a/arch/arm64/boot/dts/qcom/qcs410-iot.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs410-iot.dtsi @@ -19,8 +19,6 @@ #include #include #include -#include "sm6150-sde-pll.dtsi" -#include "sm6150-sde-display.dtsi" #include "qcs610-camera-sensor-idp.dtsi" / { @@ -33,10 +31,6 @@ #include "smb1390.dtsi" }; -&fsa4480 { - status = "disabled"; -}; - &qupv3_se0_2uart { status = "ok"; }; @@ -248,124 +242,3 @@ &L5C { regulator-max-microvolt = <2912000>; }; - -&sde_dp { - status="disabled"; -}; - -&mdss_dp_pll { - status="disabled"; -}; - -&mdss_mdp { - connectors = <&sde_rscc &sde_wb &sde_dsi>; -}; - -&qupv3_se1_i2c { - status = "ok"; - lt9611: lt,lt9611@3b { - compatible = "lt,lt9611"; - reg = <0x3b>; - interrupt-parent = <&tlmm>; - interrupts = <26 0>; - interrupt-names = "lt_irq"; - lt,irq-gpio = <&tlmm 26 0x0>; - lt,reset-gpio = <&tlmm 20 0x0>; - lt,hdmi-en-gpio = <&tlmm 79 0x0>; - instance_id = <0>; - lt,non-pluggable; - lt,preferred-mode = "1920x1080"; - - pinctrl-names = "default"; - pinctrl-0 = <<9611_pins>; - - vdd-supply = <&pm6150_l13>; - vcc-supply = <&pm6150_l16>; - - lt,supply-entries { - #address-cells = <1>; - #size-cells = <0>; - - lt,supply-entry@0 { - reg = <0>; - lt,supply-name = "vdd"; - lt,supply-min-voltage = <1800000>; - lt,supply-max-voltage = <1800000>; - lt,supply-enable-load = <200000>; - lt,supply-post-on-sleep = <50>; - }; - lt,supply-entry@1 { - reg = <1>; - lt,supply-name = "vcc"; - lt,supply-min-voltage = <3304000>; - lt,supply-max-voltage = <3304000>; - lt,supply-enable-load = <200000>; - lt,supply-post-on-sleep = <50>; - }; - - - }; - - lt,customize-modes { - lt,customize-mode-id@0 { - lt,mode-h-active = <1920>; - lt,mode-h-front-porch = <88>; - lt,mode-h-pulse-width = <44>; - lt,mode-h-back-porch = <148>; - lt,mode-h-active-high; - lt,mode-v-active = <1080>; - lt,mode-v-front-porch = <4>; - lt,mode-v-pulse-width = <5>; - lt,mode-v-back-porch = <36>; - lt,mode-v-active-high; - lt,mode-refresh-rate = <60>; - lt,mode-clock-in-khz = <148500>; - }; - }; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - lt9611_in: endpoint { - remote-endpoint = <&ext_dsi_out>; - }; - }; - }; - }; -}; - -&dsi_ext_bridge_hdmi_1080p { - qcom,mdss-dsi-ext-bridge = <0>; -}; - -&soc { - ext_dsi_bridge_display: qcom,dsi-display@50 { - label = "ext_dsi_bridge_display hdmi 1080p"; - qcom,dsi-display-active; - qcom,display-type = "primary"; - - qcom,dsi-ctrl-num = <0>; - qcom,dsi-phy-num = <0>; - qcom,dsi-select-clocks = "mux_byte_clk0", "mux_pixel_clk0"; - qcom,dsi-panel = <&dsi_ext_bridge_hdmi_1080p>; - }; -}; - -&sde_dsi { - qcom,dsi-display-list = <&ext_dsi_bridge_display>; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - ext_dsi_out: endpoint { - remote-endpoint = <<9611_in>; - }; - }; - }; -}; From 4604b6ec7851b7a89c2e04c47a2122123c6fd924 Mon Sep 17 00:00:00 2001 From: Ajay Agarwal Date: Wed, 29 Jul 2020 16:48:20 +0530 Subject: [PATCH 314/592] usb: gadget: f_ipc: Wait for req completion only when suspended 'Commit ab5cf70b3dc8 ("usb: gadget: f_ipc: Add support of sideband notifier call chain")' added support for case where the IPC message is queued onto the bus by the device and the host suspends the bus after that. The device is expected to wait for the host to resume and complete this pending transfer. For that, the driver currently re-initializes the write_done completion and waits for the transfer to complete if the online flag is false. But this flag is false also as a part of composition switch or cable disconnect when _disable will be called. Consider the case of device reboot where qrtr is waiting for ipc_write to return so that it can release its lock and honor other services. Because of the mentioned commit, ipc_write never returns and these services are not able to end gracefully. Fix this by waiting for completion only if the _suspend has been called. Change-Id: I77dc2c0d4a5eb9642d11081636e1ba3817402c01 Signed-off-by: Ajay Agarwal --- drivers/usb/gadget/function/f_ipc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/function/f_ipc.c b/drivers/usb/gadget/function/f_ipc.c index f77991cd1f80..22adf6d92cec 100644 --- a/drivers/usb/gadget/function/f_ipc.c +++ b/drivers/usb/gadget/function/f_ipc.c @@ -297,7 +297,7 @@ retry_write_done: /* Notify the GPIO driver to wakeup the host and reintialize the * completion structure. */ - } else if (!ipc_dev->online) { + } else if (ipc_dev->connected && !ipc_dev->online) { sb_notifier_call_chain(EVT_WAKE_UP, NULL); reinit_completion(&ipc_dev->write_done); goto retry_write_done; From 588da3ddacb1ed43066adb6d444fd45c15dac3fe Mon Sep 17 00:00:00 2001 From: Lakshmi Pola Date: Tue, 21 Jul 2020 11:40:52 +0530 Subject: [PATCH 315/592] ARM: dts: msm: Enable slimbus slave for SDMw429 Add DT entry for Slimbus slave for WCN3990. Change-Id: I9c28ef08bd4e8caec673ba80335047d6c57927ae Signed-off-by: Lakshmi Pola --- arch/arm64/boot/dts/qcom/sdm429.dtsi | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/sdm429.dtsi b/arch/arm64/boot/dts/qcom/sdm429.dtsi index 31218880dc07..92bc1710583a 100644 --- a/arch/arm64/boot/dts/qcom/sdm429.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm429.dtsi @@ -1315,7 +1315,15 @@ interrupt-names = "slimbus_irq", "slimbus_bam_irq"; qcom,apps-ch-pipes = <0x600000>; qcom,ea-pc = <0x230>; - status = "disabled"; + status = "okay"; + + /* Slimbus Slave DT for WCN3980 */ + btfmslim_codec: wcn3990 { + compatible = "qcom,btfmslim_slave"; + elemental-addr = [00 01 20 02 17 02]; + qcom,btfm-slim-ifd = "btfmslim_slave_ifd"; + qcom,btfm-slim-ifd-elemental-addr = [00 00 20 02 17 02]; + }; }; }; From 1746b8bc7751ee6fd0c27024f5205e100d369cb3 Mon Sep 17 00:00:00 2001 From: Ajay Agarwal Date: Thu, 30 Jul 2020 15:51:29 +0530 Subject: [PATCH 316/592] usb: gadget: f_ipc: Increase max packet size to 24k The IPC packet size requirement has increased in order to support maximum GNSS SV measurements. Increase the max packet size to 24k for the same. Change-Id: I9e4f6d73f132d271125862e42f0a4f369f65fc7f Signed-off-by: Ajay Agarwal --- drivers/usb/gadget/function/f_ipc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/function/f_ipc.c b/drivers/usb/gadget/function/f_ipc.c index f77991cd1f80..6ad1e0b78dce 100644 --- a/drivers/usb/gadget/function/f_ipc.c +++ b/drivers/usb/gadget/function/f_ipc.c @@ -25,8 +25,8 @@ #define MAX_INST_NAME_LEN 40 -#define IPC_BRIDGE_MAX_READ_SZ (8 * 1024) -#define IPC_BRIDGE_MAX_WRITE_SZ (8 * 1024) +#define IPC_BRIDGE_MAX_READ_SZ (24 * 1024) +#define IPC_BRIDGE_MAX_WRITE_SZ (24 * 1024) #define IPC_WRITE_WAIT_TIMEOUT 10000 From 233b075ea27d1e0d1c49513a8a95051c8a13f6b2 Mon Sep 17 00:00:00 2001 From: Rahul Sharma Date: Tue, 14 Jul 2020 22:14:12 +0530 Subject: [PATCH 317/592] ARM: dts: msm: Add virtual display connector for sa8195 This change adds virtual display connector for card 0 in MSM lease configuration which is required for virtual display support. Change-Id: I39559121d6fdecee9f88fab7da96592759903790 Acked-by: Santosh Ramani Signed-off-by: Rahul Sharma --- arch/arm64/boot/dts/qcom/sa8195p-adp-star-display.dtsi | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/sa8195p-adp-star-display.dtsi b/arch/arm64/boot/dts/qcom/sa8195p-adp-star-display.dtsi index 36ffa616fecd..b75b2f8a5156 100644 --- a/arch/arm64/boot/dts/qcom/sa8195p-adp-star-display.dtsi +++ b/arch/arm64/boot/dts/qcom/sa8195p-adp-star-display.dtsi @@ -432,7 +432,8 @@ compatible = "qcom,sde-kms-lease"; qcom,dev-name = "msm_drm"; qcom,lease-connectors = "DSI-2", "shared-disp-0", - "DP-1", "DP-2", "DP-3", "DP-4", "DP-5"; + "DP-1", "DP-2", "DP-3", "DP-4", "DP-5", + "Virtual-1"; qcom,lease-planes = "plane-0", "plane-1", "plane-2", "plane-3","plane-4", "plane-5", "plane-6","plane-7", "plane-8", From 76b7ef6f50c11a8893bcd4e6a093b672596ee9a0 Mon Sep 17 00:00:00 2001 From: Rahul Sharma Date: Fri, 26 Jun 2020 11:43:16 +0530 Subject: [PATCH 318/592] ARM: dts: msm: Add virtual display connector for sa6155 This change adds virtual display connector for card 0 in MSM lease configuration which is required for virtual display support. Change-Id: I8f1da29377da3afa2df12afc056fe1a50e4536be Acked-by: Santosh Ramani Signed-off-by: Rahul Sharma --- arch/arm64/boot/dts/qcom/sa6155-display.dtsi | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/sa6155-display.dtsi b/arch/arm64/boot/dts/qcom/sa6155-display.dtsi index 137d946a946d..41c5448b182c 100644 --- a/arch/arm64/boot/dts/qcom/sa6155-display.dtsi +++ b/arch/arm64/boot/dts/qcom/sa6155-display.dtsi @@ -313,7 +313,8 @@ sde_card1: qcom,sde-kms-lease@0 { compatible = "qcom,sde-kms-lease"; qcom,dev-name = "msm_drm"; - qcom,lease-connectors = "shared-disp-0","DP-1","DP-2","DP-3"; + qcom,lease-connectors = "shared-disp-0","DP-1","DP-2","DP-3", + "Virtual-1"; qcom,lease-planes = "plane-0","plane-1","plane-2","plane-3", "plane-4", "plane-5", "plane-6", "plane-7","plane-8","plane-9"; From 727a7916dd894dc0d168066c758aaea5814d50f2 Mon Sep 17 00:00:00 2001 From: Rahul Sharma Date: Tue, 14 Jul 2020 21:50:29 +0530 Subject: [PATCH 319/592] ARM: dts: msm: Add virtual display connector for sa8155 This change adds virtual display connector for card 0 in MSM lease configuration which is required for virtual display support. Change-Id: Ice9e611804706d484d15badfd79c605cd6363a0f Acked-by: Santosh Ramani Signed-off-by: Rahul Sharma --- arch/arm64/boot/dts/qcom/sa8155-adp-star-display.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/sa8155-adp-star-display.dtsi b/arch/arm64/boot/dts/qcom/sa8155-adp-star-display.dtsi index 925a9c239c57..f9e38514f732 100644 --- a/arch/arm64/boot/dts/qcom/sa8155-adp-star-display.dtsi +++ b/arch/arm64/boot/dts/qcom/sa8155-adp-star-display.dtsi @@ -397,7 +397,7 @@ compatible = "qcom,sde-kms-lease"; qcom,dev-name = "msm_drm"; qcom,lease-connectors = "DSI-2", "shared-disp-0", - "DP-1", "DP-2", "DP-3"; + "DP-1", "DP-2", "DP-3", "Virtual-1"; qcom,lease-planes = "plane-0", "plane-1", "plane-2", "plane-3","plane-4", "plane-5", "plane-6","plane-7", "plane-8", From d8626274dd80ec66d50c1d92c7429bf3b7b41483 Mon Sep 17 00:00:00 2001 From: Manaf Meethalavalappu Pallikunhi Date: Thu, 30 Jul 2020 18:20:46 +0530 Subject: [PATCH 320/592] ARM: dts: msm: fix cx_cdev label size for SDM429W Reduce the size of the node for cx-cdev to fix regulator name with size limit for SDM429W. Change-Id: I893b7fc5c36950ec8f82ad5e87f3209122db17df Signed-off-by: Manaf Meethalavalappu Pallikunhi --- arch/arm64/boot/dts/qcom/sdm429w-regulator.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/sdm429w-regulator.dtsi b/arch/arm64/boot/dts/qcom/sdm429w-regulator.dtsi index e3c95e217f21..8d154467c1ec 100644 --- a/arch/arm64/boot/dts/qcom/sdm429w-regulator.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm429w-regulator.dtsi @@ -56,7 +56,7 @@ qcom,use-voltage-level; }; - pm660_cx_cdev: regulator-cx-cdev { + pm660_cx_cdev: cx { compatible = "qcom,regulator-cooling-device"; regulator-cdev-supply = <&pm660_s1_floor_level>; regulator-levels = Date: Wed, 14 Mar 2018 17:00:22 +0530 Subject: [PATCH 321/592] drivers: qti-virtual-sensor: Add hexa cpu max virtual sensor for SDM429 Update MAX mode virtual sensors list with hexa core sensors for SDM429. It enables thermal zone devicetree rule to use this sensor for cpu mitigation. Change-Id: If67d7af942398d13922a03ae2bf4178484537f96 Signed-off-by: Manaf Meethalavalappu Pallikunhi --- drivers/thermal/qcom/qti_virtual_sensor.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/thermal/qcom/qti_virtual_sensor.c b/drivers/thermal/qcom/qti_virtual_sensor.c index 46bfd0d5c2d2..e27c9712ca1d 100644 --- a/drivers/thermal/qcom/qti_virtual_sensor.c +++ b/drivers/thermal/qcom/qti_virtual_sensor.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -181,6 +181,17 @@ static const struct virtual_sensor_data qti_virtual_sensors[] = { "gpuss-3-usr"}, .logic = VIRT_MAXIMUM, }, + { + .virt_zone_name = "hexa-cpu-max-step", + .num_sensors = 6, + .sensor_names = {"apc1-cpu0-usr", + "apc1-cpu1-usr", + "apc1-cpu2-usr", + "apc1-cpu3-usr", + "cpuss0-usr", + "cpuss1-usr"}, + .logic = VIRT_MAXIMUM, + }, }; int qti_virtual_sensor_register(struct device *dev) From 98f848ff5830ca4afc62dca6d1d8b5c938c9df5c Mon Sep 17 00:00:00 2001 From: Manohar Vavilapalli Date: Thu, 30 Jul 2020 22:47:26 +0530 Subject: [PATCH 322/592] ARM: dts: msm: Add correct board name for SDX55 MTP Telematics AU DSDA Change the incorrect model name and board name for MTP Telematics AU DSDA. Change-Id: Icbff92066b8d98887652e65c47f583b69d737d63 Signed-off-by: Manohar Vavilapalli --- Documentation/devicetree/bindings/arm/msm/msm.txt | 1 - arch/arm64/boot/dts/qcom/Makefile | 2 +- ...prairie-v2-ttp-cpe.dts => sdxprairie-v2-mtp-au-dsda.dts} | 6 +++--- 3 files changed, 4 insertions(+), 5 deletions(-) rename arch/arm64/boot/dts/qcom/{sdxprairie-v2-ttp-cpe.dts => sdxprairie-v2-mtp-au-dsda.dts} (82%) diff --git a/Documentation/devicetree/bindings/arm/msm/msm.txt b/Documentation/devicetree/bindings/arm/msm/msm.txt index 5b614f215d22..b58a1eb312ee 100644 --- a/Documentation/devicetree/bindings/arm/msm/msm.txt +++ b/Documentation/devicetree/bindings/arm/msm/msm.txt @@ -255,7 +255,6 @@ compatible = "qcom,sa8155p-adp-alcor" compatible = "qcom,sdxprairie-rumi" compatible = "qcom,sdxprairie-mtp" compatible = "qcom,sdxprairie-cdp" -compatible = "qcom,sdxprairie-ttp" compatible = "qcom,sa515m-ccard" compatible = "qcom,sa515m-ttp" compatible = "qcom,sdmmagpie-rumi" diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 694f2cd805f2..86523cc11354 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -444,7 +444,7 @@ dtb-$(CONFIG_ARCH_SDXPRAIRIE) += sdxprairie-rumi.dtb \ sdxprairie-v2-mtp-v1.1-cpe.dtb \ sdxprairie-v2-mtp-v1.1.dtb \ sdxprairie-v2-mtp-le-cpe.dtb \ - sdxprairie-v2-ttp-cpe.dtb \ + sdxprairie-v2-mtp-au-dsda.dtb \ sa515m-v2-ttp.dtb \ sa515m-v2-ttp-usb-ep.dtb \ sa515m-v2-ttp-pcie-ep.dtb \ diff --git a/arch/arm64/boot/dts/qcom/sdxprairie-v2-ttp-cpe.dts b/arch/arm64/boot/dts/qcom/sdxprairie-v2-mtp-au-dsda.dts similarity index 82% rename from arch/arm64/boot/dts/qcom/sdxprairie-v2-ttp-cpe.dts rename to arch/arm64/boot/dts/qcom/sdxprairie-v2-mtp-au-dsda.dts index e8c478d1593b..b81e0dd144ed 100644 --- a/arch/arm64/boot/dts/qcom/sdxprairie-v2-ttp-cpe.dts +++ b/arch/arm64/boot/dts/qcom/sdxprairie-v2-mtp-au-dsda.dts @@ -15,9 +15,9 @@ #include "sdxprairie-v2-mtp-cpe.dtsi" / { - model = "Qualcomm Technologies, Inc. SDXPRAIRIE V2 TTP (CPE)"; - compatible = "qcom,sdxprairie-ttp", - "qcom,sdxprairie", "qcom,ttp"; + model = "Qualcomm Technologies, Inc. SDXPRAIRIE V2 AU DSDA"; + compatible = "qcom,sdxprairie-mtp", + "qcom,sdxprairie", "qcom,mtp"; qcom,board-id = <0x08010008 0x0>; }; From 0dec508fff62b9812b8bacd36a21788c24d5ef1a Mon Sep 17 00:00:00 2001 From: Bhaumik Bhatt Date: Thu, 16 Jul 2020 14:28:24 -0700 Subject: [PATCH 323/592] mhi: cntrl: qcom: Update the fw image name for new devices Newer devices need to load xbl.elf over BHI instead of the older filename sbl1.mbn. Make the appropriate filename change in the firmware info table. Change-Id: If5a455469c38a9134f610bcd39e5028cc9dbb6b4 Signed-off-by: Bhaumik Bhatt --- drivers/bus/mhi/controllers/mhi_qcom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/bus/mhi/controllers/mhi_qcom.c b/drivers/bus/mhi/controllers/mhi_qcom.c index 26811368e6c3..e0154b549b4f 100644 --- a/drivers/bus/mhi/controllers/mhi_qcom.c +++ b/drivers/bus/mhi/controllers/mhi_qcom.c @@ -33,7 +33,7 @@ struct firmware_info { }; static const struct firmware_info firmware_table[] = { - {.dev_id = 0x308, .fw_image = "sdx65m/sbl1.mbn", + {.dev_id = 0x308, .fw_image = "sdx65m/xbl.elf", .edl_image = "sdx65m/edl.mbn"}, {.dev_id = 0x307, .fw_image = "sdx60m/sbl1.mbn", .edl_image = "sdx60m/edl.mbn"}, From 8000044af5c50f9f7ae3b1c69a72b44aa80abc60 Mon Sep 17 00:00:00 2001 From: Sanjay Dwivedi Date: Thu, 30 Jul 2020 14:16:47 +0530 Subject: [PATCH 324/592] defconfig: sa2150p: Remove unwanted debug configs Debug configs are removed from sa2150p defconfig to optimize memory consumption and kpi improvement of non-perf build. Change-Id: I17d3a6088969b934a9196b9ac6cc7455fdf2e9b7 Signed-off-by: Sanjay Dwivedi --- .../configs/vendor/sa2150p-nand_defconfig | 51 +------------------ arch/arm64/configs/vendor/sa2150p_defconfig | 51 +------------------ 2 files changed, 4 insertions(+), 98 deletions(-) diff --git a/arch/arm64/configs/vendor/sa2150p-nand_defconfig b/arch/arm64/configs/vendor/sa2150p-nand_defconfig index 1f8ddc2423f6..e35d9fe9cf9c 100644 --- a/arch/arm64/configs/vendor/sa2150p-nand_defconfig +++ b/arch/arm64/configs/vendor/sa2150p-nand_defconfig @@ -6,7 +6,6 @@ CONFIG_HIGH_RES_TIMERS=y CONFIG_IRQ_TIME_ACCOUNTING=y CONFIG_SCHED_WALT=y CONFIG_TASKSTATS=y -CONFIG_TASK_DELAY_ACCT=y CONFIG_TASK_XACCT=y CONFIG_TASK_IO_ACCOUNTING=y CONFIG_RCU_EXPERT=y @@ -20,7 +19,6 @@ CONFIG_RT_GROUP_SCHED=y CONFIG_CGROUP_FREEZER=y CONFIG_CPUSETS=y CONFIG_CGROUP_CPUACCT=y -CONFIG_CGROUP_DEBUG=y CONFIG_NAMESPACES=y # CONFIG_UTS_NS is not set # CONFIG_PID_NS is not set @@ -47,9 +45,7 @@ CONFIG_PCI_MSM=y CONFIG_PCI_MSM_MSI=y CONFIG_NR_CPUS=4 CONFIG_PREEMPT=y -CONFIG_CLEANCACHE=y CONFIG_CMA=y -CONFIG_CMA_DEBUGFS=y CONFIG_ZSMALLOC=y CONFIG_SECCOMP=y # CONFIG_HARDEN_BRANCH_PREDICTOR is not set @@ -66,7 +62,6 @@ CONFIG_PM_AUTOSLEEP=y CONFIG_PM_WAKELOCKS=y CONFIG_PM_WAKELOCKS_LIMIT=0 # CONFIG_PM_WAKELOCKS_GC is not set -CONFIG_PM_DEBUG=y CONFIG_CPU_IDLE=y CONFIG_ARM_CPUIDLE=y CONFIG_CPU_FREQ=y @@ -187,7 +182,6 @@ CONFIG_BRIDGE_EBT_ARPREPLY=y CONFIG_BRIDGE_EBT_DNAT=y CONFIG_BRIDGE_EBT_SNAT=y CONFIG_L2TP=y -CONFIG_L2TP_DEBUGFS=y CONFIG_L2TP_V3=y CONFIG_L2TP_IP=y CONFIG_L2TP_ETH=y @@ -282,11 +276,9 @@ CONFIG_I2C_CHARDEV=y CONFIG_I2C_MUX=y CONFIG_I2C_MSM_V2=y CONFIG_SPI=y -CONFIG_SPI_DEBUG=y CONFIG_SPI_QUP=y CONFIG_SPI_SPIDEV=y CONFIG_SPMI=y -CONFIG_SPMI_MSM_PMIC_ARB_DEBUG=y CONFIG_SLIMBUS=y CONFIG_SLIMBUS_MSM_NGD=y CONFIG_PPS_CLIENT_GPIO=y @@ -321,7 +313,6 @@ CONFIG_REGULATOR_SPM=y CONFIG_REGULATOR_STUB=y # CONFIG_RC_CORE is not set # CONFIG_VGA_ARB is not set -# CONFIG_DSI_PARSER is not set CONFIG_SOUND=y CONFIG_SND=y CONFIG_SND_DYNAMIC_MINORS=y @@ -347,8 +338,6 @@ CONFIG_USB_MSM_SSPHY=y CONFIG_USB_QCOM_EMU_PHY=y CONFIG_DUAL_ROLE_USB_INTF=y CONFIG_USB_GADGET=y -CONFIG_USB_GADGET_DEBUG_FILES=y -CONFIG_USB_GADGET_DEBUG_FS=y CONFIG_USB_GADGET_VBUS_DRAW=900 CONFIG_USB_CONFIGFS=y CONFIG_USB_CONFIGFS_F_FS=y @@ -358,7 +347,6 @@ CONFIG_MMC_PERF_PROFILING=y CONFIG_MMC_BLOCK_MINORS=32 CONFIG_MMC_BLOCK_DEFERRED_RESUME=y CONFIG_MMC_TEST=m -CONFIG_MMC_RING_BUFFER=y CONFIG_MMC_PARANOID_SD_INIT=y CONFIG_MMC_CLKGATE=y CONFIG_MMC_SDHCI=y @@ -395,12 +383,10 @@ CONFIG_ARM_SMMU=y CONFIG_QCOM_LAZY_MAPPING=y CONFIG_IOMMU_DEBUG=y CONFIG_IOMMU_DEBUG_TRACKING=y -CONFIG_IOMMU_TESTS=y CONFIG_RPMSG_CHAR=y CONFIG_RPMSG_QCOM_GLINK_RPM=y CONFIG_RPMSG_QCOM_GLINK_SMEM=y CONFIG_MSM_RPM_SMD=y -CONFIG_QCOM_CPUSS_DUMP=y CONFIG_QCOM_QMI_HELPERS=y CONFIG_QCOM_SMEM=y CONFIG_QCOM_SMD_RPM=y @@ -408,7 +394,6 @@ CONFIG_MSM_SPM=y CONFIG_MSM_L2_SPM=y CONFIG_QCOM_SCM=y CONFIG_QCOM_MEMORY_DUMP_V2=y -CONFIG_MSM_DEBUG_LAR_UNLOCK=y CONFIG_QCOM_WATCHDOG_V2=y CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y CONFIG_QCOM_WDOG_IPI_ENABLE=y @@ -421,7 +406,6 @@ CONFIG_MSM_SYSMON_QMI_COMM=y CONFIG_MSM_PIL_SSR_GENERIC=y CONFIG_MSM_BOOT_STATS=y CONFIG_MSM_BOOT_TIME_MARKER=y -CONFIG_MSM_CORE_HANG_DETECT=y CONFIG_QCOM_DCC_V2=y CONFIG_SDX_EXT_IPC=y CONFIG_QTI_NOTIFY_SIDEBAND=y @@ -429,6 +413,7 @@ CONFIG_QCOM_BUS_SCALING=y CONFIG_MSM_TZ_SMMU=y CONFIG_QCOM_GLINK=y CONFIG_QCOM_GLINK_PKT=y +CONFIG_MSM_JTAGV8=y CONFIG_QTI_RPM_STATS_LOG=y CONFIG_MSM_CDSP_LOADER=y CONFIG_QCOM_SMCINVOKE=y @@ -458,7 +443,6 @@ CONFIG_QUOTA_NETLINK_INTERFACE=y # CONFIG_PRINT_QUOTA_WARNING is not set CONFIG_QFMT_V2=y CONFIG_FUSE_FS=y -CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y CONFIG_TMPFS=y CONFIG_TMPFS_POSIX_ACL=y @@ -474,49 +458,19 @@ CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ASCII=y CONFIG_NLS_ISO8859_1=y CONFIG_PRINTK_TIME=y -CONFIG_DYNAMIC_DEBUG=y CONFIG_DEBUG_INFO=y CONFIG_PAGE_OWNER=y CONFIG_MAGIC_SYSRQ=y -CONFIG_DEBUG_PAGEALLOC=y -CONFIG_SLUB_DEBUG_PANIC_ON=y -CONFIG_DEBUG_PAGEALLOC_ENABLE_DEFAULT=y CONFIG_PAGE_POISONING=y CONFIG_PAGE_POISONING_ENABLE_DEFAULT=y -CONFIG_DEBUG_OBJECTS=y -CONFIG_DEBUG_OBJECTS_FREE=y -CONFIG_DEBUG_OBJECTS_TIMERS=y -CONFIG_DEBUG_OBJECTS_WORK=y -CONFIG_DEBUG_OBJECTS_RCU_HEAD=y -CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y -CONFIG_SLUB_DEBUG_ON=y -CONFIG_DEBUG_KMEMLEAK=y -CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=4000 -CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y -CONFIG_DEBUG_STACK_USAGE=y -CONFIG_DEBUG_MEMORY_INIT=y CONFIG_PANIC_ON_RECURSIVE_FAULT=y CONFIG_PANIC_ON_OOPS=y CONFIG_PANIC_TIMEOUT=5 CONFIG_SCHEDSTATS=y -CONFIG_SCHED_STACK_END_CHECK=y -CONFIG_DEBUG_SPINLOCK=y -CONFIG_DEBUG_MUTEXES=y -CONFIG_DEBUG_ATOMIC_SLEEP=y -CONFIG_FAULT_INJECTION=y -CONFIG_FAIL_PAGE_ALLOC=y -CONFIG_UFS_FAULT_INJECTION=y -CONFIG_FAULT_INJECTION_DEBUG_FS=y -CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y CONFIG_IPC_LOGGING=y -CONFIG_QCOM_RTB=y -CONFIG_QCOM_RTB_SEPARATE_CPUS=y -CONFIG_BLK_DEV_IO_TRACE=y -CONFIG_LKDTM=y CONFIG_BUG_ON_DATA_CORRUPTION=y CONFIG_CORESIGHT=y CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y -CONFIG_CORESIGHT_SOURCE_ETM4X=y CONFIG_CORESIGHT_DYNAMIC_REPLICATOR=y CONFIG_CORESIGHT_STM=y CONFIG_CORESIGHT_CTI=y @@ -524,8 +478,6 @@ CONFIG_CORESIGHT_TPDA=y CONFIG_CORESIGHT_TPDM=y CONFIG_CORESIGHT_HWEVENT=y CONFIG_CORESIGHT_DUMMY=y -CONFIG_CORESIGHT_REMOTE_ETM=y -CONFIG_CORESIGHT_REMOTE_ETM_DEFAULT_ENABLE=0 CONFIG_CORESIGHT_EVENT=y CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y CONFIG_SECURITY=y @@ -543,3 +495,4 @@ CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y CONFIG_CRYPTO_DEV_QCRYPTO=y CONFIG_CRYPTO_DEV_QCEDEV=y CONFIG_CRYPTO_DEV_QCOM_ICE=y +CONFIG_STACK_HASH_ORDER_SHIFT=12 diff --git a/arch/arm64/configs/vendor/sa2150p_defconfig b/arch/arm64/configs/vendor/sa2150p_defconfig index 43100c444244..5a7550fc9fdf 100644 --- a/arch/arm64/configs/vendor/sa2150p_defconfig +++ b/arch/arm64/configs/vendor/sa2150p_defconfig @@ -6,7 +6,6 @@ CONFIG_HIGH_RES_TIMERS=y CONFIG_IRQ_TIME_ACCOUNTING=y CONFIG_SCHED_WALT=y CONFIG_TASKSTATS=y -CONFIG_TASK_DELAY_ACCT=y CONFIG_TASK_XACCT=y CONFIG_TASK_IO_ACCOUNTING=y CONFIG_RCU_EXPERT=y @@ -20,7 +19,6 @@ CONFIG_RT_GROUP_SCHED=y CONFIG_CGROUP_FREEZER=y CONFIG_CPUSETS=y CONFIG_CGROUP_CPUACCT=y -CONFIG_CGROUP_DEBUG=y CONFIG_NAMESPACES=y # CONFIG_UTS_NS is not set # CONFIG_PID_NS is not set @@ -47,9 +45,7 @@ CONFIG_PCI_MSM=y CONFIG_PCI_MSM_MSI=y CONFIG_NR_CPUS=4 CONFIG_PREEMPT=y -CONFIG_CLEANCACHE=y CONFIG_CMA=y -CONFIG_CMA_DEBUGFS=y CONFIG_ZSMALLOC=y CONFIG_SECCOMP=y # CONFIG_HARDEN_BRANCH_PREDICTOR is not set @@ -66,7 +62,6 @@ CONFIG_PM_AUTOSLEEP=y CONFIG_PM_WAKELOCKS=y CONFIG_PM_WAKELOCKS_LIMIT=0 # CONFIG_PM_WAKELOCKS_GC is not set -CONFIG_PM_DEBUG=y CONFIG_CPU_IDLE=y CONFIG_ARM_CPUIDLE=y CONFIG_CPU_FREQ=y @@ -187,7 +182,6 @@ CONFIG_BRIDGE_EBT_ARPREPLY=y CONFIG_BRIDGE_EBT_DNAT=y CONFIG_BRIDGE_EBT_SNAT=y CONFIG_L2TP=y -CONFIG_L2TP_DEBUGFS=y CONFIG_L2TP_V3=y CONFIG_L2TP_IP=y CONFIG_L2TP_ETH=y @@ -296,11 +290,9 @@ CONFIG_I2C_CHARDEV=y CONFIG_I2C_MUX=y CONFIG_I2C_MSM_V2=y CONFIG_SPI=y -CONFIG_SPI_DEBUG=y CONFIG_SPI_QUP=y CONFIG_SPI_SPIDEV=y CONFIG_SPMI=y -CONFIG_SPMI_MSM_PMIC_ARB_DEBUG=y CONFIG_SLIMBUS_MSM_NGD=y CONFIG_PPS_CLIENT_GPIO=y CONFIG_PINCTRL_QCS405=y @@ -333,7 +325,6 @@ CONFIG_REGULATOR_SPM=y CONFIG_REGULATOR_STUB=y # CONFIG_RC_CORE is not set # CONFIG_VGA_ARB is not set -# CONFIG_DSI_PARSER is not set CONFIG_SOUND=y CONFIG_SND=y CONFIG_SND_DYNAMIC_MINORS=y @@ -359,8 +350,6 @@ CONFIG_USB_MSM_SSPHY=y CONFIG_USB_QCOM_EMU_PHY=y CONFIG_DUAL_ROLE_USB_INTF=y CONFIG_USB_GADGET=y -CONFIG_USB_GADGET_DEBUG_FILES=y -CONFIG_USB_GADGET_DEBUG_FS=y CONFIG_USB_GADGET_VBUS_DRAW=900 CONFIG_USB_CONFIGFS=y CONFIG_USB_CONFIGFS_F_FS=y @@ -370,7 +359,6 @@ CONFIG_MMC_PERF_PROFILING=y CONFIG_MMC_BLOCK_MINORS=32 CONFIG_MMC_BLOCK_DEFERRED_RESUME=y CONFIG_MMC_TEST=m -CONFIG_MMC_RING_BUFFER=y CONFIG_MMC_PARANOID_SD_INIT=y CONFIG_MMC_CLKGATE=y CONFIG_MMC_SDHCI=y @@ -407,12 +395,10 @@ CONFIG_ARM_SMMU=y CONFIG_QCOM_LAZY_MAPPING=y CONFIG_IOMMU_DEBUG=y CONFIG_IOMMU_DEBUG_TRACKING=y -CONFIG_IOMMU_TESTS=y CONFIG_RPMSG_CHAR=y CONFIG_RPMSG_QCOM_GLINK_RPM=y CONFIG_RPMSG_QCOM_GLINK_SMEM=y CONFIG_MSM_RPM_SMD=y -CONFIG_QCOM_CPUSS_DUMP=y CONFIG_QCOM_QMI_HELPERS=y CONFIG_QCOM_SMEM=y CONFIG_QCOM_SMD_RPM=y @@ -420,7 +406,6 @@ CONFIG_MSM_SPM=y CONFIG_MSM_L2_SPM=y CONFIG_QCOM_SCM=y CONFIG_QCOM_MEMORY_DUMP_V2=y -CONFIG_MSM_DEBUG_LAR_UNLOCK=y CONFIG_QCOM_WATCHDOG_V2=y CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y CONFIG_QCOM_WDOG_IPI_ENABLE=y @@ -433,7 +418,6 @@ CONFIG_MSM_SYSMON_QMI_COMM=y CONFIG_MSM_PIL_SSR_GENERIC=y CONFIG_MSM_BOOT_STATS=y CONFIG_MSM_BOOT_TIME_MARKER=y -CONFIG_MSM_CORE_HANG_DETECT=y CONFIG_QCOM_DCC_V2=y CONFIG_SDX_EXT_IPC=y CONFIG_QTI_NOTIFY_SIDEBAND=y @@ -441,6 +425,7 @@ CONFIG_QCOM_BUS_SCALING=y CONFIG_MSM_TZ_SMMU=y CONFIG_QCOM_GLINK=y CONFIG_QCOM_GLINK_PKT=y +CONFIG_MSM_JTAGV8=y CONFIG_QTI_RPM_STATS_LOG=y CONFIG_MSM_CDSP_LOADER=y CONFIG_QCOM_SMCINVOKE=y @@ -470,7 +455,6 @@ CONFIG_QUOTA_NETLINK_INTERFACE=y # CONFIG_PRINT_QUOTA_WARNING is not set CONFIG_QFMT_V2=y CONFIG_FUSE_FS=y -CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y CONFIG_TMPFS=y CONFIG_TMPFS_POSIX_ACL=y @@ -486,49 +470,19 @@ CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ASCII=y CONFIG_NLS_ISO8859_1=y CONFIG_PRINTK_TIME=y -CONFIG_DYNAMIC_DEBUG=y CONFIG_DEBUG_INFO=y CONFIG_PAGE_OWNER=y CONFIG_MAGIC_SYSRQ=y -CONFIG_DEBUG_PAGEALLOC=y -CONFIG_SLUB_DEBUG_PANIC_ON=y -CONFIG_DEBUG_PAGEALLOC_ENABLE_DEFAULT=y CONFIG_PAGE_POISONING=y CONFIG_PAGE_POISONING_ENABLE_DEFAULT=y -CONFIG_DEBUG_OBJECTS=y -CONFIG_DEBUG_OBJECTS_FREE=y -CONFIG_DEBUG_OBJECTS_TIMERS=y -CONFIG_DEBUG_OBJECTS_WORK=y -CONFIG_DEBUG_OBJECTS_RCU_HEAD=y -CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y -CONFIG_SLUB_DEBUG_ON=y -CONFIG_DEBUG_KMEMLEAK=y -CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=4000 -CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y -CONFIG_DEBUG_STACK_USAGE=y -CONFIG_DEBUG_MEMORY_INIT=y CONFIG_PANIC_ON_RECURSIVE_FAULT=y CONFIG_PANIC_ON_OOPS=y CONFIG_PANIC_TIMEOUT=5 CONFIG_SCHEDSTATS=y -CONFIG_SCHED_STACK_END_CHECK=y -CONFIG_DEBUG_SPINLOCK=y -CONFIG_DEBUG_MUTEXES=y -CONFIG_DEBUG_ATOMIC_SLEEP=y -CONFIG_FAULT_INJECTION=y -CONFIG_FAIL_PAGE_ALLOC=y -CONFIG_UFS_FAULT_INJECTION=y -CONFIG_FAULT_INJECTION_DEBUG_FS=y -CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y CONFIG_IPC_LOGGING=y -CONFIG_QCOM_RTB=y -CONFIG_QCOM_RTB_SEPARATE_CPUS=y -CONFIG_BLK_DEV_IO_TRACE=y -CONFIG_LKDTM=y CONFIG_BUG_ON_DATA_CORRUPTION=y CONFIG_CORESIGHT=y CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y -CONFIG_CORESIGHT_SOURCE_ETM4X=y CONFIG_CORESIGHT_DYNAMIC_REPLICATOR=y CONFIG_CORESIGHT_STM=y CONFIG_CORESIGHT_CTI=y @@ -536,8 +490,6 @@ CONFIG_CORESIGHT_TPDA=y CONFIG_CORESIGHT_TPDM=y CONFIG_CORESIGHT_HWEVENT=y CONFIG_CORESIGHT_DUMMY=y -CONFIG_CORESIGHT_REMOTE_ETM=y -CONFIG_CORESIGHT_REMOTE_ETM_DEFAULT_ENABLE=0 CONFIG_CORESIGHT_EVENT=y CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y CONFIG_SECURITY=y @@ -554,3 +506,4 @@ CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y CONFIG_CRYPTO_DEV_QCRYPTO=y CONFIG_CRYPTO_DEV_QCEDEV=y CONFIG_CRYPTO_DEV_QCOM_ICE=y +CONFIG_STACK_HASH_ORDER_SHIFT=12 From 253c17d93abaca5d4a3269a72588f547b4b81339 Mon Sep 17 00:00:00 2001 From: Peilin Ye Date: Wed, 22 Jul 2020 11:19:01 -0400 Subject: [PATCH 325/592] AX.25: Fix out-of-bounds read in ax25_connect() [ Upstream commit 2f2a7ffad5c6cbf3d438e813cfdc88230e185ba6 ] Checks on `addr_len` and `fsa->fsa_ax25.sax25_ndigis` are insufficient. ax25_connect() can go out of bounds when `fsa->fsa_ax25.sax25_ndigis` equals to 7 or 8. Fix it. This issue has been reported as a KMSAN uninit-value bug, because in such a case, ax25_connect() reaches into the uninitialized portion of the `struct sockaddr_storage` statically allocated in __sys_connect(). It is safe to remove `fsa->fsa_ax25.sax25_ndigis > AX25_MAX_DIGIS` because `addr_len` is guaranteed to be less than or equal to `sizeof(struct full_sockaddr_ax25)`. Reported-by: syzbot+c82752228ed975b0a623@syzkaller.appspotmail.com Link: https://syzkaller.appspot.com/bug?id=55ef9d629f3b3d7d70b69558015b63b48d01af66 Signed-off-by: Peilin Ye Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ax25/af_ax25.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index 89d074ce10fc..cc44959cdd0b 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -1191,7 +1191,9 @@ static int __must_check ax25_connect(struct socket *sock, if (addr_len > sizeof(struct sockaddr_ax25) && fsa->fsa_ax25.sax25_ndigis != 0) { /* Valid number of digipeaters ? */ - if (fsa->fsa_ax25.sax25_ndigis < 1 || fsa->fsa_ax25.sax25_ndigis > AX25_MAX_DIGIS) { + if (fsa->fsa_ax25.sax25_ndigis < 1 || + addr_len < sizeof(struct sockaddr_ax25) + + sizeof(ax25_address) * fsa->fsa_ax25.sax25_ndigis) { err = -EINVAL; goto out_release; } From 1411bf6e5910fdb9d03ac4d4f9bfd0363bd003a5 Mon Sep 17 00:00:00 2001 From: Peilin Ye Date: Wed, 22 Jul 2020 12:05:12 -0400 Subject: [PATCH 326/592] AX.25: Prevent out-of-bounds read in ax25_sendmsg() [ Upstream commit 8885bb0621f01a6c82be60a91e5fc0f6e2f71186 ] Checks on `addr_len` and `usax->sax25_ndigis` are insufficient. ax25_sendmsg() can go out of bounds when `usax->sax25_ndigis` equals to 7 or 8. Fix it. It is safe to remove `usax->sax25_ndigis > AX25_MAX_DIGIS`, since `addr_len` is guaranteed to be less than or equal to `sizeof(struct full_sockaddr_ax25)` Signed-off-by: Peilin Ye Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ax25/af_ax25.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index cc44959cdd0b..751b6e8cfa19 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -1513,7 +1513,8 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) struct full_sockaddr_ax25 *fsa = (struct full_sockaddr_ax25 *)usax; /* Valid number of digipeaters ? */ - if (usax->sax25_ndigis < 1 || usax->sax25_ndigis > AX25_MAX_DIGIS) { + if (usax->sax25_ndigis < 1 || addr_len < sizeof(struct sockaddr_ax25) + + sizeof(ax25_address) * usax->sax25_ndigis) { err = -EINVAL; goto out; } From fbcdf3849aa1b8c5fd1009abf1b2e7b96e6a954d Mon Sep 17 00:00:00 2001 From: Subash Abhinov Kasiviswanathan Date: Thu, 23 Jul 2020 11:31:48 -0600 Subject: [PATCH 327/592] dev: Defer free of skbs in flush_backlog [ Upstream commit 7df5cb75cfb8acf96c7f2342530eb41e0c11f4c3 ] IRQs are disabled when freeing skbs in input queue. Use the IRQ safe variant to free skbs here. Fixes: 145dd5f9c88f ("net: flush the softnet backlog in process context") Signed-off-by: Subash Abhinov Kasiviswanathan Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/dev.c b/net/core/dev.c index 1ee177485fd0..7ec549e481e3 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4626,7 +4626,7 @@ static void flush_backlog(struct work_struct *work) skb_queue_walk_safe(&sd->input_pkt_queue, skb, tmp) { if (skb->dev->reg_state == NETREG_UNREGISTERING) { __skb_unlink(skb, &sd->input_pkt_queue); - kfree_skb(skb); + dev_kfree_skb_irq(skb); input_queue_head_incr(sd); } } From 237070f593b2b94aa0af7252684cf3af01f62a04 Mon Sep 17 00:00:00 2001 From: Xie He Date: Thu, 16 Jul 2020 16:44:33 -0700 Subject: [PATCH 328/592] drivers/net/wan/x25_asy: Fix to make it work [ Upstream commit 8fdcabeac39824fe67480fd9508d80161c541854 ] This driver is not working because of problems of its receiving code. This patch fixes it to make it work. When the driver receives an LAPB frame, it should first pass the frame to the LAPB module to process. After processing, the LAPB module passes the data (the packet) back to the driver, the driver should then add a one-byte pseudo header and pass the data to upper layers. The changes to the "x25_asy_bump" function and the "x25_asy_data_indication" function are to correctly implement this procedure. Also, the "x25_asy_unesc" function ignores any frame that is shorter than 3 bytes. However the shortest frames are 2-byte long. So we need to change it to allow 2-byte frames to pass. Cc: Eric Dumazet Cc: Martin Schiller Signed-off-by: Xie He Reviewed-by: Martin Schiller Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/wan/x25_asy.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c index 3eaefecd4448..229cab00c4b0 100644 --- a/drivers/net/wan/x25_asy.c +++ b/drivers/net/wan/x25_asy.c @@ -183,7 +183,7 @@ static inline void x25_asy_unlock(struct x25_asy *sl) netif_wake_queue(sl->dev); } -/* Send one completely decapsulated IP datagram to the IP layer. */ +/* Send an LAPB frame to the LAPB module to process. */ static void x25_asy_bump(struct x25_asy *sl) { @@ -195,13 +195,12 @@ static void x25_asy_bump(struct x25_asy *sl) count = sl->rcount; dev->stats.rx_bytes += count; - skb = dev_alloc_skb(count+1); + skb = dev_alloc_skb(count); if (skb == NULL) { netdev_warn(sl->dev, "memory squeeze, dropping packet\n"); dev->stats.rx_dropped++; return; } - skb_push(skb, 1); /* LAPB internal control */ skb_put_data(skb, sl->rbuff, count); skb->protocol = x25_type_trans(skb, sl->dev); err = lapb_data_received(skb->dev, skb); @@ -209,7 +208,6 @@ static void x25_asy_bump(struct x25_asy *sl) kfree_skb(skb); printk(KERN_DEBUG "x25_asy: data received err - %d\n", err); } else { - netif_rx(skb); dev->stats.rx_packets++; } } @@ -355,12 +353,21 @@ static netdev_tx_t x25_asy_xmit(struct sk_buff *skb, */ /* - * Called when I frame data arrives. We did the work above - throw it - * at the net layer. + * Called when I frame data arrive. We add a pseudo header for upper + * layers and pass it to upper layers. */ static int x25_asy_data_indication(struct net_device *dev, struct sk_buff *skb) { + if (skb_cow(skb, 1)) { + kfree_skb(skb); + return NET_RX_DROP; + } + skb_push(skb, 1); + skb->data[0] = X25_IFACE_DATA; + + skb->protocol = x25_type_trans(skb, dev); + return netif_rx(skb); } @@ -656,7 +663,7 @@ static void x25_asy_unesc(struct x25_asy *sl, unsigned char s) switch (s) { case X25_END: if (!test_and_clear_bit(SLF_ERROR, &sl->flags) && - sl->rcount > 2) + sl->rcount >= 2) x25_asy_bump(sl); clear_bit(SLF_ESCAPE, &sl->flags); sl->rcount = 0; From f8607dcce0594a9ef7a82564bf12fbbb200ce29f Mon Sep 17 00:00:00 2001 From: Xiongfeng Wang Date: Tue, 21 Jul 2020 15:02:57 +0800 Subject: [PATCH 329/592] net-sysfs: add a newline when printing 'tx_timeout' by sysfs [ Upstream commit 9bb5fbea59f36a589ef886292549ca4052fe676c ] When I cat 'tx_timeout' by sysfs, it displays as follows. It's better to add a newline for easy reading. root@syzkaller:~# cat /sys/devices/virtual/net/lo/queues/tx-0/tx_timeout 0root@syzkaller:~# Signed-off-by: Xiongfeng Wang Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/net-sysfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index baf771d2d088..9d012255cedc 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -1028,7 +1028,7 @@ static ssize_t tx_timeout_show(struct netdev_queue *queue, char *buf) trans_timeout = queue->trans_timeout; spin_unlock_irq(&queue->_xmit_lock); - return sprintf(buf, "%lu", trans_timeout); + return sprintf(buf, fmt_ulong, trans_timeout); } static unsigned int get_netdev_queue_index(struct netdev_queue *queue) From cc1227c4ad82a63bd9d0f12b9f8e14e0b31e0af5 Mon Sep 17 00:00:00 2001 From: Miaohe Lin Date: Tue, 21 Jul 2020 17:11:44 +0800 Subject: [PATCH 330/592] net: udp: Fix wrong clean up for IS_UDPLITE macro [ Upstream commit b0a422772fec29811e293c7c0e6f991c0fd9241d ] We can't use IS_UDPLITE to replace udp_sk->pcflag when UDPLITE_RECV_CC is checked. Fixes: b2bf1e2659b1 ("[UDP]: Clean up for IS_UDPLITE macro") Signed-off-by: Miaohe Lin Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/udp.c | 2 +- net/ipv6/udp.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index e33258d69246..f335dd4c84e2 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1894,7 +1894,7 @@ static int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) /* * UDP-Lite specific tests, ignored on UDP sockets */ - if ((is_udplite & UDPLITE_RECV_CC) && UDP_SKB_CB(skb)->partial_cov) { + if ((up->pcflag & UDPLITE_RECV_CC) && UDP_SKB_CB(skb)->partial_cov) { /* * MIB statistics other than incrementing the error count are diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index a2ba7356fa65..38ad3fac8c37 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -629,7 +629,7 @@ static int udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) /* * UDP-Lite specific tests, ignored on UDP sockets (see net/ipv4/udp.c). */ - if ((is_udplite & UDPLITE_RECV_CC) && UDP_SKB_CB(skb)->partial_cov) { + if ((up->pcflag & UDPLITE_RECV_CC) && UDP_SKB_CB(skb)->partial_cov) { if (up->pcrlen == 0) { /* full coverage was set */ net_dbg_ratelimited("UDPLITE6: partial coverage %d while full coverage %d requested\n", From 88fb6b3913690564889dff0e9851f6533dd06000 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 20 Jul 2020 12:41:46 +0100 Subject: [PATCH 331/592] rxrpc: Fix sendmsg() returning EPIPE due to recvmsg() returning ENODATA [ Upstream commit 639f181f0ee20d3249dbc55f740f0167267180f0 ] rxrpc_sendmsg() returns EPIPE if there's an outstanding error, such as if rxrpc_recvmsg() indicating ENODATA if there's nothing for it to read. Change rxrpc_recvmsg() to return EAGAIN instead if there's nothing to read as this particular error doesn't get stored in ->sk_err by the networking core. Also change rxrpc_sendmsg() so that it doesn't fail with delayed receive errors (there's no way for it to report which call, if any, the error was caused by). Fixes: 17926a79320a ("[AF_RXRPC]: Provide secure RxRPC sockets for use by userspace and kernel both") Signed-off-by: David Howells Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/rxrpc/recvmsg.c | 2 +- net/rxrpc/sendmsg.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/net/rxrpc/recvmsg.c b/net/rxrpc/recvmsg.c index b74cde2fd214..e82e91fe6178 100644 --- a/net/rxrpc/recvmsg.c +++ b/net/rxrpc/recvmsg.c @@ -445,7 +445,7 @@ try_again: list_empty(&rx->recvmsg_q) && rx->sk.sk_state != RXRPC_SERVER_LISTENING) { release_sock(&rx->sk); - return -ENODATA; + return -EAGAIN; } if (list_empty(&rx->recvmsg_q)) { diff --git a/net/rxrpc/sendmsg.c b/net/rxrpc/sendmsg.c index a980b49d7a4f..f4386ad975cf 100644 --- a/net/rxrpc/sendmsg.c +++ b/net/rxrpc/sendmsg.c @@ -222,7 +222,7 @@ static int rxrpc_send_data(struct rxrpc_sock *rx, /* this should be in poll */ sk_clear_bit(SOCKWQ_ASYNC_NOSPACE, sk); - if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN)) + if (sk->sk_shutdown & SEND_SHUTDOWN) return -EPIPE; more = msg->msg_flags & MSG_MORE; From c1142de65e8f7f502896f7a5f3c25845ef5f56ac Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 23 Jul 2020 17:49:57 +0300 Subject: [PATCH 332/592] AX.25: Prevent integer overflows in connect and sendmsg [ Upstream commit 17ad73e941b71f3bec7523ea4e9cbc3752461c2d ] We recently added some bounds checking in ax25_connect() and ax25_sendmsg() and we so we removed the AX25_MAX_DIGIS checks because they were no longer required. Unfortunately, I believe they are required to prevent integer overflows so I have added them back. Fixes: 8885bb0621f0 ("AX.25: Prevent out-of-bounds read in ax25_sendmsg()") Fixes: 2f2a7ffad5c6 ("AX.25: Fix out-of-bounds read in ax25_connect()") Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ax25/af_ax25.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index 751b6e8cfa19..6915eebc7a4a 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -1192,6 +1192,7 @@ static int __must_check ax25_connect(struct socket *sock, fsa->fsa_ax25.sax25_ndigis != 0) { /* Valid number of digipeaters ? */ if (fsa->fsa_ax25.sax25_ndigis < 1 || + fsa->fsa_ax25.sax25_ndigis > AX25_MAX_DIGIS || addr_len < sizeof(struct sockaddr_ax25) + sizeof(ax25_address) * fsa->fsa_ax25.sax25_ndigis) { err = -EINVAL; @@ -1513,7 +1514,9 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) struct full_sockaddr_ax25 *fsa = (struct full_sockaddr_ax25 *)usax; /* Valid number of digipeaters ? */ - if (usax->sax25_ndigis < 1 || addr_len < sizeof(struct sockaddr_ax25) + + if (usax->sax25_ndigis < 1 || + usax->sax25_ndigis > AX25_MAX_DIGIS || + addr_len < sizeof(struct sockaddr_ax25) + sizeof(ax25_address) * usax->sax25_ndigis) { err = -EINVAL; goto out; From d6b1ffe225b2524c70d2be829a412da0eda66f84 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Mon, 13 Jul 2020 23:59:50 +0800 Subject: [PATCH 333/592] ip6_gre: fix null-ptr-deref in ip6gre_init_net() [ Upstream commit 46ef5b89ec0ecf290d74c4aee844f063933c4da4 ] KASAN report null-ptr-deref error when register_netdev() failed: KASAN: null-ptr-deref in range [0x00000000000003c0-0x00000000000003c7] CPU: 2 PID: 422 Comm: ip Not tainted 5.8.0-rc4+ #12 Call Trace: ip6gre_init_net+0x4ab/0x580 ? ip6gre_tunnel_uninit+0x3f0/0x3f0 ops_init+0xa8/0x3c0 setup_net+0x2de/0x7e0 ? rcu_read_lock_bh_held+0xb0/0xb0 ? ops_init+0x3c0/0x3c0 ? kasan_unpoison_shadow+0x33/0x40 ? __kasan_kmalloc.constprop.0+0xc2/0xd0 copy_net_ns+0x27d/0x530 create_new_namespaces+0x382/0xa30 unshare_nsproxy_namespaces+0xa1/0x1d0 ksys_unshare+0x39c/0x780 ? walk_process_tree+0x2a0/0x2a0 ? trace_hardirqs_on+0x4a/0x1b0 ? _raw_spin_unlock_irq+0x1f/0x30 ? syscall_trace_enter+0x1a7/0x330 ? do_syscall_64+0x1c/0xa0 __x64_sys_unshare+0x2d/0x40 do_syscall_64+0x56/0xa0 entry_SYSCALL_64_after_hwframe+0x44/0xa9 ip6gre_tunnel_uninit() has set 'ign->fb_tunnel_dev' to NULL, later access to ign->fb_tunnel_dev cause null-ptr-deref. Fix it by saving 'ign->fb_tunnel_dev' to local variable ndev. Fixes: dafabb6590cb ("ip6_gre: fix use-after-free in ip6gre_tunnel_lookup()") Reported-by: Hulk Robot Signed-off-by: Wei Yongjun Reviewed-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv6/ip6_gre.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index e07cc2cfc1a6..802457c0a121 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c @@ -1169,15 +1169,16 @@ static void ip6gre_destroy_tunnels(struct net *net, struct list_head *head) static int __net_init ip6gre_init_net(struct net *net) { struct ip6gre_net *ign = net_generic(net, ip6gre_net_id); + struct net_device *ndev; int err; - ign->fb_tunnel_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6gre0", - NET_NAME_UNKNOWN, - ip6gre_tunnel_setup); - if (!ign->fb_tunnel_dev) { + ndev = alloc_netdev(sizeof(struct ip6_tnl), "ip6gre0", + NET_NAME_UNKNOWN, ip6gre_tunnel_setup); + if (!ndev) { err = -ENOMEM; goto err_alloc_dev; } + ign->fb_tunnel_dev = ndev; dev_net_set(ign->fb_tunnel_dev, net); /* FB netdevice is special: we have one, and only one per netns. * Allowing to move it to another netns is clearly unsafe. @@ -1197,7 +1198,7 @@ static int __net_init ip6gre_init_net(struct net *net) return 0; err_reg_dev: - free_netdev(ign->fb_tunnel_dev); + free_netdev(ndev); err_alloc_dev: return err; } From b1f58d61380aa5ebacac666e0fe28bc0f5b5a533 Mon Sep 17 00:00:00 2001 From: Weilong Chen Date: Wed, 15 Jul 2020 20:58:10 +0800 Subject: [PATCH 334/592] rtnetlink: Fix memory(net_device) leak when ->newlink fails [ Upstream commit cebb69754f37d68e1355a5e726fdac317bcda302 ] When vlan_newlink call register_vlan_dev fails, it might return error with dev->reg_state = NETREG_UNREGISTERED. The rtnl_newlink should free the memory. But currently rtnl_newlink only free the memory which state is NETREG_UNINITIALIZED. BUG: memory leak unreferenced object 0xffff8881051de000 (size 4096): comm "syz-executor139", pid 560, jiffies 4294745346 (age 32.445s) hex dump (first 32 bytes): 76 6c 61 6e 32 00 00 00 00 00 00 00 00 00 00 00 vlan2........... 00 45 28 03 81 88 ff ff 00 00 00 00 00 00 00 00 .E(............. backtrace: [<0000000047527e31>] kmalloc_node include/linux/slab.h:578 [inline] [<0000000047527e31>] kvmalloc_node+0x33/0xd0 mm/util.c:574 [<000000002b59e3bc>] kvmalloc include/linux/mm.h:753 [inline] [<000000002b59e3bc>] kvzalloc include/linux/mm.h:761 [inline] [<000000002b59e3bc>] alloc_netdev_mqs+0x83/0xd90 net/core/dev.c:9929 [<000000006076752a>] rtnl_create_link+0x2c0/0xa20 net/core/rtnetlink.c:3067 [<00000000572b3be5>] __rtnl_newlink+0xc9c/0x1330 net/core/rtnetlink.c:3329 [<00000000e84ea553>] rtnl_newlink+0x66/0x90 net/core/rtnetlink.c:3397 [<0000000052c7c0a9>] rtnetlink_rcv_msg+0x540/0x990 net/core/rtnetlink.c:5460 [<000000004b5cb379>] netlink_rcv_skb+0x12b/0x3a0 net/netlink/af_netlink.c:2469 [<00000000c71c20d3>] netlink_unicast_kernel net/netlink/af_netlink.c:1303 [inline] [<00000000c71c20d3>] netlink_unicast+0x4c6/0x690 net/netlink/af_netlink.c:1329 [<00000000cca72fa9>] netlink_sendmsg+0x735/0xcc0 net/netlink/af_netlink.c:1918 [<000000009221ebf7>] sock_sendmsg_nosec net/socket.c:652 [inline] [<000000009221ebf7>] sock_sendmsg+0x109/0x140 net/socket.c:672 [<000000001c30ffe4>] ____sys_sendmsg+0x5f5/0x780 net/socket.c:2352 [<00000000b71ca6f3>] ___sys_sendmsg+0x11d/0x1a0 net/socket.c:2406 [<0000000007297384>] __sys_sendmsg+0xeb/0x1b0 net/socket.c:2439 [<000000000eb29b11>] do_syscall_64+0x56/0xa0 arch/x86/entry/common.c:359 [<000000006839b4d0>] entry_SYSCALL_64_after_hwframe+0x44/0xa9 Fixes: cb626bf566eb ("net-sysfs: Fix reference count leak") Reported-by: Hulk Robot Signed-off-by: Weilong Chen Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/rtnetlink.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index cb15338cfda4..0168c700a201 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -2733,7 +2733,8 @@ replay: */ if (err < 0) { /* If device is not registered at all, free it now */ - if (dev->reg_state == NETREG_UNINITIALIZED) + if (dev->reg_state == NETREG_UNINITIALIZED || + dev->reg_state == NETREG_UNREGISTERED) free_netdev(dev); goto out; } From e72a42b699ba49590d177847407e6ff161daded1 Mon Sep 17 00:00:00 2001 From: Yuchung Cheng Date: Thu, 23 Jul 2020 12:00:06 -0700 Subject: [PATCH 335/592] tcp: allow at most one TLP probe per flight [ Upstream commit 76be93fc0702322179bb0ea87295d820ee46ad14 ] Previously TLP may send multiple probes of new data in one flight. This happens when the sender is cwnd limited. After the initial TLP containing new data is sent, the sender receives another ACK that acks partial inflight. It may re-arm another TLP timer to send more, if no further ACK returns before the next TLP timeout (PTO) expires. The sender may send in theory a large amount of TLP until send queue is depleted. This only happens if the sender sees such irregular uncommon ACK pattern. But it is generally undesirable behavior during congestion especially. The original TLP design restrict only one TLP probe per inflight as published in "Reducing Web Latency: the Virtue of Gentle Aggression", SIGCOMM 2013. This patch changes TLP to send at most one probe per inflight. Note that if the sender is app-limited, TLP retransmits old data and did not have this issue. Signed-off-by: Yuchung Cheng Signed-off-by: Neal Cardwell Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/linux/tcp.h | 4 +++- net/ipv4/tcp_input.c | 11 ++++++----- net/ipv4/tcp_output.c | 13 ++++++++----- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/include/linux/tcp.h b/include/linux/tcp.h index 60aea230dc6a..61eb40fef759 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -209,6 +209,8 @@ struct tcp_sock { u8 reord; /* reordering detected */ } rack; u16 advmss; /* Advertised MSS */ + u8 tlp_retrans:1, /* TLP is a retransmission */ + unused_1:7; u32 chrono_start; /* Start time in jiffies of a TCP chrono */ u32 chrono_stat[3]; /* Time in jiffies for chrono_stat stats */ u8 chrono_type:2, /* current chronograph type */ @@ -229,7 +231,7 @@ struct tcp_sock { syn_data_acked:1,/* data in SYN is acked by SYN-ACK */ save_syn:1, /* Save headers of SYN packet */ is_cwnd_limited:1;/* forward progress limited by snd_cwnd? */ - u32 tlp_high_seq; /* snd_nxt at the time of TLP retransmit. */ + u32 tlp_high_seq; /* snd_nxt at the time of TLP */ /* RTT measurement */ u64 tcp_mstamp; /* most recent packet received/sent */ diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index a2c26c2b3a94..83d03340417a 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -3516,10 +3516,8 @@ static void tcp_replace_ts_recent(struct tcp_sock *tp, u32 seq) } } -/* This routine deals with acks during a TLP episode. - * We mark the end of a TLP episode on receiving TLP dupack or when - * ack is after tlp_high_seq. - * Ref: loss detection algorithm in draft-dukkipati-tcpm-tcp-loss-probe. +/* This routine deals with acks during a TLP episode and ends an episode by + * resetting tlp_high_seq. Ref: TLP algorithm in draft-ietf-tcpm-rack */ static void tcp_process_tlp_ack(struct sock *sk, u32 ack, int flag) { @@ -3528,7 +3526,10 @@ static void tcp_process_tlp_ack(struct sock *sk, u32 ack, int flag) if (before(ack, tp->tlp_high_seq)) return; - if (flag & FLAG_DSACKING_ACK) { + if (!tp->tlp_retrans) { + /* TLP of new data has been acknowledged */ + tp->tlp_high_seq = 0; + } else if (flag & FLAG_DSACKING_ACK) { /* This DSACK means original and TLP probe arrived; no loss */ tp->tlp_high_seq = 0; } else if (after(ack, tp->tlp_high_seq)) { diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 8fc14ad0726a..355ebae883c1 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -2500,6 +2500,11 @@ void tcp_send_loss_probe(struct sock *sk) int pcount; int mss = tcp_current_mss(sk); + /* At most one outstanding TLP */ + if (tp->tlp_high_seq) + goto rearm_timer; + + tp->tlp_retrans = 0; skb = tcp_send_head(sk); if (skb) { if (tcp_snd_wnd_test(tp, skb, mss)) { @@ -2522,10 +2527,6 @@ void tcp_send_loss_probe(struct sock *sk) return; } - /* At most one outstanding TLP retransmission. */ - if (tp->tlp_high_seq) - goto rearm_timer; - if (skb_still_in_host_queue(sk, skb)) goto rearm_timer; @@ -2546,10 +2547,12 @@ void tcp_send_loss_probe(struct sock *sk) if (__tcp_retransmit_skb(sk, skb, 1)) goto rearm_timer; + tp->tlp_retrans = 1; + +probe_sent: /* Record snd_nxt for loss detection. */ tp->tlp_high_seq = tp->snd_nxt; -probe_sent: NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPLOSSPROBES); /* Reset s.t. tcp_rearm_rto will restart timer from now */ inet_csk(sk)->icsk_pending = 0; From bbacb34b84407ac008409d45b816617579ca26fd Mon Sep 17 00:00:00 2001 From: Oscar Salvador Date: Thu, 18 Jan 2018 16:33:53 -0800 Subject: [PATCH 336/592] mm/page_owner.c: remove drain_all_pages from init_early_allocated_pages commit 6bec6ad77fac3d29aed0d8e0b7526daedc964970 upstream. When setting page_owner = on, the following warning can be seen in the boot log: WARNING: CPU: 0 PID: 0 at mm/page_alloc.c:2537 drain_all_pages+0x171/0x1a0 Modules linked in: CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.15.0-rc7-next-20180109-1-default+ #7 Hardware name: Dell Inc. Latitude E7470/0T6HHJ, BIOS 1.11.3 11/09/2016 RIP: 0010:drain_all_pages+0x171/0x1a0 Call Trace: init_page_owner+0x4e/0x260 start_kernel+0x3e6/0x4a6 ? set_init_arg+0x55/0x55 secondary_startup_64+0xa5/0xb0 Code: c5 ed ff 89 df 48 c7 c6 20 3b 71 82 e8 f9 4b 52 00 3b 05 d7 0b f8 00 89 c3 72 d5 5b 5d 41 5 This warning is shown because we are calling drain_all_pages() in init_early_allocated_pages(), but mm_percpu_wq is not up yet, it is being set up later on in kernel_init_freeable() -> init_mm_internals(). Link: http://lkml.kernel.org/r/20180109153921.GA13070@techadventures.net Signed-off-by: Oscar Salvador Acked-by: Joonsoo Kim Cc: Vlastimil Babka Cc: Michal Hocko Cc: Ayush Mittal Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Nick Desaulniers Signed-off-by: Greg Kroah-Hartman --- mm/page_owner.c | 1 - 1 file changed, 1 deletion(-) diff --git a/mm/page_owner.c b/mm/page_owner.c index 6ac05a6ff2d1..4753b317ef7b 100644 --- a/mm/page_owner.c +++ b/mm/page_owner.c @@ -617,7 +617,6 @@ static void init_early_allocated_pages(void) { pg_data_t *pgdat; - drain_all_pages(NULL); for_each_online_pgdat(pgdat) init_zones_in_node(pgdat); } From 1f850ba16f920edca56ffa13adf493fe85d86498 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Fri, 13 Mar 2020 09:58:07 +0800 Subject: [PATCH 337/592] regmap: debugfs: check count when read regmap file commit 74edd08a4fbf51d65fd8f4c7d8289cd0f392bd91 upstream. When executing the following command, we met kernel dump. dmesg -c > /dev/null; cd /sys; for i in `ls /sys/kernel/debug/regmap/* -d`; do echo "Checking regmap in $i"; cat $i/registers; done && grep -ri "0x02d0" *; It is because the count value is too big, and kmalloc fails. So add an upper bound check to allow max size `PAGE_SIZE << (MAX_ORDER - 1)`. Signed-off-by: Peng Fan Link: https://lore.kernel.org/r/1584064687-12964-1-git-send-email-peng.fan@nxp.com Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- drivers/base/regmap/regmap-debugfs.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c index 36ce3511c733..7d0c83b47259 100644 --- a/drivers/base/regmap/regmap-debugfs.c +++ b/drivers/base/regmap/regmap-debugfs.c @@ -204,6 +204,9 @@ static ssize_t regmap_read_debugfs(struct regmap *map, unsigned int from, if (*ppos < 0 || !count) return -EINVAL; + if (count > (PAGE_SIZE << (MAX_ORDER - 1))) + count = PAGE_SIZE << (MAX_ORDER - 1); + buf = kmalloc(count, GFP_KERNEL); if (!buf) return -ENOMEM; @@ -352,6 +355,9 @@ static ssize_t regmap_reg_ranges_read_file(struct file *file, if (*ppos < 0 || !count) return -EINVAL; + if (count > (PAGE_SIZE << (MAX_ORDER - 1))) + count = PAGE_SIZE << (MAX_ORDER - 1); + buf = kmalloc(count, GFP_KERNEL); if (!buf) return -ENOMEM; From 8a443ffcf7b572c071398644d35cf9cc55cfa2cb Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Mon, 16 Apr 2018 23:07:27 -0700 Subject: [PATCH 338/592] xfs: set format back to extents if xfs_bmap_extents_to_btree commit 2c4306f719b083d17df2963bc761777576b8ad1b upstream. If xfs_bmap_extents_to_btree fails in a mode where we call xfs_iroot_realloc(-1) to de-allocate the root, set the format back to extents. Otherwise we can assume we can dereference ifp->if_broot based on the XFS_DINODE_FMT_BTREE format, and crash. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=199423 Signed-off-by: Eric Sandeen Reviewed-by: Christoph Hellwig Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong Signed-off-by: Nobuhiro Iwamatsu (CIP) Signed-off-by: Greg Kroah-Hartman --- fs/xfs/libxfs/xfs_bmap.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 84245d210182..2b07dadc5916 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -761,12 +761,16 @@ xfs_bmap_extents_to_btree( *logflagsp = 0; if ((error = xfs_alloc_vextent(&args))) { xfs_iroot_realloc(ip, -1, whichfork); + ASSERT(ifp->if_broot == NULL); + XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS); xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); return error; } if (WARN_ON_ONCE(args.fsbno == NULLFSBLOCK)) { xfs_iroot_realloc(ip, -1, whichfork); + ASSERT(ifp->if_broot == NULL); + XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS); xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); return -ENOSPC; } From 7f2c5eb458b8855655a19c44cd0043f7f83c595f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 31 Jul 2020 16:44:45 +0200 Subject: [PATCH 339/592] Linux 4.14.191 Signed-off-by: Greg Kroah-Hartman --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 4e5f6615fd98..e31c1ce12895 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 VERSION = 4 PATCHLEVEL = 14 -SUBLEVEL = 190 +SUBLEVEL = 191 EXTRAVERSION = NAME = Petit Gorille From d91b1d17fef71edec7ea9405c91a6b7c0c305543 Mon Sep 17 00:00:00 2001 From: Xiaowen Wu Date: Thu, 21 Nov 2019 13:09:59 -0500 Subject: [PATCH 340/592] drm/msm/sde: fix topology lookup table when ctl version is used Fix topology lookup table when ctl version is used. Currently, hardcoded tables are used instead of the selected one in rm based on the ctl version. Change-Id: I316575aa65489242b54f3764f272db586998f7d6 Signed-off-by: satbir singh Signed-off-by: Amine Najahi Signed-off-by: Xiaowen Wu Signed-off-by: UtsavBalar1231 --- drivers/gpu/drm/msm/sde/sde_connector.c | 4 ++-- drivers/gpu/drm/msm/sde/sde_encoder.c | 3 ++- drivers/gpu/drm/msm/sde/sde_rm.c | 13 +++++++------ drivers/gpu/drm/msm/sde/sde_rm.h | 5 +++-- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_connector.c b/drivers/gpu/drm/msm/sde/sde_connector.c index 8f9254e526dd..4d9a27891886 100644 --- a/drivers/gpu/drm/msm/sde/sde_connector.c +++ b/drivers/gpu/drm/msm/sde/sde_connector.c @@ -2224,8 +2224,8 @@ static int sde_connector_populate_mode_info(struct drm_connector *conn, sde_kms_info_add_keyint(info, "bit_clk_rate", mode_info.clk_rate); - topology_idx = (int)sde_rm_get_topology_name( - mode_info.topology); + topology_idx = (int)sde_rm_get_topology_name(&sde_kms->rm, + mode_info.topology); if (topology_idx < SDE_RM_TOPOLOGY_MAX) { sde_kms_info_add_keystr(info, "topology", e_topology_name[topology_idx].name); diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c index 777e75d71a19..905138da300f 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder.c @@ -1143,7 +1143,8 @@ static int sde_encoder_virt_atomic_check( if (crtc_state->active) topology = &sde_conn_state->mode_info.topology; - ret = sde_rm_update_topology(conn_state, topology); + ret = sde_rm_update_topology(&sde_kms->rm, conn_state, + topology); if (ret) { SDE_ERROR_ENC(sde_enc, "RM failed to update topology, rc: %d\n", ret); diff --git a/drivers/gpu/drm/msm/sde/sde_rm.c b/drivers/gpu/drm/msm/sde/sde_rm.c index 66fd28093ffc..ccfe8239efaa 100644 --- a/drivers/gpu/drm/msm/sde/sde_rm.c +++ b/drivers/gpu/drm/msm/sde/sde_rm.c @@ -190,14 +190,14 @@ void sde_rm_init_hw_iter( iter->type = type; } -enum sde_rm_topology_name sde_rm_get_topology_name( +enum sde_rm_topology_name sde_rm_get_topology_name(struct sde_rm *rm, struct msm_display_topology topology) { int i; for (i = 0; i < SDE_RM_TOPOLOGY_MAX; i++) - if (RM_IS_TOPOLOGY_MATCH(g_top_table[i], topology)) - return g_top_table[i].top_name; + if (RM_IS_TOPOLOGY_MATCH(rm->topology_tbl[i], topology)) + return rm->topology_tbl[i].top_name; return SDE_RM_TOPOLOGY_NONE; } @@ -1645,7 +1645,8 @@ static struct drm_connector *_sde_rm_get_connector( return NULL; } -int sde_rm_update_topology(struct drm_connector_state *conn_state, +int sde_rm_update_topology(struct sde_rm *rm, + struct drm_connector_state *conn_state, struct msm_display_topology *topology) { int i, ret = 0; @@ -1658,8 +1659,8 @@ int sde_rm_update_topology(struct drm_connector_state *conn_state, if (topology) { top = *topology; for (i = 0; i < SDE_RM_TOPOLOGY_MAX; i++) - if (RM_IS_TOPOLOGY_MATCH(g_top_table[i], top)) { - top_name = g_top_table[i].top_name; + if (RM_IS_TOPOLOGY_MATCH(rm->topology_tbl[i], top)) { + top_name = rm->topology_tbl[i].top_name; break; } } diff --git a/drivers/gpu/drm/msm/sde/sde_rm.h b/drivers/gpu/drm/msm/sde/sde_rm.h index ab6beaf928dc..486b73f1dfb4 100644 --- a/drivers/gpu/drm/msm/sde/sde_rm.h +++ b/drivers/gpu/drm/msm/sde/sde_rm.h @@ -162,7 +162,7 @@ struct sde_rm_hw_request { * @topology: msm_display_topology topology config * @Return: name of the given topology */ -enum sde_rm_topology_name sde_rm_get_topology_name( +enum sde_rm_topology_name sde_rm_get_topology_name(struct sde_rm *rm, struct msm_display_topology topology); @@ -279,7 +279,8 @@ int sde_rm_cont_splash_res_init(struct msm_drm_private *priv, * @topology: topology selected for the display * @return: 0 on success or error */ -int sde_rm_update_topology(struct drm_connector_state *conn_state, +int sde_rm_update_topology(struct sde_rm *rm, + struct drm_connector_state *conn_state, struct msm_display_topology *topology); /** From e301160d5d6cba53ae988d5f5c402d4f1aa108c5 Mon Sep 17 00:00:00 2001 From: Xiaowen Wu Date: Thu, 27 Feb 2020 13:09:59 -0500 Subject: [PATCH 341/592] drm/msm/sde: skip crtc atomic begin when active is false When active in crtc state is false we should skip atomic begin to avoid unnecessary configurations. Change-Id: I4133d318e88ccf5e27a982257d8ec09a7b49af12 Signed-off-by: Xiaowen Wu Signed-off-by: UtsavBalar1231 --- drivers/gpu/drm/msm/sde/sde_crtc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c index 82e3c2f6885a..c4ebdcf02fcc 100644 --- a/drivers/gpu/drm/msm/sde/sde_crtc.c +++ b/drivers/gpu/drm/msm/sde/sde_crtc.c @@ -3951,9 +3951,9 @@ static void sde_crtc_atomic_begin(struct drm_crtc *crtc, return; } - if (!crtc->state->enable) { - SDE_DEBUG("crtc%d -> enable %d, skip atomic_begin\n", - crtc->base.id, crtc->state->enable); + if (!crtc->state->active) { + SDE_DEBUG("crtc%d -> active %d, skip atomic_begin\n", + crtc->base.id, crtc->state->active); return; } From 2870498a6d58cd554bec29d0dd26f080b5d1c730 Mon Sep 17 00:00:00 2001 From: Xiaowen Wu Date: Mon, 16 Mar 2020 13:09:59 -0500 Subject: [PATCH 342/592] drm/msm/sde: remove redundant connector cache list update Remove the redundant connector cache list update, which is already done in sde_crtc_atomic_check. Change-Id: I5a6f9892c3925d9ab6f8b41860ea6c15ecaadd56 Signed-off-by: Xiaowen Wu Signed-off-by: UtsavBalar1231 --- drivers/gpu/drm/msm/sde/sde_crtc.c | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c index c4ebdcf02fcc..fafd97c75286 100644 --- a/drivers/gpu/drm/msm/sde/sde_crtc.c +++ b/drivers/gpu/drm/msm/sde/sde_crtc.c @@ -2898,7 +2898,7 @@ void sde_crtc_prepare_commit(struct drm_crtc *crtc, struct sde_crtc_state *cstate; struct drm_connector *conn; struct drm_encoder *encoder; - struct drm_connector_list_iter conn_iter; + int i; if (!crtc || !crtc->state) { SDE_ERROR("invalid crtc\n"); @@ -2912,24 +2912,16 @@ void sde_crtc_prepare_commit(struct drm_crtc *crtc, SDE_ATRACE_BEGIN("sde_crtc_prepare_commit"); - /* identify connectors attached to this crtc */ - cstate->num_connectors = 0; - - drm_connector_list_iter_begin(dev, &conn_iter); - drm_for_each_connector_iter(conn, &conn_iter) - if (conn->state && conn->state->crtc == crtc && - cstate->num_connectors < MAX_CONNECTORS) { - encoder = conn->state->best_encoder; - if (encoder) - sde_encoder_register_frame_event_callback( - encoder, - sde_crtc_frame_event_cb, - crtc); - - cstate->connectors[cstate->num_connectors++] = conn; - sde_connector_prepare_fence(conn); - } - drm_connector_list_iter_end(&conn_iter); + for (i = 0; i < cstate->num_connectors; i++) { + conn = cstate->connectors[i]; + encoder = conn->state->best_encoder; + if (encoder) + sde_encoder_register_frame_event_callback( + encoder, + sde_crtc_frame_event_cb, + crtc); + sde_connector_prepare_fence(conn); + } /* prepare main output fence */ sde_fence_prepare(sde_crtc->output_fence); From f6e613d3e4914edf4b93fdf66f22ecb953b7af4d Mon Sep 17 00:00:00 2001 From: Xiaowen Wu Date: Fri, 13 Mar 2020 13:09:59 -0500 Subject: [PATCH 343/592] drm/msm/sde: fix deadlock by connection_mutex After crtc_mask get updated in msm_atomic_commit, we should not request any drm state lock as it will cause deadlock if another commit from different thread aquires the same crtc. This changes removes the locking request for connection_mutex in prepare_fence stage. connection_mutex is not needed when drm_connector_list_iter is used. Change-Id: Ifef96c6cedda486618ba3680f2aa328e8f0767cf Signed-off-by: Xiaowen Wu Signed-off-by: UtsavBalar1231 --- drivers/gpu/drm/msm/sde/sde_kms.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c index dda77d6ccd72..840959d71c96 100644 --- a/drivers/gpu/drm/msm/sde/sde_kms.c +++ b/drivers/gpu/drm/msm/sde/sde_kms.c @@ -1239,7 +1239,7 @@ static void sde_kms_prepare_fence(struct msm_kms *kms, { struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state; - int i, rc; + int i; if (!kms || !old_state || !old_state->dev || !old_state->acquire_ctx) { SDE_ERROR("invalid argument(s)\n"); @@ -1247,15 +1247,6 @@ static void sde_kms_prepare_fence(struct msm_kms *kms, } SDE_ATRACE_BEGIN("sde_kms_prepare_fence"); -retry: - /* attempt to acquire ww mutex for connection */ - rc = drm_modeset_lock(&old_state->dev->mode_config.connection_mutex, - old_state->acquire_ctx); - - if (rc == -EDEADLK) { - drm_modeset_backoff(old_state->acquire_ctx); - goto retry; - } /* old_state actually contains updated crtc pointers */ for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) { From 6cf6bb0877517e7efb2d5a2428d26515d94879fc Mon Sep 17 00:00:00 2001 From: Xiaowen Wu Date: Mon, 9 Mar 2020 13:09:59 -0500 Subject: [PATCH 344/592] drm/msm/sde: skip rsc client creation for external encoders If phy is inited from external, we'll let external drivers to create rsc client if needed. This change will avoid unnecessary RSC voting for shared displays. CRs-Fixed: 2637895 Change-Id: Ie4819eebccc49db89b98dd71b853ac0b0dd57e46 Signed-off-by: Xiaowen Wu Signed-off-by: UtsavBalar1231 --- drivers/gpu/drm/msm/sde/sde_encoder.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c index 905138da300f..d4cd7deaa620 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder.c @@ -5467,14 +5467,21 @@ struct drm_encoder *sde_encoder_init_with_ops( if (phys->ops.is_master && phys->ops.is_master(phys)) intf_index = phys->intf_idx - INTF_0; } - snprintf(name, SDE_NAME_SIZE, "rsc_enc%u", drm_enc->base.id); - sde_enc->rsc_client = sde_rsc_client_create(SDE_RSC_INDEX, name, - disp_info->is_primary ? SDE_RSC_PRIMARY_DISP_CLIENT : - SDE_RSC_EXTERNAL_DISP_CLIENT, intf_index + 1); - if (IS_ERR_OR_NULL(sde_enc->rsc_client)) { - SDE_DEBUG("sde rsc client create failed :%ld\n", - PTR_ERR(sde_enc->rsc_client)); - sde_enc->rsc_client = NULL; + /* + * if phy is inited from external, we'll let external drivers to + * create rsc client if needed. + */ + if (!sde_enc->ops.phys_init) { + snprintf(name, SDE_NAME_SIZE, "rsc_enc%u", drm_enc->base.id); + sde_enc->rsc_client = + sde_rsc_client_create(SDE_RSC_INDEX, name, + disp_info->is_primary ? SDE_RSC_PRIMARY_DISP_CLIENT : + SDE_RSC_EXTERNAL_DISP_CLIENT, intf_index + 1); + if (IS_ERR_OR_NULL(sde_enc->rsc_client)) { + SDE_DEBUG("sde rsc client create failed :%ld\n", + PTR_ERR(sde_enc->rsc_client)); + sde_enc->rsc_client = NULL; + } } if (disp_info->capabilities & MSM_DISPLAY_CAP_CMD_MODE) { From 89104c7472ab4717b4cd03324a1a68983cf71339 Mon Sep 17 00:00:00 2001 From: Xiaowen Wu Date: Tue, 3 Mar 2020 13:09:59 -0500 Subject: [PATCH 345/592] drm/msm/sde: update multirect op to max for multirect mode Update multirect op to max when multirect mode is set. This fixes the mismatch when rect 0 and rect 1 are committed in different commits and multirect mode is selected. Change-Id: Ie96e18ea9ec616820249104f95a90e11da692416 Signed-off-by: Xiaowen Wu Signed-off-by: UtsavBalar1231 --- drivers/gpu/drm/msm/sde/sde_hw_sspp.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/sde/sde_hw_sspp.c b/drivers/gpu/drm/msm/sde/sde_hw_sspp.c index 35b1e099fcbe..ca3608040f1c 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_sspp.c +++ b/drivers/gpu/drm/msm/sde/sde_hw_sspp.c @@ -220,7 +220,10 @@ static void sde_hw_sspp_setup_multirect(struct sde_hw_pipe *ctx, mode_mask = 0; } else { mode_mask = SDE_REG_READ(&ctx->hw, SSPP_MULTIRECT_OPMODE + idx); - mode_mask |= index; + if (mode == SDE_SSPP_MULTIRECT_NONE) + mode_mask |= index; + else + mode_mask |= SDE_SSPP_RECT_MAX; if (mode == SDE_SSPP_MULTIRECT_TIME_MX) mode_mask |= BIT(2); else From 850d77e5027a1ce6f1a03e048f0ce8016651c3a0 Mon Sep 17 00:00:00 2001 From: Jayaprakash Date: Mon, 2 Dec 2019 11:56:01 +0530 Subject: [PATCH 346/592] disp: msm: sde: modify setting of split_display flag For CTL_ACTIVE targets, slave ctl need not to be reserved as both the interfaces can be driven with single ctl. Add a necessary check before enabling the feature. Change-Id: Id68d7dd4fc1cf9534466fd5bfa50c3f551d06ce4 Signed-off-by: Jayaprakash Signed-off-by: UtsavBalar1231 --- drivers/gpu/drm/msm/sde/sde_hw_catalog.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c index 155645567ce2..e0f33def74ac 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c +++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c @@ -1597,7 +1597,8 @@ static int sde_ctl_parse_dt(struct device_node *np, ctl_prop[HW_DISP].prop_name, i, &disp_pref); if (disp_pref && !strcmp(disp_pref, "primary")) set_bit(SDE_CTL_PRIMARY_PREF, &ctl->features); - if (i < MAX_SPLIT_DISPLAY_CTL) + if ((i < MAX_SPLIT_DISPLAY_CTL) && + !(IS_SDE_CTL_REV_100(sde_cfg->ctl_rev))) set_bit(SDE_CTL_SPLIT_DISPLAY, &ctl->features); if (i < MAX_PP_SPLIT_DISPLAY_CTL) set_bit(SDE_CTL_PINGPONG_SPLIT, &ctl->features); From 592bd5788805bf0a47678f7a36486c947dea6789 Mon Sep 17 00:00:00 2001 From: UtsavBalar1231 Date: Fri, 31 Jul 2020 23:30:30 +0530 Subject: [PATCH 347/592] drm/msm/sde: revert gcc compilation fix from yaro Signed-off-by: UtsavBalar1231 --- drivers/gpu/drm/msm/sde/sde_kms.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c index 840959d71c96..03d3349839ea 100644 --- a/drivers/gpu/drm/msm/sde/sde_kms.c +++ b/drivers/gpu/drm/msm/sde/sde_kms.c @@ -2761,13 +2761,8 @@ retry: } crtc_state->active = true; - ret = drm_atomic_set_crtc_for_connector(conn_state, enc->crtc); - if (ret) - goto end; - - ret = drm_atomic_commit(state); - if (ret != -EDEADLK) - goto end; + drm_atomic_set_crtc_for_connector(conn_state, enc->crtc); + drm_atomic_commit(state); end: if (state) From a69eaf5efd61f3280ed287aaa6b28d76e02847f4 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Wed, 13 Mar 2019 10:16:32 -0600 Subject: [PATCH 348/592] drm: msm: sde: Fix compile warnings Fix the following compiler warning(s) from gcc 6.1.1 with -Werror enabled: msm/sde/sde_kms.c:2672:2: error: ignoring return value of 'drm_atomic_set_crtc_for_connector', declared with attribute warn_unused_result [-Werror=unused-result] msm/sde/sde_kms.c:2674:2: error: ignoring return value of 'drm_atomic_commit', declared with attribute warn_unused_result [-Werror=unused-result] Change-Id: I4cf8f050927cadc51622fb059e622261609bd247 Signed-off-by: Jordan Crouse Signed-off-by: UtsavBalar1231 --- drivers/gpu/drm/msm/sde/sde_kms.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c index 03d3349839ea..0d5e7012b919 100644 --- a/drivers/gpu/drm/msm/sde/sde_kms.c +++ b/drivers/gpu/drm/msm/sde/sde_kms.c @@ -2761,8 +2761,13 @@ retry: } crtc_state->active = true; - drm_atomic_set_crtc_for_connector(conn_state, enc->crtc); - drm_atomic_commit(state); + ret = drm_atomic_set_crtc_for_connector(conn_state, enc->crtc); + if (ret) + SDE_ERROR("error %d setting the crtc\n", ret); + + ret = drm_atomic_commit(state); + if (ret) + SDE_ERROR("Error %d doing the atomic commit\n", ret); end: if (state) From 13800cfcd392a1aead7a314ad0d0087d124ad6fa Mon Sep 17 00:00:00 2001 From: Manaf Meethalavalappu Pallikunhi Date: Thu, 16 Jul 2020 13:35:22 +0530 Subject: [PATCH 349/592] ARM: dts: msm: Enable default thermal zones and cooling devices for sdm429 Enable default thermal zones like TSENS user_space rules, cpu, gpu stepwise mitigation rules, low temperature vdd restriction rules, skin thermistor rules and BCL thermal zone rules for sdm429. Change-Id: I9e0d3cc5657e856e44c6ae3fd6d30eb2dcb75415 Signed-off-by: Manaf Meethalavalappu Pallikunhi --- arch/arm64/boot/dts/qcom/pm660.dtsi | 100 +++ arch/arm64/boot/dts/qcom/sdm429-thermal.dtsi | 706 +++++++++++++++++++ arch/arm64/boot/dts/qcom/sdm429.dtsi | 12 + arch/arm64/boot/dts/qcom/sdm429w-pm660.dtsi | 160 +++++ 4 files changed, 978 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/sdm429-thermal.dtsi diff --git a/arch/arm64/boot/dts/qcom/pm660.dtsi b/arch/arm64/boot/dts/qcom/pm660.dtsi index 7ebb230eb269..a26ed10d7dc5 100644 --- a/arch/arm64/boot/dts/qcom/pm660.dtsi +++ b/arch/arm64/boot/dts/qcom/pm660.dtsi @@ -551,6 +551,106 @@ }; &thermal_zones { + ibat-high { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-governor = "step_wise"; + thermal-sensors = <&bcl_sensor 0>; + wake-capable-sensor; + + trips { + ibat-high { + temperature = <4200>; + hysteresis = <200>; + type = "passive"; + }; + }; + }; + + ibat-vhigh { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-governor = "step_wise"; + thermal-sensors = <&bcl_sensor 1>; + wake-capable-sensor; + + trips { + ibat-vhigh { + temperature = <4300>; + hysteresis = <100>; + type = "passive"; + }; + }; + }; + + vbat_adc { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-governor = "low_limits_cap"; + thermal-sensors = <&bcl_sensor 2>; + wake-capable-sensor; + tracks-low; + + trips { + pm660_vbat_adc: vbat-adc { + temperature = <3200>; + hysteresis = <100>; + type = "passive"; + }; + }; + }; + + vbat_low { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-governor = "low_limits_cap"; + thermal-sensors = <&bcl_sensor 3>; + wake-capable-sensor; + tracks-low; + + trips { + vbat-low { + temperature = <2800>; + hysteresis = <0>; + type = "passive"; + }; + }; + }; + + vbat_too_low { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-governor = "low_limits_cap"; + thermal-sensors = <&bcl_sensor 4>; + wake-capable-sensor; + tracks-low; + + trips { + vbat-too-low { + temperature = <2600>; + hysteresis = <0>; + type = "passive"; + }; + }; + }; + + soc { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-governor = "low_limits_cap"; + thermal-sensors = <&bcl_sensor 5>; + wake-capable-sensor; + tracks-low; + + trips { + pm660_low_soc: low-soc { + temperature = <10>; + hysteresis = <0>; + type = "passive"; + }; + }; + }; + pm660_temp_alarm: pm660-tz { polling-delay-passive = <0>; polling-delay = <0>; diff --git a/arch/arm64/boot/dts/qcom/sdm429-thermal.dtsi b/arch/arm64/boot/dts/qcom/sdm429-thermal.dtsi new file mode 100644 index 000000000000..a7d1b7635fc8 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sdm429-thermal.dtsi @@ -0,0 +1,706 @@ +/* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include + +&soc { + qmi-tmd-devices { + compatible = "qcom,qmi-cooling-devices"; + + modem { + qcom,instance-id = <0x0>; + + modem_pa: modem_pa { + qcom,qmi-dev-name = "pa"; + #cooling-cells = <2>; + }; + + modem_proc: modem_proc { + qcom,qmi-dev-name = "modem"; + #cooling-cells = <2>; + }; + + modem_current: modem_current { + qcom,qmi-dev-name = "modem_current"; + #cooling-cells = <2>; + }; + + modem_vdd: modem_vdd { + qcom,qmi-dev-name = "cpuv_restriction_cold"; + #cooling-cells = <2>; + }; + }; + }; +}; + +&thermal_zones { + aoss0-usr { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-governor = "user_space"; + thermal-sensors = <&tsens0 0>; + wake-capable-sensor; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + mdm-core-usr { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-governor = "user_space"; + thermal-sensors = <&tsens0 1>; + wake-capable-sensor; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + lpass-usr { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-governor = "user_space"; + thermal-sensors = <&tsens0 2>; + wake-capable-sensor; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + camera-usr { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-governor = "user_space"; + thermal-sensors = <&tsens0 3>; + wake-capable-sensor; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + cpuss1-usr { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens0 4>; + thermal-governor = "user_space"; + wake-capable-sensor; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + apc1-cpu0-usr { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens0 5>; + thermal-governor = "user_space"; + wake-capable-sensor; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + apc1-cpu1-usr { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens0 6>; + thermal-governor = "user_space"; + wake-capable-sensor; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + apc1-cpu2-usr { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens0 7>; + thermal-governor = "user_space"; + wake-capable-sensor; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + apc1-cpu3-usr { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens0 8>; + thermal-governor = "user_space"; + wake-capable-sensor; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + cpuss0-usr { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens0 9>; + thermal-governor = "user_space"; + wake-capable-sensor; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + gpu-usr { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens0 10>; + thermal-governor = "user_space"; + wake-capable-sensor; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + gpu-step { + polling-delay-passive = <250>; + polling-delay = <0>; + thermal-sensors = <&tsens0 10>; + thermal-governor = "step_wise"; + wake-capable-sensor; + trips { + gpu_step_trip: gpu-step-trip { + temperature = <95000>; + hysteresis = <0>; + type = "passive"; + }; + }; + cooling-maps { + gpu_cdev0 { + trip = <&gpu_step_trip>; + cooling-device = + <&msm_gpu THERMAL_NO_LIMIT + THERMAL_NO_LIMIT>; + }; + }; + }; + + hexa-cpu-max-step { + polling-delay-passive = <50>; + polling-delay = <100>; + thermal-governor = "step_wise"; + wake-capable-sensor; + trips { + cpu_trip:cpu-trip { + temperature = <85000>; + hysteresis = <0>; + type = "passive"; + }; + }; + cooling-maps { + cpu0_cdev { + trip = <&cpu_trip>; + cooling-device = + <&CPU0 THERMAL_NO_LIMIT + (THERMAL_MAX_LIMIT-1)>; + }; + cpu1_cdev { + trip = <&cpu_trip>; + cooling-device = + <&CPU1 THERMAL_NO_LIMIT + (THERMAL_MAX_LIMIT-1)>; + }; + cpu2_cdev { + trip = <&cpu_trip>; + cooling-device = + <&CPU2 THERMAL_NO_LIMIT + (THERMAL_MAX_LIMIT-1)>; + }; + cpu3_cdev { + trip = <&cpu_trip>; + cooling-device = + <&CPU3 THERMAL_NO_LIMIT + (THERMAL_MAX_LIMIT-1)>; + }; + }; + }; + + apc1-cpu0-step { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens0 5>; + thermal-governor = "step_wise"; + wake-capable-sensor; + trips { + apc1_cpu0_trip: apc1-cpu0-trip { + temperature = <105000>; + hysteresis = <15000>; + type = "passive"; + }; + }; + cooling-maps { + cpu0_cdev { + trip = <&apc1_cpu0_trip>; + cooling-device = + <&CPU0 THERMAL_MAX_LIMIT + THERMAL_MAX_LIMIT>; + }; + }; + }; + + apc1-cpu1-step { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens0 6>; + thermal-governor = "step_wise"; + wake-capable-sensor; + trips { + apc1_cpu1_trip: apc1-cpu1-trip { + temperature = <105000>; + hysteresis = <15000>; + type = "passive"; + }; + }; + cooling-maps { + cpu1_cdev { + trip = <&apc1_cpu1_trip>; + cooling-device = + <&CPU1 THERMAL_MAX_LIMIT + THERMAL_MAX_LIMIT>; + }; + }; + }; + + apc1-cpu2-step { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens0 7>; + thermal-governor = "step_wise"; + wake-capable-sensor; + trips { + apc1_cpu2_trip: apc1-cpu2-trip { + temperature = <105000>; + hysteresis = <15000>; + type = "passive"; + }; + }; + cooling-maps { + cpu2_cdev { + trip = <&apc1_cpu2_trip>; + cooling-device = + <&CPU2 THERMAL_MAX_LIMIT + THERMAL_MAX_LIMIT>; + }; + }; + }; + + apc1-cpu3-step { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens0 8>; + thermal-governor = "step_wise"; + wake-capable-sensor; + trips { + apc1_cpu3_trip: apc1-cpu3-trip { + temperature = <105000>; + hysteresis = <15000>; + type = "passive"; + }; + }; + cooling-maps { + cpu3_cdev { + trip = <&apc1_cpu3_trip>; + cooling-device = + <&CPU3 THERMAL_MAX_LIMIT + THERMAL_MAX_LIMIT>; + }; + }; + }; + + aoss0-lowf { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-governor = "low_limits_floor"; + thermal-sensors = <&tsens0 0>; + wake-capable-sensor; + tracks-low; + trips { + aoss0_trip: aoss-trip { + temperature = <5000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + cooling-maps { + cpu0_vdd_cdev { + trip = <&aoss0_trip>; + cooling-device = <&CPU0 (THERMAL_MAX_LIMIT-2) + (THERMAL_MAX_LIMIT-2)>; + }; + cx_vdd_cdev { + trip = <&aoss0_trip>; + cooling-device = <&pm660_cx_cdev 0 0>; + }; + modem_vdd_cdev { + trip = <&aoss0_trip>; + cooling-device = <&modem_vdd 0 0>; + }; + }; + }; + + mdm-core-lowf { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-governor = "low_limits_floor"; + thermal-sensors = <&tsens0 1>; + wake-capable-sensor; + tracks-low; + trips { + mdm_core_trip: mdm-core-trip { + temperature = <5000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + cooling-maps { + cpu0_vdd_cdev { + trip = <&mdm_core_trip>; + cooling-device = <&CPU0 (THERMAL_MAX_LIMIT-2) + (THERMAL_MAX_LIMIT-2)>; + }; + cx_vdd_cdev { + trip = <&mdm_core_trip>; + cooling-device = <&pm660_cx_cdev 0 0>; + }; + modem_vdd_cdev { + trip = <&mdm_core_trip>; + cooling-device = <&modem_vdd 0 0>; + }; + }; + }; + + lpass-lowf { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-governor = "low_limits_floor"; + thermal-sensors = <&tsens0 2>; + wake-capable-sensor; + tracks-low; + trips { + qdsp_trip: qdsp-trip { + temperature = <5000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + cooling-maps { + cpu0_vdd_cdev { + trip = <&qdsp_trip>; + cooling-device = <&CPU0 (THERMAL_MAX_LIMIT-2) + (THERMAL_MAX_LIMIT-2)>; + }; + cx_vdd_cdev { + trip = <&qdsp_trip>; + cooling-device = <&pm660_cx_cdev 0 0>; + }; + modem_vdd_cdev { + trip = <&qdsp_trip>; + cooling-device = <&modem_vdd 0 0>; + }; + }; + }; + + camera-lowf { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-governor = "low_limits_floor"; + thermal-sensors = <&tsens0 3>; + wake-capable-sensor; + tracks-low; + trips { + camera_trip: camera-trip { + temperature = <5000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + cooling-maps { + cpu0_vdd_cdev { + trip = <&camera_trip>; + cooling-device = <&CPU0 (THERMAL_MAX_LIMIT-2) + (THERMAL_MAX_LIMIT-2)>; + }; + cx_vdd_cdev { + trip = <&camera_trip>; + cooling-device = <&pm660_cx_cdev 0 0>; + }; + modem_vdd_cdev { + trip = <&camera_trip>; + cooling-device = <&modem_vdd 0 0>; + }; + }; + }; + + cpuss1-lowf { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-governor = "low_limits_floor"; + thermal-sensors = <&tsens0 4>; + wake-capable-sensor; + tracks-low; + trips { + cpuss1_trip: cpuss1-trip { + temperature = <5000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + cooling-maps { + cpu0_vdd_cdev { + trip = <&cpuss1_trip>; + cooling-device = <&CPU0 (THERMAL_MAX_LIMIT-2) + (THERMAL_MAX_LIMIT-2)>; + }; + cx_vdd_cdev { + trip = <&cpuss1_trip>; + cooling-device = <&pm660_cx_cdev 0 0>; + }; + modem_vdd_cdev { + trip = <&cpuss1_trip>; + cooling-device = <&modem_vdd 0 0>; + }; + }; + }; + + apc1-cpu0-lowf { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-governor = "low_limits_floor"; + thermal-sensors = <&tsens0 5>; + wake-capable-sensor; + tracks-low; + trips { + cpu0_trip: apc1-cpu0-trip { + temperature = <5000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + cooling-maps { + cpu0_vdd_cdev { + trip = <&cpu0_trip>; + cooling-device = <&CPU0 (THERMAL_MAX_LIMIT-2) + (THERMAL_MAX_LIMIT-2)>; + }; + cx_vdd_cdev { + trip = <&cpu0_trip>; + cooling-device = <&pm660_cx_cdev 0 0>; + }; + modem_vdd_cdev { + trip = <&cpu0_trip>; + cooling-device = <&modem_vdd 0 0>; + }; + }; + }; + + apc1-cpu1-lowf { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-governor = "low_limits_floor"; + thermal-sensors = <&tsens0 6>; + wake-capable-sensor; + tracks-low; + trips { + cpu1_trip: apc1-cpu1-trip { + temperature = <5000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + cooling-maps { + cpu0_vdd_cdev { + trip = <&cpu1_trip>; + cooling-device = <&CPU0 (THERMAL_MAX_LIMIT-2) + (THERMAL_MAX_LIMIT-2)>; + }; + cx_vdd_cdev { + trip = <&cpu1_trip>; + cooling-device = <&pm660_cx_cdev 0 0>; + }; + modem_vdd_cdev { + trip = <&cpu1_trip>; + cooling-device = <&modem_vdd 0 0>; + }; + }; + }; + + apc1-cpu2-lowf { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-governor = "low_limits_floor"; + thermal-sensors = <&tsens0 7>; + wake-capable-sensor; + tracks-low; + trips { + cpu2_trip: apc1-cpu2-trip { + temperature = <5000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + cooling-maps { + cpu0_vdd_cdev { + trip = <&cpu2_trip>; + cooling-device = <&CPU0 (THERMAL_MAX_LIMIT-2) + (THERMAL_MAX_LIMIT-2)>; + }; + cx_vdd_cdev { + trip = <&cpu2_trip>; + cooling-device = <&pm660_cx_cdev 0 0>; + }; + modem_vdd_cdev { + trip = <&cpu2_trip>; + cooling-device = <&modem_vdd 0 0>; + }; + }; + }; + + apc1-cpu3-lowf { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-governor = "low_limits_floor"; + thermal-sensors = <&tsens0 8>; + wake-capable-sensor; + tracks-low; + trips { + cpu3_trip: apc1-cpu3-trip { + temperature = <5000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + cooling-maps { + cpu0_vdd_cdev { + trip = <&cpu3_trip>; + cooling-device = <&CPU0 (THERMAL_MAX_LIMIT-2) + (THERMAL_MAX_LIMIT-2)>; + }; + cx_vdd_cdev { + trip = <&cpu3_trip>; + cooling-device = <&pm660_cx_cdev 0 0>; + }; + modem_vdd_cdev { + trip = <&cpu3_trip>; + cooling-device = <&modem_vdd 0 0>; + }; + }; + }; + + cpuss0-lowf { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-governor = "low_limits_floor"; + thermal-sensors = <&tsens0 9>; + wake-capable-sensor; + tracks-low; + trips { + cpuss0_lowf_trip: cpuss0-lowf-trip { + temperature = <5000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + cooling-maps { + cpu0_vdd_cdev { + trip = <&cpuss0_lowf_trip>; + cooling-device = <&CPU0 (THERMAL_MAX_LIMIT-2) + (THERMAL_MAX_LIMIT-2)>; + }; + cx_vdd_cdev { + trip = <&cpuss0_lowf_trip>; + cooling-device = <&pm660_cx_cdev 0 0>; + }; + modem_vdd_cdev { + trip = <&cpuss0_lowf_trip>; + cooling-device = <&modem_vdd 0 0>; + }; + }; + }; + + gpu-lowf { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-governor = "low_limits_floor"; + thermal-sensors = <&tsens0 10>; + wake-capable-sensor; + tracks-low; + trips { + gpu_lowf_trip: gpu-lowf-trip { + temperature = <5000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + cooling-maps { + cpu0_vdd_cdev { + trip = <&gpu_lowf_trip>; + cooling-device = <&CPU0 (THERMAL_MAX_LIMIT-2) + (THERMAL_MAX_LIMIT-2)>; + }; + cx_vdd_cdev { + trip = <&gpu_lowf_trip>; + cooling-device = <&pm660_cx_cdev 0 0>; + }; + modem_vdd_cdev { + trip = <&gpu_lowf_trip>; + cooling-device = <&modem_vdd 0 0>; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sdm429.dtsi b/arch/arm64/boot/dts/qcom/sdm429.dtsi index b7e4f9567998..264abdc06820 100644 --- a/arch/arm64/boot/dts/qcom/sdm429.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm429.dtsi @@ -1420,6 +1420,17 @@ < 1708800 MHZ_TO_MBPS( 749, 8) >; }; + tsens0: tsens@4a8000 { + compatible = "qcom,msm8937-tsens"; + reg = <0x4a8000 0x1000>, + <0x4a9000 0x1000>, + <0xa4000 0x1000>; + reg-names = "tsens_srot_physical", + "tsens_tm_physical", "tsens_eeprom_physical"; + interrupts = <0 184 0>; + interrupt-names = "tsens-upper-lower"; + #thermal-sensor-cells = <1>; + }; }; #include "sdm429-gdsc.dtsi" @@ -1428,6 +1439,7 @@ #include "sdm429-mdss.dtsi" #include "sdm429-mdss-pll.dtsi" #include "sdm429-audio.dtsi" +#include "sdm429-thermal.dtsi" &venus_gdsc { clock-names = "bus_clk", "core_clk"; diff --git a/arch/arm64/boot/dts/qcom/sdm429w-pm660.dtsi b/arch/arm64/boot/dts/qcom/sdm429w-pm660.dtsi index 1cf4c8ad62a0..b1586250aa47 100644 --- a/arch/arm64/boot/dts/qcom/sdm429w-pm660.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm429w-pm660.dtsi @@ -165,6 +165,8 @@ }; }; +#include + &thermal_zones { xo-therm-adc { polling-delay-passive = <0>; @@ -245,6 +247,164 @@ }; }; }; + + quiet-therm-step { + polling-delay-passive = <1000>; + polling-delay = <0>; + thermal-sensors = <&pm660_adc_tm 0x51>; + thermal-governor = "step_wise"; + wake-capable-sensor; + + trips { + quiet_batt_439_trip1: quiet-batt-trip1 { + temperature = <38000>; + hysteresis = <2000>; + type = "passive"; + }; + + quiet_batt_439_trip2: quiet-batt-trip2 { + temperature = <40000>; + hysteresis = <2000>; + type = "passive"; + }; + + quiet_batt_439_trip3: quiet-batt-trip3 { + temperature = <42000>; + hysteresis = <2000>; + type = "passive"; + }; + + quiet_batt_439_trip4: quiet-batt-trip4 { + temperature = <44000>; + hysteresis = <2000>; + type = "passive"; + }; + + quiet_modem_439_trip1: quiet-modem-trip0 { + temperature = <44000>; + hysteresis = <4000>; + type = "passive"; + }; + + quiet_modem_439_trip2: quiet-modem-trip1 { + temperature = <46000>; + hysteresis = <4000>; + type = "passive"; + }; + + quiet_batt_439_trip5: quiet-batt-trip5 { + temperature = <46000>; + hysteresis = <2000>; + type = "passive"; + }; + + quiet_modem_439_trip3: quiet-modem-trp3 { + temperature = <48000>; + hysteresis = <2000>; + type = "passive"; + }; + + quiet_cpus_439_trip: quiet-cpus-trip { + temperature = <48000>; + hysteresis = <0>; + type = "passive"; + }; + + quiet_batt_439_trip6: quiet-batt-trip6 { + temperature = <55000>; + hysteresis = <2000>; + type = "passive"; + }; + + quiet_modem_439_trip4: quiet-modem-trip3 { + temperature = <55000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + + cooling-maps { + skin_cpu0 { + trip = <&quiet_cpus_439_trip>; + /* throttle from fmax to 1497600KHz */ + cooling-device = <&CPU0 THERMAL_NO_LIMIT + (THERMAL_MAX_LIMIT-3)>; + }; + + skin_cpu1 { + trip = <&quiet_cpus_439_trip>; + cooling-device = <&CPU1 THERMAL_NO_LIMIT + (THERMAL_MAX_LIMIT-3)>; + }; + + skin_cpu2 { + trip = <&quiet_cpus_439_trip>; + cooling-device = <&CPU2 THERMAL_NO_LIMIT + (THERMAL_MAX_LIMIT-3)>; + }; + + skin_cpu3 { + trip = <&quiet_cpus_439_trip>; + cooling-device = <&CPU3 THERMAL_NO_LIMIT + (THERMAL_MAX_LIMIT-3)>; + }; + + modem_proc_lvl1 { + trip = <&quiet_modem_439_trip1>; + cooling-device = <&modem_proc 1 1>; + }; + + modem_proc_lvl2 { + trip = <&quiet_modem_439_trip4>; + cooling-device = <&modem_proc 3 3>; + }; + + modem_lvl1 { + trip = <&quiet_modem_439_trip2>; + cooling-device = <&modem_pa 1 1>; + }; + + modem_lvl2 { + trip = <&quiet_modem_439_trip3>; + cooling-device = <&modem_pa 2 2>; + }; + + modem_lvl3 { + trip = <&quiet_modem_439_trip4>; + cooling-device = <&modem_pa 3 3>; + }; + + battery_lvl1 { + trip = <&quiet_batt_439_trip1>; + cooling-device = <&pm660_charger 1 1>; + }; + + battery_lvl2 { + trip = <&quiet_batt_439_trip2>; + cooling-device = <&pm660_charger 2 2>; + }; + + battery_lvl3 { + trip = <&quiet_batt_439_trip3>; + cooling-device = <&pm660_charger 3 3>; + }; + + battery_lvl4 { + trip = <&quiet_batt_439_trip4>; + cooling-device = <&pm660_charger 4 4>; + }; + + battery_lvl5 { + trip = <&quiet_batt_439_trip5>; + cooling-device = <&pm660_charger 5 5>; + }; + + battery_lvl6 { + trip = <&quiet_batt_439_trip6>; + cooling-device = <&pm660_charger 6 6>; + }; + }; + }; }; &usb_otg { From 3eeac3ad78fce18abd270eaf9fc82cee35d7095b Mon Sep 17 00:00:00 2001 From: Chandrasekhar Mattaparthy Date: Fri, 31 Jul 2020 18:20:23 +0530 Subject: [PATCH 350/592] ARM: dts: msm: enable fuel gauge driver enable fuel gauge driver for new kernel to report battery level. Change-Id: I507ea68f97aaea7e7008c37e30840eb676fed77e Signed-off-by: Chandrasekhar Mattaparthy --- arch/arm64/boot/dts/qcom/sdm429w-pm660.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/sdm429w-pm660.dtsi b/arch/arm64/boot/dts/qcom/sdm429w-pm660.dtsi index 1cf4c8ad62a0..39b189e7096e 100644 --- a/arch/arm64/boot/dts/qcom/sdm429w-pm660.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm429w-pm660.dtsi @@ -122,7 +122,7 @@ qcom,fg-bmd-en-delay-ms = <300>; qcom,fg-force-load-profile; qcom,fg-jeita-thresholds = <0 20 45 60>; - status = "disabled"; + status = "ok"; }; &pm660_haptics { From 53ca7b624dc63bffee581ab128016705e7790328 Mon Sep 17 00:00:00 2001 From: Surendar karka Date: Tue, 2 Jun 2020 11:57:11 +0530 Subject: [PATCH 351/592] uapi: sound: add TTP pass through run mode command Add RUN_WITH_TTP_PASS_THROUGH run mode to support split A2Dp source usecase with TTP. Change-Id: I0490464b4620dcde9b777d6d48b1e25ecd3eca7b Signed-off-by: Surendar karka --- include/uapi/sound/compress_offload.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/uapi/sound/compress_offload.h b/include/uapi/sound/compress_offload.h index 5f0fd5ebb94a..3a50f6ca1619 100644 --- a/include/uapi/sound/compress_offload.h +++ b/include/uapi/sound/compress_offload.h @@ -137,6 +137,7 @@ struct snd_compr_audio_info { #define SNDRV_COMPRESS_RENDER_MODE_AUDIO_MASTER 0 #define SNDRV_COMPRESS_RENDER_MODE_STC_MASTER 1 #define SNDRV_COMPRESS_RENDER_MODE_TTP 2 +#define SNDRV_COMPRESS_RENDER_MODE_TTP_PASS_THROUGH 3 #define SNDRV_COMPRESS_CLK_REC_MODE_NONE 0 #define SNDRV_COMPRESS_CLK_REC_MODE_AUTO 1 From f5315064399244665f5ce18e861e17ef8d5dfd97 Mon Sep 17 00:00:00 2001 From: Nitesh Gupta Date: Tue, 28 Jul 2020 18:52:35 +0530 Subject: [PATCH 352/592] msm: ep_pcie: set irq flag to IRQF_EARLY_RESUME for PERST irq All interrupts get disabled during system suspend and enabled during system resume. The enabling/disabling of interrupts happen in sequence of interrupt registration with framework. Set flag for early resume so that PERST interrupt get enabled before parent interrupt. Change-Id: Icccf8d2968832d9dc88e4f7c16b2d8fc6597698e Signed-off-by: Nitesh Gupta --- drivers/platform/msm/ep_pcie/ep_pcie_core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/platform/msm/ep_pcie/ep_pcie_core.c b/drivers/platform/msm/ep_pcie/ep_pcie_core.c index d3c79d7a2912..adae05919994 100644 --- a/drivers/platform/msm/ep_pcie/ep_pcie_core.c +++ b/drivers/platform/msm/ep_pcie/ep_pcie_core.c @@ -2558,7 +2558,8 @@ perst_irq: perst_irq = gpio_to_irq(dev->gpio[EP_PCIE_GPIO_PERST].num); ret = devm_request_irq(pdev, perst_irq, ep_pcie_handle_perst_irq, - (dev->perst_deast ? IRQF_TRIGGER_LOW : IRQF_TRIGGER_HIGH), + ((dev->perst_deast ? IRQF_TRIGGER_LOW : IRQF_TRIGGER_HIGH) + | IRQF_EARLY_RESUME), "ep_pcie_perst", dev); if (ret) { EP_PCIE_ERR(dev, From 4833a0841109c23c065696a14f2802d0d65f7448 Mon Sep 17 00:00:00 2001 From: Rishi Gupta Date: Sun, 12 Jul 2020 21:27:41 +0530 Subject: [PATCH 353/592] ARM: dts: sa515m: correct sideband wakeup gpio numbers This commit populates gpio numbers as per sa515m ccard55 and moves sideband wake up specific nodes and properties to ccard specific device tree files from common device tree file. Change-Id: I4f162972dbabcb458424b5b76509cc42080ff753 Signed-off-by: Rishi Gupta --- arch/arm64/boot/dts/qcom/sa515m-ccard.dtsi | 14 ++++++++++++++ arch/arm64/boot/dts/qcom/sdxprairie-pinctrl.dtsi | 13 ------------- arch/arm64/boot/dts/qcom/sdxprairie.dtsi | 4 ---- 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sa515m-ccard.dtsi b/arch/arm64/boot/dts/qcom/sa515m-ccard.dtsi index 6504d82f6f3a..251b24cce5f1 100644 --- a/arch/arm64/boot/dts/qcom/sa515m-ccard.dtsi +++ b/arch/arm64/boot/dts/qcom/sa515m-ccard.dtsi @@ -643,3 +643,17 @@ }; }; }; + +&tlmm { + wakeup_gpio_default: wakeup_gpio_default { + mux { + pins = "gpio96"; + function = "gpio"; + }; + config { + pins = "gpio96"; + drive-strength = <2>; + bias-pull-down; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sdxprairie-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/sdxprairie-pinctrl.dtsi index aaf72774fa18..edba1fd6cdbb 100644 --- a/arch/arm64/boot/dts/qcom/sdxprairie-pinctrl.dtsi +++ b/arch/arm64/boot/dts/qcom/sdxprairie-pinctrl.dtsi @@ -1685,18 +1685,5 @@ bias-pull-down; }; }; - - wakeup_gpio_default: wakeup_gpio_default { - mux { - pins = "gpio22"; - function = "gpio"; - }; - - config { - pins = "gpio22"; - drive-strength = <2>; - bias-pull-down; - }; - }; }; }; diff --git a/arch/arm64/boot/dts/qcom/sdxprairie.dtsi b/arch/arm64/boot/dts/qcom/sdxprairie.dtsi index e2327a27c58e..ae83aacc0450 100644 --- a/arch/arm64/boot/dts/qcom/sdxprairie.dtsi +++ b/arch/arm64/boot/dts/qcom/sdxprairie.dtsi @@ -1607,10 +1607,6 @@ qcom,status-in-gpio = <&tlmm 64 0x00>; qcom,status-out-gpio = <&tlmm 63 0x00>; qcom,status-out2-gpio = <&tlmm 66 0x00>; - qcom,wakeup-gpio-in = <&tlmm 87 0x00>; - qcom,wakeup-gpio-out = <&tlmm 22 0x00>; - pinctrl-names = "default"; - pinctrl-0 = <&wakeup_gpio_default>; status = "disabled"; }; }; From c402cceac266f87b0e846b334cf6ec7f18cafe3f Mon Sep 17 00:00:00 2001 From: Rishi Gupta Date: Sun, 12 Jul 2020 21:33:08 +0530 Subject: [PATCH 354/592] ARM: dts: sa515m: enable ssr and wake up sideband support This commit enables sideband SSR and wake up support for USB and Ethernet interconnect and unifies the device tree node declarations among all interconnect types. Change-Id: I970641693364f6b48b7e1c0066d5bb0b36bc7c65 Signed-off-by: Rishi Gupta --- arch/arm64/boot/dts/qcom/sa515m-ccard-eth-ep.dts | 13 +++++++++++++ arch/arm64/boot/dts/qcom/sa515m-ccard-pcie-ep.dts | 4 ++++ arch/arm64/boot/dts/qcom/sa515m-ccard-usb-ep.dts | 13 +++++++++++++ arch/arm64/boot/dts/qcom/sa515m-v2-ccard-eth-ep.dts | 13 +++++++++++++ .../arm64/boot/dts/qcom/sa515m-v2-ccard-pcie-ep.dts | 11 ++++++----- arch/arm64/boot/dts/qcom/sa515m-v2-ccard-usb-ep.dts | 13 +++++++++++++ 6 files changed, 62 insertions(+), 5 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sa515m-ccard-eth-ep.dts b/arch/arm64/boot/dts/qcom/sa515m-ccard-eth-ep.dts index 67e23a084989..7523ffe8312f 100644 --- a/arch/arm64/boot/dts/qcom/sa515m-ccard-eth-ep.dts +++ b/arch/arm64/boot/dts/qcom/sa515m-ccard-eth-ep.dts @@ -41,3 +41,16 @@ &usb { qcom,smmu-s1-bypass; }; + +&sdx_ext_ipc { + compatible = "qcom,sa515m-ccard"; + qcom,status-in-gpio = <&tlmm 76 0x00>; + qcom,status-out-gpio = <&tlmm 33 0x00>; + qcom,status-out2-gpio = <&tlmm 31 0x00>; + qcom,wakeup-gpio-in = <&tlmm 77 0x00>; + qcom,wakeup-gpio-out = <&tlmm 96 0x00>; + pinctrl-names = "default"; + pinctrl-0 = <&wakeup_gpio_default>; + qcom,default-policy-nop; + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/qcom/sa515m-ccard-pcie-ep.dts b/arch/arm64/boot/dts/qcom/sa515m-ccard-pcie-ep.dts index 81786435e82c..ff3f04b02f67 100644 --- a/arch/arm64/boot/dts/qcom/sa515m-ccard-pcie-ep.dts +++ b/arch/arm64/boot/dts/qcom/sa515m-ccard-pcie-ep.dts @@ -73,6 +73,10 @@ }; &sdx_ext_ipc { + compatible = "qcom,sa515m-ccard"; + qcom,status-in-gpio = <&tlmm 76 0x00>; + qcom,status-out-gpio = <&tlmm 33 0x00>; + qcom,status-out2-gpio = <&tlmm 31 0x00>; qcom,default-policy-nop; status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/sa515m-ccard-usb-ep.dts b/arch/arm64/boot/dts/qcom/sa515m-ccard-usb-ep.dts index 1053f3273f31..7bd2e445adf7 100644 --- a/arch/arm64/boot/dts/qcom/sa515m-ccard-usb-ep.dts +++ b/arch/arm64/boot/dts/qcom/sa515m-ccard-usb-ep.dts @@ -56,3 +56,16 @@ &usb { qcom,num-gsi-evt-buffs = <0x5>; }; + +&sdx_ext_ipc { + compatible = "qcom,sa515m-ccard"; + qcom,status-in-gpio = <&tlmm 76 0x00>; + qcom,status-out-gpio = <&tlmm 33 0x00>; + qcom,status-out2-gpio = <&tlmm 31 0x00>; + qcom,wakeup-gpio-in = <&tlmm 77 0x00>; + qcom,wakeup-gpio-out = <&tlmm 96 0x00>; + pinctrl-names = "default"; + pinctrl-0 = <&wakeup_gpio_default>; + qcom,default-policy-nop; + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/qcom/sa515m-v2-ccard-eth-ep.dts b/arch/arm64/boot/dts/qcom/sa515m-v2-ccard-eth-ep.dts index 9eeb1c42076f..e0a7d29a6b27 100644 --- a/arch/arm64/boot/dts/qcom/sa515m-v2-ccard-eth-ep.dts +++ b/arch/arm64/boot/dts/qcom/sa515m-v2-ccard-eth-ep.dts @@ -41,3 +41,16 @@ &usb { qcom,smmu-s1-bypass; }; + +&sdx_ext_ipc { + compatible = "qcom,sa515m-ccard"; + qcom,status-in-gpio = <&tlmm 76 0x00>; + qcom,status-out-gpio = <&tlmm 33 0x00>; + qcom,status-out2-gpio = <&tlmm 31 0x00>; + qcom,wakeup-gpio-in = <&tlmm 77 0x00>; + qcom,wakeup-gpio-out = <&tlmm 96 0x00>; + pinctrl-names = "default"; + pinctrl-0 = <&wakeup_gpio_default>; + qcom,default-policy-nop; + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/qcom/sa515m-v2-ccard-pcie-ep.dts b/arch/arm64/boot/dts/qcom/sa515m-v2-ccard-pcie-ep.dts index ebeac7624478..3b49920ff05c 100644 --- a/arch/arm64/boot/dts/qcom/sa515m-v2-ccard-pcie-ep.dts +++ b/arch/arm64/boot/dts/qcom/sa515m-v2-ccard-pcie-ep.dts @@ -74,9 +74,10 @@ }; &sdx_ext_ipc { - compatible = "qcom,sa515m-ccard"; - qcom,status-in-gpio = <&tlmm 76 0x00>; - qcom,status-out-gpio = <&tlmm 33 0x00>; - qcom,status-out2-gpio = <&tlmm 31 0x00>; - status = "okay"; + compatible = "qcom,sa515m-ccard"; + qcom,status-in-gpio = <&tlmm 76 0x00>; + qcom,status-out-gpio = <&tlmm 33 0x00>; + qcom,status-out2-gpio = <&tlmm 31 0x00>; + qcom,default-policy-nop; + status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/sa515m-v2-ccard-usb-ep.dts b/arch/arm64/boot/dts/qcom/sa515m-v2-ccard-usb-ep.dts index 9734f0b88ab4..fe78525bc062 100644 --- a/arch/arm64/boot/dts/qcom/sa515m-v2-ccard-usb-ep.dts +++ b/arch/arm64/boot/dts/qcom/sa515m-v2-ccard-usb-ep.dts @@ -56,3 +56,16 @@ &usb { qcom,num-gsi-evt-buffs = <0x5>; }; + +&sdx_ext_ipc { + compatible = "qcom,sa515m-ccard"; + qcom,status-in-gpio = <&tlmm 76 0x00>; + qcom,status-out-gpio = <&tlmm 33 0x00>; + qcom,status-out2-gpio = <&tlmm 31 0x00>; + qcom,wakeup-gpio-in = <&tlmm 77 0x00>; + qcom,wakeup-gpio-out = <&tlmm 96 0x00>; + pinctrl-names = "default"; + pinctrl-0 = <&wakeup_gpio_default>; + qcom,default-policy-nop; + status = "okay"; +}; From db67b69c76bb885d18651f5b0bde8971da118a22 Mon Sep 17 00:00:00 2001 From: Ashok Vuyyuru Date: Mon, 20 Jul 2020 14:45:50 +0530 Subject: [PATCH 355/592] msm: ipa3: Fix to unmap sgt pages with correct size scatterlist pages not unmapped properly, it was leading to issue when mapping the same pages again. Adding changes to store scatterlist information properly and unmap the page with correct length. Change-Id: If11926608f633ce1d66150b1e4b6c515adc48049 Signed-off-by: Ashok Vuyyuru --- drivers/platform/msm/ipa/ipa_api.c | 2 +- drivers/platform/msm/ipa/ipa_v3/ipa_client.c | 35 +++++++++++++++----- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_api.c b/drivers/platform/msm/ipa/ipa_api.c index 755910c02582..7579988bc919 100644 --- a/drivers/platform/msm/ipa/ipa_api.c +++ b/drivers/platform/msm/ipa/ipa_api.c @@ -381,7 +381,7 @@ int ipa_smmu_store_sgt(struct sg_table **out_ch_ptr, } memcpy((*out_ch_ptr)->sgl, in_sgt_ptr->sgl, - nents*sizeof((*out_ch_ptr)->sgl)); + nents*sizeof(struct scatterlist)); (*out_ch_ptr)->nents = nents; (*out_ch_ptr)->orig_nents = in_sgt_ptr->orig_nents; } diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c index 96ef459437cd..1f7ab697f918 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c @@ -433,14 +433,33 @@ int ipa3_smmu_map_peer_buff(u64 iova, u32 size, bool map, struct sg_table *sgt, } } } else { - res = iommu_unmap(smmu_domain, - rounddown(iova, PAGE_SIZE), - roundup(size + iova - rounddown(iova, PAGE_SIZE), - PAGE_SIZE)); - if (res != roundup(size + iova - rounddown(iova, PAGE_SIZE), - PAGE_SIZE)) { - IPAERR("Fail to unmap 0x%llx\n", iova); - return -EINVAL; + if (sgt != NULL) { + va = rounddown(iova, PAGE_SIZE); + len = 0; + for_each_sg(sgt->sgl, sg, sgt->nents, i) { + len = PAGE_ALIGN(sg->offset + sg->length); + res = iommu_unmap(smmu_domain, va, + roundup(len, PAGE_SIZE)); + if (res != + roundup(len, PAGE_SIZE)) { + IPAERR("Fail to unmap iova=%llx\n", + iova); + return -EINVAL; + } + va += len; + count++; + } + } else { + res = iommu_unmap(smmu_domain, + rounddown(iova, PAGE_SIZE), + roundup(size + iova - + rounddown(iova, PAGE_SIZE), + PAGE_SIZE)); + if (res != roundup(size + iova - + rounddown(iova, PAGE_SIZE), PAGE_SIZE)) { + IPAERR("Fail to unmap 0x%llx\n", iova); + return -EINVAL; + } } } IPADBG("Peer buff %s 0x%llx\n", map ? "map" : "unmap", iova); From 3f788addf8d61d0df855bd3bcf2e69b34d8fab63 Mon Sep 17 00:00:00 2001 From: Ashish Chavan Date: Wed, 29 Jul 2020 09:32:06 +0530 Subject: [PATCH 356/592] power: smb1390: Fix taper condition for VPH configuration For VPH configuration fcc and fcc_main are same. Reducing fcc_main from fcc can cause the charger disbale condition to always be false. Fix this by changing the main_ilim_ua type to int and add a check for subtracting the main_fcc_ua from fcc_ua only for VBAT configuration. Change-Id: I63a527a6de981a42d0c879151af1346191dbb4f6 Signed-off-by: Ashish Chavan --- .../power/supply/qcom/smb1390-charger-psy.c | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/drivers/power/supply/qcom/smb1390-charger-psy.c b/drivers/power/supply/qcom/smb1390-charger-psy.c index bb2daa1a1bed..2ba33936e048 100644 --- a/drivers/power/supply/qcom/smb1390-charger-psy.c +++ b/drivers/power/supply/qcom/smb1390-charger-psy.c @@ -211,10 +211,10 @@ struct smb1390 { int cp_isns_slave; int cp_ilim; int die_temp; + int min_ilim_ua; bool suspended; bool disabled; u32 debug_mask; - u32 min_ilim_ua; u32 max_temp_alarm_degc; u32 max_cutoff_soc; u32 pl_output_mode; @@ -1240,7 +1240,7 @@ static void smb1390_taper_work(struct work_struct *work) { struct smb1390 *chip = container_of(work, struct smb1390, taper_work); union power_supply_propval pval = {0, }; - int rc, fcc_uA, delta_fcc_uA, main_fcc_ua = 0; + int rc, fcc_uA, delta_fcc_uA, main_fcc_ua = 0, fcc_cp_ua; if (!is_psy_voter_available(chip)) goto out; @@ -1290,7 +1290,21 @@ static void smb1390_taper_work(struct work_struct *work) goto out; } - if ((fcc_uA - main_fcc_ua) < (chip->min_ilim_ua * 2)) { + /* + * fcc and fcc_main are the same for VPH config, hence + * reduce fcc_main from fcc only in VBAT (output config) + * where fcc_main is a portion of full-fcc. + */ + fcc_cp_ua = fcc_uA; + if (chip->pl_output_mode == POWER_SUPPLY_PL_OUTPUT_VBAT) + fcc_cp_ua = fcc_uA - main_fcc_ua; + + smb1390_dbg(chip, PR_INFO, + "Taper: fcc_ua=%d fcc_cp_ua=%d fcc_main_ua=%d min_ilim_ua(x2) = %u\n", + fcc_uA, fcc_cp_ua, main_fcc_ua, + (chip->min_ilim_ua*2)); + + if (fcc_cp_ua < (chip->min_ilim_ua * 2)) { vote(chip->disable_votable, TAPER_END_VOTER, true, 0); /* From 77b6ab37a12c9d46ae60ddf2015254b848a3e3c6 Mon Sep 17 00:00:00 2001 From: UtsavBalar1231 Date: Sat, 1 Aug 2020 12:13:01 +0530 Subject: [PATCH 357/592] Revert "exec: Do not block userspace writes when CPU_BOOST is enabled" This reverts commit 2a5c21bf2ba024d895cd12f2d114b5e4c37b2ed1. --- include/linux/binfmts.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h index 611fe13446e7..a1c50c633a77 100644 --- a/include/linux/binfmts.h +++ b/include/linux/binfmts.h @@ -149,7 +149,6 @@ extern int do_execveat(int, struct filename *, const char __user * const __user *, int); -#ifndef CONFIG_CPU_BOOST static inline bool task_is_booster(struct task_struct *tsk) { char comm[sizeof(tsk->comm)]; @@ -164,5 +163,5 @@ static inline bool task_is_booster(struct task_struct *tsk) !strcmp(comm, "iop@") || !strcmp(comm, "init.qcom.post_"); } -#endif /* CONFIG_CPU_BOOST=n */ + #endif /* _LINUX_BINFMTS_H */ From 81ab5fb8308e6fd48ff4efede1b00dd724545a99 Mon Sep 17 00:00:00 2001 From: UtsavBalar1231 Date: Sat, 1 Aug 2020 12:13:01 +0530 Subject: [PATCH 358/592] kernel: squash revert dynamic stune boost patches Revert "ARM64: configs: raphael: Enable qcom CPU_BOOST" Revert "ARM64: configs: raphael: Enable Dynamic Stune Booosting" Revert "cpu-boost: reset to CAF" Revert "cpu-boost: Create separate tunable for Dynamic Schedtune Boost duration" Revert "cpu-boost: Update functions for newer Dynamic Schedtune Boost changes" Revert "cpu-boost: Reset Dynamic SchedTune Boost only if it is currently active" Revert "cpu-boost: Implement Dynamic SchedTune Boost v3" Revert "sched/boost: Perform SchedTune boosting when sched_boost is triggered" Revert "sched/tune: Switch Dynamic Schedtune Boost to a slot-based tracking system" Revert "sched/stune: Rename stune_boost() to do_stune_sched_boost()" Revert "sched/tune: Rename dynamic_boost parameter to sched_boost" Revert "sched/tune: Track active boosts on a per-Schedtune basis" Revert "sched/tune: Reset Dynamic Schedtune Boost only if no more boosts running" Revert "sched/tune: Introduce stune_boost() function" Revert "sched/tune: Refactor do_stune_boost()" Revert "sched/tune: Create dynamic_boost SchedTune parameter" Revert "sched/tune: Rename dynamic_boost_write() to dynamic_boost()" Revert "sched/tune: Add initial support for Dynamic SchedTune Boost" Signed-off-by: UtsavBalar1231 --- arch/arm64/configs/raphael_defconfig | 8 +- drivers/cpufreq/cpu-boost.c | 228 +++++++++++++----- include/linux/kthread.h | 13 + include/linux/sched.h | 6 - init/Kconfig | 9 - kernel/kthread.c | 13 - kernel/sched/boost.c | 12 - kernel/sched/tune.c | 341 --------------------------- 8 files changed, 181 insertions(+), 449 deletions(-) diff --git a/arch/arm64/configs/raphael_defconfig b/arch/arm64/configs/raphael_defconfig index 5a06bbe21533..5548e5273587 100644 --- a/arch/arm64/configs/raphael_defconfig +++ b/arch/arm64/configs/raphael_defconfig @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm64 4.14.190 Kernel Configuration +# Linux/arm64 4.14.189 Kernel Configuration # CONFIG_ARM64=y CONFIG_64BIT=y @@ -168,7 +168,6 @@ CONFIG_NET_NS=y # CONFIG_SCHED_AUTOGROUP is not set CONFIG_SCHED_TUNE=y # CONFIG_CPUSETS_ASSIST is not set -CONFIG_DYNAMIC_STUNE_BOOST=y CONFIG_DEFAULT_USE_ENERGY_AWARE=y # CONFIG_SYSFS_DEPRECATED is not set # CONFIG_RELAY is not set @@ -733,10 +732,11 @@ CONFIG_CPU_FREQ_GOV_POWERSAVE=y # CONFIG_CPU_FREQ_GOV_USERSPACE is not set # CONFIG_CPU_FREQ_GOV_ONDEMAND is not set # CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set -CONFIG_CPU_BOOST=y +# CONFIG_CPU_BOOST is not set CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y +CONFIG_SCHEDUTIL_UP_RATE_LIMIT=500 +CONFIG_SCHEDUTIL_DOWN_RATE_LIMIT=20000 # CONFIG_CPU_FREQ_GOV_INTERACTIVE is not set -# CONFIG_CPU_INPUT_BOOST is not set # # CPU frequency scaling drivers diff --git a/drivers/cpufreq/cpu-boost.c b/drivers/cpufreq/cpu-boost.c index da4884795cdf..b6ceb2133b9b 100644 --- a/drivers/cpufreq/cpu-boost.c +++ b/drivers/cpufreq/cpu-boost.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2013-2015,2017, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -17,46 +18,60 @@ #include #include #include +#include #include #include #include #include #include +#include + +#include struct cpu_sync { int cpu; unsigned int input_boost_min; unsigned int input_boost_freq; + unsigned int powerkey_input_boost_freq; +}; + +enum input_boost_type { + default_input_boost, + powerkey_input_boost }; static DEFINE_PER_CPU(struct cpu_sync, sync_info); -static struct workqueue_struct *cpu_boost_wq; -static struct work_struct input_boost_work; +static struct kthread_work input_boost_work; + +static struct kthread_work powerkey_input_boost_work; static bool input_boost_enabled; static unsigned int input_boost_ms = 40; module_param(input_boost_ms, uint, 0644); +static unsigned int powerkey_input_boost_ms = 400; +module_param(powerkey_input_boost_ms, uint, 0644); + static unsigned int sched_boost_on_input; module_param(sched_boost_on_input, uint, 0644); -static bool sched_boost_active; +static bool sched_boost_on_powerkey_input = true; +module_param(sched_boost_on_powerkey_input, bool, 0644); -#ifdef CONFIG_DYNAMIC_STUNE_BOOST -static int dynamic_stune_boost = 1; -module_param(dynamic_stune_boost, uint, 0644); -static bool stune_boost_active; -static int boost_slot; -static unsigned int dynamic_stune_boost_ms = 40; -module_param(dynamic_stune_boost_ms, uint, 0644); -static struct delayed_work dynamic_stune_boost_rem; -#endif /* CONFIG_DYNAMIC_STUNE_BOOST */ +static bool sched_boost_active; static struct delayed_work input_boost_rem; static u64 last_input_time; -#define MIN_INPUT_INTERVAL (150 * USEC_PER_MSEC) + +static struct kthread_worker cpu_boost_worker; +static struct task_struct *cpu_boost_worker_thread; + +static struct kthread_worker powerkey_cpu_boost_worker; +static struct task_struct *powerkey_cpu_boost_worker_thread; + +#define MIN_INPUT_INTERVAL (100 * USEC_PER_MSEC) static int set_input_boost_freq(const char *buf, const struct kernel_param *kp) { @@ -64,6 +79,12 @@ static int set_input_boost_freq(const char *buf, const struct kernel_param *kp) unsigned int val, cpu; const char *cp = buf; bool enabled = false; + enum input_boost_type type; + + if (strstr(kp->name, "input_boost_freq")) + type = default_input_boost; + if (strstr(kp->name, "powerkey_input_boost_freq")) + type = powerkey_input_boost; while ((cp = strpbrk(cp + 1, " :"))) ntokens++; @@ -72,8 +93,12 @@ static int set_input_boost_freq(const char *buf, const struct kernel_param *kp) if (!ntokens) { if (sscanf(buf, "%u\n", &val) != 1) return -EINVAL; - for_each_possible_cpu(i) - per_cpu(sync_info, i).input_boost_freq = val; + for_each_possible_cpu(i) { + if (type == default_input_boost) + per_cpu(sync_info, i).input_boost_freq = val; + else if (type == powerkey_input_boost) + per_cpu(sync_info, i).powerkey_input_boost_freq = val; + } goto check_enable; } @@ -88,14 +113,18 @@ static int set_input_boost_freq(const char *buf, const struct kernel_param *kp) if (cpu >= num_possible_cpus()) return -EINVAL; - per_cpu(sync_info, cpu).input_boost_freq = val; + if (type == default_input_boost) + per_cpu(sync_info, cpu).input_boost_freq = val; + else if (type == powerkey_input_boost) + per_cpu(sync_info, cpu).powerkey_input_boost_freq = val; cp = strnchr(cp, PAGE_SIZE - (cp - buf), ' '); cp++; } check_enable: for_each_possible_cpu(i) { - if (per_cpu(sync_info, i).input_boost_freq) { + if (per_cpu(sync_info, i).input_boost_freq + || per_cpu(sync_info, i).powerkey_input_boost_freq) { enabled = true; break; } @@ -109,11 +138,22 @@ static int get_input_boost_freq(char *buf, const struct kernel_param *kp) { int cnt = 0, cpu; struct cpu_sync *s; + unsigned int boost_freq = 0; + enum input_boost_type type; + + if (strstr(kp->name, "input_boost_freq")) + type = default_input_boost; + if (strstr(kp->name, "powerkey_input_boost_freq")) + type = powerkey_input_boost; for_each_possible_cpu(cpu) { s = &per_cpu(sync_info, cpu); + if (type == default_input_boost) + boost_freq = s->input_boost_freq; + else if(type == powerkey_input_boost) + boost_freq = s->powerkey_input_boost_freq; cnt += snprintf(buf + cnt, PAGE_SIZE - cnt, - "%d:%u ", cpu, s->input_boost_freq); + "%d:%u ", cpu, boost_freq); } cnt += snprintf(buf + cnt, PAGE_SIZE - cnt, "\n"); return cnt; @@ -125,6 +165,8 @@ static const struct kernel_param_ops param_ops_input_boost_freq = { }; module_param_cb(input_boost_freq, ¶m_ops_input_boost_freq, NULL, 0644); +module_param_cb(powerkey_input_boost_freq, ¶m_ops_input_boost_freq, NULL, 0644); + /* * The CPUFREQ_ADJUST notifier is used to override the current policy min to * make sure policy min >= boost_min. The cpufreq framework then does the job @@ -197,38 +239,17 @@ static void do_input_boost_rem(struct work_struct *work) } } -#ifdef CONFIG_DYNAMIC_STUNE_BOOST -static void do_dynamic_stune_boost_rem(struct work_struct *work) -{ - /* Reset dynamic stune boost value to the default value */ - if (stune_boost_active) { - reset_stune_boost("top-app", boost_slot); - stune_boost_active = false; - } -} -#endif /* CONFIG_DYNAMIC_STUNE_BOOST */ - -static void do_input_boost(struct work_struct *work) +static void do_input_boost(struct kthread_work *work) { unsigned int i, ret; struct cpu_sync *i_sync_info; -#ifdef CONFIG_DYNAMIC_STUNE_BOOST - cancel_delayed_work_sync(&dynamic_stune_boost_rem); -#endif /* CONFIG_DYNAMIC_STUNE_BOOST */ cancel_delayed_work_sync(&input_boost_rem); if (sched_boost_active) { sched_set_boost(0); sched_boost_active = false; } -#ifdef CONFIG_DYNAMIC_STUNE_BOOST - if (stune_boost_active) { - reset_stune_boost("top-app", boost_slot); - stune_boost_active = false; - } -#endif /* CONFIG_DYNAMIC_STUNE_BOOST */ - /* Set the input_boost_min for all CPUs in the system */ pr_debug("Setting input boost min for all CPUs\n"); for_each_possible_cpu(i) { @@ -248,18 +269,41 @@ static void do_input_boost(struct work_struct *work) sched_boost_active = true; } -#ifdef CONFIG_DYNAMIC_STUNE_BOOST - /* Set dynamic stune boost value */ - ret = do_stune_boost("top-app", dynamic_stune_boost, &boost_slot); - if (!ret) - stune_boost_active = true; + schedule_delayed_work(&input_boost_rem, msecs_to_jiffies(input_boost_ms)); +} - queue_delayed_work(cpu_boost_wq, &dynamic_stune_boost_rem, - msecs_to_jiffies(dynamic_stune_boost_ms)); -#endif /* CONFIG_DYNAMIC_STUNE_BOOST */ +static void do_powerkey_input_boost(struct kthread_work *work) +{ - queue_delayed_work(cpu_boost_wq, &input_boost_rem, - msecs_to_jiffies(input_boost_ms)); + unsigned int i, ret; + struct cpu_sync *i_sync_info; + cancel_delayed_work_sync(&input_boost_rem); + if (sched_boost_active) { + sched_set_boost(0); + sched_boost_active = false; + } + + /* Set the powerkey_input_boost_min for all CPUs in the system */ + pr_debug("Setting powerkey input boost min for all CPUs\n"); + for_each_possible_cpu(i) { + i_sync_info = &per_cpu(sync_info, i); + i_sync_info->input_boost_min = i_sync_info->powerkey_input_boost_freq; + } + + /* Update policies for all online CPUs */ + update_policy_online(); + + /* Enable scheduler boost to migrate tasks to big cluster */ + if (sched_boost_on_powerkey_input) { + ret = sched_set_boost(1); + if (ret) + pr_err("cpu-boost: HMP boost enable failed\n"); + else + sched_boost_active = true; + } + + schedule_delayed_work(&input_boost_rem, + msecs_to_jiffies(powerkey_input_boost_ms)); } static void cpuboost_input_event(struct input_handle *handle, @@ -274,13 +318,40 @@ static void cpuboost_input_event(struct input_handle *handle, if (now - last_input_time < MIN_INPUT_INTERVAL) return; - if (work_pending(&input_boost_work)) + if (queuing_blocked(&cpu_boost_worker, &input_boost_work)) return; - queue_work(cpu_boost_wq, &input_boost_work); + kthread_queue_work(&cpu_boost_worker, &input_boost_work); + + if ((type == EV_KEY && code == KEY_POWER) || + (type == EV_KEY && code == KEY_WAKEUP)) { + kthread_queue_work(&cpu_boost_worker, &powerkey_input_boost_work); + } else { + kthread_queue_work(&cpu_boost_worker, &input_boost_work); + } last_input_time = ktime_to_us(ktime_get()); } +void touch_irq_boost(void) +{ + u64 now; + + if (!input_boost_enabled) + return; + + now = ktime_to_us(ktime_get()); + if (now - last_input_time < MIN_INPUT_INTERVAL) + return; + + if (queuing_blocked(&cpu_boost_worker, &input_boost_work)) + return; + + kthread_queue_work(&cpu_boost_worker, &input_boost_work); + + last_input_time = ktime_to_us(ktime_get()); +} +EXPORT_SYMBOL(touch_irq_boost); + static int cpuboost_input_connect(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id) { @@ -313,11 +384,6 @@ err2: static void cpuboost_input_disconnect(struct input_handle *handle) { -#ifdef CONFIG_DYNAMIC_STUNE_BOOST - /* Reset dynamic stune boost value to the default value */ - reset_stune_boost("top-app", boost_slot); -#endif /* CONFIG_DYNAMIC_STUNE_BOOST */ - input_close_device(handle); input_unregister_handle(handle); kfree(handle); @@ -359,18 +425,52 @@ static struct input_handler cpuboost_input_handler = { static int cpu_boost_init(void) { - int cpu, ret; + int cpu, ret, i; struct cpu_sync *s; + struct sched_param param = { .sched_priority = 2 }; + cpumask_t sys_bg_mask; - cpu_boost_wq = alloc_workqueue("cpuboost_wq", WQ_HIGHPRI, 0); - if (!cpu_boost_wq) + /* Hardcode the cpumask to bind the kthread to it */ + cpumask_clear(&sys_bg_mask); + for (i = 0; i <= 3; i++) { + cpumask_set_cpu(i, &sys_bg_mask); + } + + kthread_init_worker(&cpu_boost_worker); + cpu_boost_worker_thread = kthread_create(kthread_worker_fn, + &cpu_boost_worker, "cpu_boost_worker_thread"); + if (IS_ERR(cpu_boost_worker_thread)) { + pr_err("cpu-boost: Failed to init kworker!\n"); return -EFAULT; + } - INIT_WORK(&input_boost_work, do_input_boost); + ret = sched_setscheduler(cpu_boost_worker_thread, SCHED_FIFO, ¶m); + if (ret) + pr_err("cpu-boost: Failed to set SCHED_FIFO!\n"); + + kthread_init_worker(&powerkey_cpu_boost_worker); + powerkey_cpu_boost_worker_thread = kthread_create(kthread_worker_fn, + &powerkey_cpu_boost_worker, "powerkey_cpu_boost_worker_thread"); + if (IS_ERR(powerkey_cpu_boost_worker_thread)) { + pr_err("powerkey_cpu-boost: Failed to init kworker!\n"); + return -EFAULT; + } + + ret = sched_setscheduler(powerkey_cpu_boost_worker_thread, SCHED_FIFO, ¶m); + if (ret) + pr_err("powerkey_cpu-boost: Failed to set SCHED_FIFO!\n"); + + /* Now bind it to the cpumask */ + kthread_bind_mask(cpu_boost_worker_thread, &sys_bg_mask); + kthread_bind_mask(powerkey_cpu_boost_worker_thread, &sys_bg_mask); + + /* Wake it up! */ + wake_up_process(cpu_boost_worker_thread); + wake_up_process(powerkey_cpu_boost_worker_thread); + + kthread_init_work(&input_boost_work, do_input_boost); + kthread_init_work(&powerkey_input_boost_work, do_powerkey_input_boost); INIT_DELAYED_WORK(&input_boost_rem, do_input_boost_rem); -#ifdef CONFIG_DYNAMIC_STUNE_BOOST - INIT_DELAYED_WORK(&dynamic_stune_boost_rem, do_dynamic_stune_boost_rem); -#endif /* CONFIG_DYNAMIC_STUNE_BOOST */ for_each_possible_cpu(cpu) { s = &per_cpu(sync_info, cpu); diff --git a/include/linux/kthread.h b/include/linux/kthread.h index 144006195c5c..413b05795a65 100644 --- a/include/linux/kthread.h +++ b/include/linux/kthread.h @@ -187,6 +187,19 @@ extern void __kthread_init_worker(struct kthread_worker *worker, TIMER_IRQSAFE); \ } while (0) +/* + * Returns true when the work could not be queued at the moment. + * It happens when it is already pending in a worker list + * or when it is being cancelled. + */ +static inline bool queuing_blocked(struct kthread_worker *worker, + struct kthread_work *work) +{ + lockdep_assert_held(&worker->lock); + + return !list_empty(&work->node) || work->canceling; +} + int kthread_worker_fn(void *worker_ptr); __printf(2, 3) diff --git a/include/linux/sched.h b/include/linux/sched.h index d7d9191133ab..bff0ed6de4c7 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -2012,10 +2012,4 @@ static inline void set_wake_up_idle(bool enabled) current->flags &= ~PF_WAKE_UP_IDLE; } -#ifdef CONFIG_DYNAMIC_STUNE_BOOST -int do_stune_boost(char *st_name, int boost, int *slot); -int do_stune_sched_boost(char *st_name, int *slot); -int reset_stune_boost(char *st_name, int slot); -#endif /* CONFIG_DYNAMIC_STUNE_BOOST */ - #endif diff --git a/init/Kconfig b/init/Kconfig index 739dc7ddac5d..6c14e5499fb9 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -1170,15 +1170,6 @@ config CPUSET_TOP_APP endif -config DYNAMIC_STUNE_BOOST - bool "Dynamic SchedTune boosting support" - depends on SCHED_TUNE - help - This option extends the SchedTune framework and provides APIs to - activate and reset SchedTune boosting from anywhere in the kernel. - - If unsure, say N. - config DEFAULT_USE_ENERGY_AWARE bool "Default to enabling the Energy Aware Scheduler feature" default n diff --git a/kernel/kthread.c b/kernel/kthread.c index 993384401c9a..a6d8ba28f5ab 100644 --- a/kernel/kthread.c +++ b/kernel/kthread.c @@ -746,19 +746,6 @@ kthread_create_worker_on_cpu(int cpu, unsigned int flags, } EXPORT_SYMBOL(kthread_create_worker_on_cpu); -/* - * Returns true when the work could not be queued at the moment. - * It happens when it is already pending in a worker list - * or when it is being cancelled. - */ -static inline bool queuing_blocked(struct kthread_worker *worker, - struct kthread_work *work) -{ - lockdep_assert_held(&worker->lock); - - return !list_empty(&work->node) || work->canceling; -} - static void kthread_insert_work_sanity_check(struct kthread_worker *worker, struct kthread_work *work) { diff --git a/kernel/sched/boost.c b/kernel/sched/boost.c index 5c08acaf30f1..c3c29e1796b8 100644 --- a/kernel/sched/boost.c +++ b/kernel/sched/boost.c @@ -16,10 +16,6 @@ #include #include -#ifdef CONFIG_DYNAMIC_STUNE_BOOST -static int boost_slot; -#endif // CONFIG_DYNAMIC_STUNE_BOOST - /* * Scheduler boost is a mechanism to temporarily place tasks on CPUs * with higher capacity than those where a task would have normally @@ -218,14 +214,6 @@ static void sched_boost_disable_all(void) static void _sched_set_boost(int type) { - -#ifdef CONFIG_DYNAMIC_STUNE_BOOST - if (type > 0) - do_stune_sched_boost("top-app", &boost_slot); - else - reset_stune_boost("top-app", boost_slot); -#endif // CONFIG_DYNAMIC_STUNE_BOOST - if (type == 0) sched_boost_disable_all(); else if (type > 0) diff --git a/kernel/sched/tune.c b/kernel/sched/tune.c index 4a278bc12587..fef0a5d6b8ff 100644 --- a/kernel/sched/tune.c +++ b/kernel/sched/tune.c @@ -7,7 +7,6 @@ #include #include -#include #include "sched.h" #include "tune.h" @@ -18,18 +17,6 @@ extern struct reciprocal_value schedtune_spc_rdiv; /* We hold schedtune boost in effect for at least this long */ #define SCHEDTUNE_BOOST_HOLD_NS 50000000ULL -#ifdef CONFIG_DYNAMIC_STUNE_BOOST -#define DYNAMIC_BOOST_SLOTS_COUNT 5 -static DEFINE_MUTEX(boost_slot_mutex); -static DEFINE_MUTEX(stune_boost_mutex); -static struct schedtune *getSchedtune(char *st_name); -static int dynamic_boost(struct schedtune *st, int boost); -struct boost_slot { - struct list_head list; - int idx; -}; -#endif /* CONFIG_DYNAMIC_STUNE_BOOST */ - /* * EAS scheduler tunables for task groups. */ @@ -69,27 +56,6 @@ struct schedtune { /* Hint to bias scheduling of tasks on that SchedTune CGroup * towards idle CPUs */ int prefer_idle; - -#ifdef CONFIG_DYNAMIC_STUNE_BOOST - /* - * This tracks the default boost value and is used to restore - * the value when Dynamic SchedTune Boost is reset. - */ - int boost_default; - - /* Sched Boost value for tasks on that SchedTune CGroup */ - int sched_boost; - - /* Number of ongoing boosts for this SchedTune CGroup */ - int boost_count; - - /* Lists of active and available boost slots */ - struct boost_slot active_boost_slots; - struct boost_slot available_boost_slots; - - /* Array of tracked boost values of each slot */ - int slot_boost[DYNAMIC_BOOST_SLOTS_COUNT]; -#endif /* CONFIG_DYNAMIC_STUNE_BOOST */ }; static inline struct schedtune *css_st(struct cgroup_subsys_state *css) @@ -126,20 +92,6 @@ root_schedtune = { .colocate_update_disabled = false, #endif .prefer_idle = 0, -#ifdef CONFIG_DYNAMIC_STUNE_BOOST - .boost_default = 0, - .sched_boost = 0, - .boost_count = 0, - .active_boost_slots = { - .list = LIST_HEAD_INIT(root_schedtune.active_boost_slots.list), - .idx = 0, - }, - .available_boost_slots = { - .list = LIST_HEAD_INIT(root_schedtune.available_boost_slots.list), - .idx = 0, - }, - .slot_boost = {0}, -#endif /* CONFIG_DYNAMIC_STUNE_BOOST */ }; /* @@ -685,9 +637,6 @@ boost_write(struct cgroup_subsys_state *css, struct cftype *cft, return -EINVAL; st->boost = boost; -#ifdef CONFIG_DYNAMIC_STUNE_BOOST - st->boost_default = boost; -#endif /* CONFIG_DYNAMIC_STUNE_BOOST */ /* Update CPU boost */ schedtune_boostgroup_update(st->idx, st->boost); @@ -695,63 +644,6 @@ boost_write(struct cgroup_subsys_state *css, struct cftype *cft, return 0; } -#ifdef CONFIG_DYNAMIC_STUNE_BOOST -static s64 -sched_boost_read(struct cgroup_subsys_state *css, struct cftype *cft) -{ - struct schedtune *st = css_st(css); - - return st->sched_boost; -} - -static int -sched_boost_write(struct cgroup_subsys_state *css, struct cftype *cft, - s64 sched_boost) -{ - struct schedtune *st = css_st(css); - st->sched_boost = sched_boost; - - return 0; -} - -static void -boost_slots_init(struct schedtune *st) -{ - int i; - struct boost_slot *slot; - - /* Initialize boost slots */ - INIT_LIST_HEAD(&(st->active_boost_slots.list)); - INIT_LIST_HEAD(&(st->available_boost_slots.list)); - - /* Populate available_boost_slots */ - for (i = 0; i < DYNAMIC_BOOST_SLOTS_COUNT; ++i) { - slot = kmalloc(sizeof(*slot), GFP_KERNEL); - slot->idx = i; - list_add_tail(&(slot->list), &(st->available_boost_slots.list)); - } -} - -static void -boost_slots_release(struct schedtune *st) -{ - struct boost_slot *slot, *next_slot; - - list_for_each_entry_safe(slot, next_slot, - &(st->available_boost_slots.list), list) { - list_del(&slot->list); - pr_info("STUNE: freed!\n"); - kfree(slot); - } - list_for_each_entry_safe(slot, next_slot, - &(st->active_boost_slots.list), list) { - list_del(&slot->list); - pr_info("STUNE: freed!\n"); - kfree(slot); - } -} -#endif // CONFIG_DYNAMIC_STUNE_BOOST - static struct cftype files[] = { #ifdef CONFIG_SCHED_WALT { @@ -775,13 +667,6 @@ static struct cftype files[] = { .read_u64 = prefer_idle_read, .write_u64 = prefer_idle_write, }, -#ifdef CONFIG_DYNAMIC_STUNE_BOOST - { - .name = "sched_boost", - .read_s64 = sched_boost_read, - .write_s64 = sched_boost_write, - }, -#endif // CONFIG_DYNAMIC_STUNE_BOOST { } /* terminate */ }; @@ -802,10 +687,6 @@ schedtune_boostgroup_init(struct schedtune *st) bg->group[st->idx].ts = 0; } -#ifdef CONFIG_DYNAMIC_STUNE_BOOST - boost_slots_init(st); -#endif // CONFIG_DYNAMIC_STUNE_BOOST - return 0; } @@ -855,10 +736,6 @@ out: static void schedtune_boostgroup_release(struct schedtune *st) { -#ifdef CONFIG_DYNAMIC_STUNE_BOOST - /* Free dynamic boost slots */ - boost_slots_release(st); -#endif // CONFIG_DYNAMIC_STUNE_BOOST /* Reset this boost group */ schedtune_boostgroup_update(st->idx, 0); @@ -904,224 +781,6 @@ schedtune_init_cgroups(void) schedtune_initialized = true; } -#ifdef CONFIG_DYNAMIC_STUNE_BOOST -static struct schedtune *getSchedtune(char *st_name) -{ - int idx; - - for (idx = 1; idx < BOOSTGROUPS_COUNT; ++idx) { - char name_buf[NAME_MAX + 1]; - struct schedtune *st = allocated_group[idx]; - - if (!st) { - pr_warn("SCHEDTUNE: Could not find %s\n", st_name); - break; - } - - cgroup_name(st->css.cgroup, name_buf, sizeof(name_buf)); - if (strncmp(name_buf, st_name, strlen(st_name)) == 0) - return st; - } - - return NULL; -} - -static int dynamic_boost(struct schedtune *st, int boost) -{ - int ret; - /* Backup boost_default */ - int boost_default_backup = st->boost_default; - - ret = boost_write(&st->css, NULL, boost); - - /* Restore boost_default */ - st->boost_default = boost_default_backup; - - return ret; -} - -static inline bool is_valid_boost_slot(int slot) -{ - return slot >= 0 && slot < DYNAMIC_BOOST_SLOTS_COUNT; -} - -static int activate_boost_slot(struct schedtune *st, int boost, int *slot) -{ - int ret = 0; - struct boost_slot *curr_slot; - struct list_head *head; - *slot = -1; - - mutex_lock(&boost_slot_mutex); - - /* Check for slots in available_boost_slots */ - if (list_empty(&(st->available_boost_slots.list))) { - ret = -EINVAL; - goto exit; - } - - /* - * Move one slot from available_boost_slots to active_boost_slots - */ - - /* Get first slot from available_boost_slots */ - head = &(st->available_boost_slots.list); - curr_slot = list_first_entry(head, struct boost_slot, list); - - /* Store slot value and boost value*/ - *slot = curr_slot->idx; - st->slot_boost[*slot] = boost; - - /* Delete slot from available_boost_slots */ - list_del(&curr_slot->list); - kfree(curr_slot); - - /* Create new slot with same value at tail of active_boost_slots */ - curr_slot = kmalloc(sizeof(*curr_slot), GFP_KERNEL); - curr_slot->idx = *slot; - list_add_tail(&(curr_slot->list), - &(st->active_boost_slots.list)); - -exit: - mutex_unlock(&boost_slot_mutex); - return ret; -} - -static int deactivate_boost_slot(struct schedtune *st, int slot) -{ - int ret = 0; - struct boost_slot *curr_slot, *next_slot; - - mutex_lock(&boost_slot_mutex); - - if (!is_valid_boost_slot(slot)) { - ret = -EINVAL; - goto exit; - } - - /* Delete slot from active_boost_slots */ - list_for_each_entry_safe(curr_slot, next_slot, - &(st->active_boost_slots.list), list) { - if (curr_slot->idx == slot) { - st->slot_boost[slot] = 0; - list_del(&curr_slot->list); - kfree(curr_slot); - - /* Create same slot at tail of available_boost_slots */ - curr_slot = kmalloc(sizeof(*curr_slot), GFP_KERNEL); - curr_slot->idx = slot; - list_add_tail(&(curr_slot->list), - &(st->available_boost_slots.list)); - - goto exit; - } - } - - /* Reaching here means that we did not find the slot to delete */ - ret = -EINVAL; - -exit: - mutex_unlock(&boost_slot_mutex); - return ret; -} - -static int max_active_boost(struct schedtune *st) -{ - struct boost_slot *slot; - int max_boost; - - mutex_lock(&boost_slot_mutex); - mutex_lock(&stune_boost_mutex); - - /* Set initial value to default boost */ - max_boost = st->boost_default; - - /* Check for active boosts */ - if (list_empty(&(st->active_boost_slots.list))) { - goto exit; - } - - /* Get largest boost value */ - list_for_each_entry(slot, &(st->active_boost_slots.list), list) { - int boost = st->slot_boost[slot->idx]; - if (boost > max_boost) - max_boost = boost; - } - -exit: - mutex_unlock(&stune_boost_mutex); - mutex_unlock(&boost_slot_mutex); - - return max_boost; -} - -static int _do_stune_boost(struct schedtune *st, int boost, int *slot) -{ - int ret = 0; - - /* Try to obtain boost slot */ - ret = activate_boost_slot(st, boost, slot); - - /* Check if boost slot obtained successfully */ - if (ret) - return -EINVAL; - - /* Boost if new value is greater than current */ - mutex_lock(&stune_boost_mutex); - if (boost > st->boost) - ret = dynamic_boost(st, boost); - mutex_unlock(&stune_boost_mutex); - - return ret; -} - -int reset_stune_boost(char *st_name, int slot) -{ - int ret = 0; - int boost = 0; - struct schedtune *st = getSchedtune(st_name); - - if (!st) - return -EINVAL; - - ret = deactivate_boost_slot(st, slot); - if (ret) { - return -EINVAL; - } - /* Find next largest active boost or reset to default */ - boost = max_active_boost(st); - - mutex_lock(&stune_boost_mutex); - /* Boost only if value changed */ - if (boost != st->boost) - ret = dynamic_boost(st, boost); - mutex_unlock(&stune_boost_mutex); - - return ret; -} - -int do_stune_sched_boost(char *st_name, int *slot) -{ - struct schedtune *st = getSchedtune(st_name); - - if (!st) - return -EINVAL; - - return _do_stune_boost(st, st->sched_boost, slot); -} - -int do_stune_boost(char *st_name, int boost, int *slot) -{ - struct schedtune *st = getSchedtune(st_name); - - if (!st) - return -EINVAL; - - return _do_stune_boost(st, boost, slot); -} - -#endif /* CONFIG_DYNAMIC_STUNE_BOOST */ - /* * Initialize the cgroup structures */ From 41c3f2de8c75cfb6c738b63093c29f0277167f5a Mon Sep 17 00:00:00 2001 From: Om Parkash Date: Mon, 3 Aug 2020 12:22:38 +0530 Subject: [PATCH 359/592] msm: camera: cci: Fix incorrect use of cci config ioctl The cci configuration will be transitioned to a new API that does not require routing through the v4l layer. This is work-in-progrss so in the mean time prevent the device from being exposed as configurable from userspace. The ioctl will still be exposed to kernel users so fix the arg size as well. We want size of struct not pointer. Change-Id: I1eeb58b8355a81fc36b9845e2096060b03f1debe Signed-off-by: Om Parkash --- .../msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.c | 4 ++-- .../msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.c index 69b5af002610..9f8ee883355a 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.c +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -404,7 +404,7 @@ static int cam_cci_platform_probe(struct platform_device *pdev) new_cci_dev->v4l2_dev_str.name = new_cci_dev->device_name; new_cci_dev->v4l2_dev_str.sd_flags = - (V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS); + V4L2_SUBDEV_FL_HAS_EVENTS; new_cci_dev->v4l2_dev_str.ent_function = CAM_CCI_DEVICE_TYPE; new_cci_dev->v4l2_dev_str.token = diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.h index 2e4c032cb322..fd93dedd01f1 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.h +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -317,6 +317,6 @@ static inline struct v4l2_subdev *cam_cci_get_subdev(int cci_dev_index) #endif #define VIDIOC_MSM_CCI_CFG \ - _IOWR('V', BASE_VIDIOC_PRIVATE + 23, struct cam_cci_ctrl *) + _IOWR('V', BASE_VIDIOC_PRIVATE + 23, struct cam_cci_ctrl) #endif /* _CAM_CCI_DEV_H_ */ From ebced8158b49486bf9666620cfe8a42b6d395047 Mon Sep 17 00:00:00 2001 From: Lina Iyer Date: Mon, 11 May 2020 11:14:16 -0600 Subject: [PATCH 360/592] drivers: cpuidle: lpm-levels: check for valid LPM stats When DEBUG_FS is not defined, the cluster->stats may be initialized to an error value. Check for valid stats pointer before updating the start and end times. Change-Id: I126766a017ebd9a84bd40f19ab3ff47877615429 Signed-off-by: Lina Iyer --- drivers/cpuidle/lpm-levels.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/cpuidle/lpm-levels.c b/drivers/cpuidle/lpm-levels.c index 8964462d5e17..b2c958a79eaa 100644 --- a/drivers/cpuidle/lpm-levels.c +++ b/drivers/cpuidle/lpm-levels.c @@ -1234,7 +1234,8 @@ static void cluster_prepare(struct lpm_cluster *cluster, if (cluster_configure(cluster, i, from_idle, predicted)) goto failed; - cluster->stats->sleep_time = start_time; + if (!IS_ERR_OR_NULL(cluster->stats)) + cluster->stats->sleep_time = start_time; cluster_prepare(cluster->parent, &cluster->num_children_in_sync, i, from_idle, start_time); @@ -1242,7 +1243,8 @@ static void cluster_prepare(struct lpm_cluster *cluster, return; failed: spin_unlock(&cluster->sync_lock); - cluster->stats->sleep_time = 0; + if (!IS_ERR_OR_NULL(cluster->stats)) + cluster->stats->sleep_time = 0; } static void cluster_unprepare(struct lpm_cluster *cluster, @@ -1281,7 +1283,7 @@ static void cluster_unprepare(struct lpm_cluster *cluster, if (!first_cpu || cluster->last_level == cluster->default_level) goto unlock_return; - if (cluster->stats->sleep_time) + if (!IS_ERR_OR_NULL(cluster->stats) && cluster->stats->sleep_time) cluster->stats->sleep_time = end_time - cluster->stats->sleep_time; lpm_stats_cluster_exit(cluster->stats, cluster->last_level, success); @@ -1723,6 +1725,9 @@ static void register_cluster_lpm_stats(struct lpm_cluster *cl, cl->stats = lpm_stats_config_level(cl->cluster_name, level_name, cl->nlevels, parent ? parent->stats : NULL, NULL); + if (IS_ERR_OR_NULL(cl->stats)) + pr_info("Cluster (%s) stats not registered\n", + cl->cluster_name); kfree(level_name); From 80879f7404cf577c8389b2a5de5c9a164e0e9c24 Mon Sep 17 00:00:00 2001 From: Manaf Meethalavalappu Pallikunhi Date: Wed, 1 Jul 2020 15:23:01 +0530 Subject: [PATCH 361/592] drivers: thermal: call TSENS re-init only when register is ready to update If TSENS controller reset pin is held asserted for long duration and the same time if TSENS software detects TSENS reset and tries to re-initialize TSENS controller, TSENS initialization may not reflect in TSENS register due to reset pin is held asserted. Invoke TSENS re-init routine only if software is able to write TSENS register successfully. It makes sure that TSENS re-init routine is able to re-initialize TSENS controller. Add a check whether TSENS is re-enabled or not on post TSENS re-init. If it is not re-enabled, re-try TSENS re-init routine. Change-Id: Ia0d9b794b47854d269438ccfd9967cf7112aa5e5 Signed-off-by: Manaf Meethalavalappu Pallikunhi Signed-off-by: Gopala Krishna Nuthaki --- drivers/thermal/tsens2xxx.c | 107 +++++++++++++++++++++++++----------- 1 file changed, 74 insertions(+), 33 deletions(-) diff --git a/drivers/thermal/tsens2xxx.c b/drivers/thermal/tsens2xxx.c index 209ba04bcc8c..76c11c3c081c 100644 --- a/drivers/thermal/tsens2xxx.c +++ b/drivers/thermal/tsens2xxx.c @@ -69,7 +69,6 @@ #define TSENS_TM_TRDY_FIRST_ROUND_COMPLETE_SHIFT 3 #define TSENS_INIT_ID 0x5 #define TSENS_RECOVERY_LOOP_COUNT 5 -#define TSENS_RE_INIT_MAX_COUNT 5 static void msm_tsens_convert_temp(int last_temp, int *temp) { @@ -186,6 +185,7 @@ static int tsens2xxx_get_temp(struct tsens_sensor *sensor, int *temp) if (tmdev->tsens_reinit_wa) { struct scm_desc desc = { 0 }; + int scm_cnt = 0, reg_write_cnt = 0; if (atomic_read(&in_tsens_reinit)) { pr_err("%s: tsens re-init is in progress\n", @@ -199,45 +199,87 @@ static int tsens2xxx_get_temp(struct tsens_sensor *sensor, int *temp) tmdev->ops->dbg(tmdev, 0, TSENS_DBG_LOG_BUS_ID_DATA, NULL); - if (tmdev->tsens_reinit_cnt >= - TSENS_RE_INIT_MAX_COUNT) { - pr_err( - "%s: TSENS not recovered after %d re-init\n", - __func__, tmdev->tsens_reinit_cnt); - BUG(); + while (1) { + /* + * Invoke scm call only if SW register write is + * reflecting in controller. If not, wait for + * 2 ms and then retry. + */ + if (reg_write_cnt >= 100) { + msleep(100); + pr_err( + "%s: Tsens write is failed. cnt:%d\n", + __func__, reg_write_cnt); + BUG(); + } + writel_relaxed(BIT(2), + TSENS_TM_INT_EN(tmdev->tsens_tm_addr)); + code = readl_relaxed( + TSENS_TM_INT_EN(tmdev->tsens_tm_addr)); + if (!(code & BIT(2))) { + udelay(2000); + TSENS_DBG(tmdev, "%s cnt:%d\n", + "Re-try TSENS write prior to scm", + reg_write_cnt++); + continue; + } + reg_write_cnt = 0; + + /* Make an scm call to re-init TSENS */ + TSENS_DBG(tmdev, "%s", + "Calling TZ to re-init TSENS\n"); + ret = scm_call2(SCM_SIP_FNID(SCM_SVC_TSENS, + TSENS_INIT_ID), &desc); + TSENS_DBG(tmdev, "%s", + "return from scm call\n"); + if (ret) { + msleep(100); + pr_err("%s: scm call failed %d\n", + __func__, ret); + BUG(); + } + tsens_ret = desc.ret[0]; + if (tsens_ret) { + msleep(100); + pr_err("%s: scm call failed, ret:%d\n", + __func__, tsens_ret); + BUG(); + } + + scm_cnt++; + rc = 0; + list_for_each_entry(tmdev_itr, + &tsens_device_list, list) { + rc = __tsens2xxx_hw_init(tmdev_itr); + if (rc) { + pr_err( + "%s: TSENS hw_init error\n", + __func__); + break; + } + } + + if (!rc) + break; + + if (scm_cnt >= 100) { + msleep(100); + pr_err( + "%s: Tsens is not up after %d scm\n", + __func__, scm_cnt); + BUG(); + } + udelay(2000); + TSENS_DBG(tmdev, "%s cnt:%d\n", + "Re-try TSENS scm call", scm_cnt); } - /* Make an scm call to re-init TSENS */ - TSENS_DBG(tmdev, "%s", - "Calling TZ to re-init TSENS\n"); - ret = scm_call2(SCM_SIP_FNID(SCM_SVC_TSENS, - TSENS_INIT_ID), &desc); - TSENS_DBG(tmdev, "%s", - "return from scm call\n"); - if (ret) { - pr_err("%s: scm call failed %d\n", - __func__, ret); - BUG(); - } - tsens_ret = desc.ret[0]; - if (tsens_ret) { - pr_err("%s: scm call failed to init tsens %d\n", - __func__, tsens_ret); - BUG(); - } tmdev->tsens_reinit_cnt++; atomic_set(&in_tsens_reinit, 0); /* Notify thermal fwk */ list_for_each_entry(tmdev_itr, &tsens_device_list, list) { - rc = __tsens2xxx_hw_init(tmdev_itr); - if (rc) { - pr_err( - "%s: Failed to re-initialize TSENS controller\n", - __func__); - BUG(); - } queue_work(tmdev_itr->tsens_reinit_work, &tmdev_itr->therm_fwk_notify); } @@ -252,7 +294,6 @@ static int tsens2xxx_get_temp(struct tsens_sensor *sensor, int *temp) sensor_read: tmdev->trdy_fail_ctr = 0; - tmdev->tsens_reinit_cnt = 0; code = readl_relaxed_no_log(sensor_addr + (sensor->hw_id << TSENS_STATUS_ADDR_OFFSET)); From aa5e885c7965d196b03992c1e95b2308e14206f9 Mon Sep 17 00:00:00 2001 From: Aditya Mathur Date: Mon, 3 Aug 2020 13:23:25 -0700 Subject: [PATCH 362/592] Documentation: devicetree: net: Add EMAC configuration options Adding parameters for configuring EMAC settings for stmmac driver. Change-Id: I86cc025f58afd6bae5d3a1feca881b7107dd3e13 Signed-off-by: Aditya Mathur --- Documentation/devicetree/bindings/net/qcom,stmmac-ethqos.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/net/qcom,stmmac-ethqos.txt b/Documentation/devicetree/bindings/net/qcom,stmmac-ethqos.txt index f910fb509396..7011dff0b7d9 100644 --- a/Documentation/devicetree/bindings/net/qcom,stmmac-ethqos.txt +++ b/Documentation/devicetree/bindings/net/qcom,stmmac-ethqos.txt @@ -114,6 +114,8 @@ Optional properties: - snps,high_credit: max write outstanding req. limit - snps,low_credit: max read outstanding req. limit - snps,priority: TX queue priority (Range: 0x0 to 0xF) +- rx-prog-swap: boolean value to enable RX_PROG_SWAP for 10/100M +- rx-dll-bypass: boolean value to indicate RX DLL in bypass mode. Examples: stmmac_axi_setup: stmmac-axi-config { From 379c1b856e842d8fd72d5e0c884fc01dfedac992 Mon Sep 17 00:00:00 2001 From: Raghavendra Rao Ananta Date: Wed, 4 Sep 2019 10:13:24 -0700 Subject: [PATCH 363/592] scripts: Consider env variables while running 'make' The scripts, gki/generate_defconfig.sh and kconfig/merge_config.sh doesn't consider the host exported environment variables (such as HOSTCC) while running 'make'. This is particularly needed in the Android build environment as it uses the compiler, linker, and other utilities from a pre-builts' path, rather than depending on the host tools. Hence, pass the environment variables explicitly. Change-Id: I082c0c05be5f4266fc647e3c1ebef8302e1a433a Signed-off-by: Raghavendra Rao Ananta Signed-off-by: Neeraj Upadhyay --- scripts/kconfig/merge_config.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/kconfig/merge_config.sh b/scripts/kconfig/merge_config.sh index 67d131447631..b5115c6b22f6 100755 --- a/scripts/kconfig/merge_config.sh +++ b/scripts/kconfig/merge_config.sh @@ -151,7 +151,7 @@ fi # Use the merged file as the starting point for: # alldefconfig: Fills in any missing symbols with Kconfig default # allnoconfig: Fills in any missing symbols with # CONFIG_* is not set -make KCONFIG_ALLCONFIG=$TMP_FILE $OUTPUT_ARG $ALLTARGET +make $MAKE_ARGS KCONFIG_ALLCONFIG=$TMP_FILE $OUTPUT_ARG $ALLTARGET # Check all specified config values took (might have missed-dependency issues) From 9fa809054f28792c43301552740f00a3415e02d7 Mon Sep 17 00:00:00 2001 From: Neeraj Upadhyay Date: Fri, 22 May 2020 15:11:13 +0530 Subject: [PATCH 364/592] defconfig: msm: Add config fragment for DEBUG_FS disablement Add a config fragment for disabling DEBUG_FS. Change-Id: I877c74955e467002976c3bac6c946183c8be7043 Signed-off-by: Neeraj Upadhyay --- arch/arm64/configs/vendor/debugfs.config | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 arch/arm64/configs/vendor/debugfs.config diff --git a/arch/arm64/configs/vendor/debugfs.config b/arch/arm64/configs/vendor/debugfs.config new file mode 100644 index 000000000000..059013b6a88a --- /dev/null +++ b/arch/arm64/configs/vendor/debugfs.config @@ -0,0 +1,2 @@ +CONFIG_PAGE_OWNER=n +CONFIG_DEBUG_FS=n From b97f8d926d0a22ff54aefa4d2ff062b61dedb626 Mon Sep 17 00:00:00 2001 From: Raghavendra Kakarla Date: Tue, 7 Jul 2020 23:47:38 +0530 Subject: [PATCH 365/592] defconfig: Disable the arm cpuidle support for sdm429 Disable arm cpuidle driver support for sdm429. Change-Id: I18c95dff4823676492eab6fbcdf586ef9b4df3eb Signed-off-by: Raghavendra Kakarla --- arch/arm/configs/vendor/sdm429-bg-perf_defconfig | 1 - arch/arm/configs/vendor/sdm429-bg_defconfig | 1 - 2 files changed, 2 deletions(-) diff --git a/arch/arm/configs/vendor/sdm429-bg-perf_defconfig b/arch/arm/configs/vendor/sdm429-bg-perf_defconfig index f412e97df448..a78dc6c5c287 100644 --- a/arch/arm/configs/vendor/sdm429-bg-perf_defconfig +++ b/arch/arm/configs/vendor/sdm429-bg-perf_defconfig @@ -78,7 +78,6 @@ CONFIG_CPU_BOOST=y CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y CONFIG_CPU_FREQ_MSM=y CONFIG_CPU_IDLE=y -CONFIG_ARM_CPUIDLE=y CONFIG_VFP=y CONFIG_NEON=y CONFIG_KERNEL_MODE_NEON=y diff --git a/arch/arm/configs/vendor/sdm429-bg_defconfig b/arch/arm/configs/vendor/sdm429-bg_defconfig index 11011eee9bed..725b4396e640 100644 --- a/arch/arm/configs/vendor/sdm429-bg_defconfig +++ b/arch/arm/configs/vendor/sdm429-bg_defconfig @@ -80,7 +80,6 @@ CONFIG_CPU_BOOST=y CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y CONFIG_CPU_FREQ_MSM=y CONFIG_CPU_IDLE=y -CONFIG_ARM_CPUIDLE=y CONFIG_VFP=y CONFIG_NEON=y CONFIG_KERNEL_MODE_NEON=y From 155d565f7cf48748a9ee0a80e571762af5939608 Mon Sep 17 00:00:00 2001 From: Shumin Qiu Date: Wed, 21 Aug 2019 00:50:24 -0700 Subject: [PATCH 366/592] Revert "Dm: init: Enable rootfs mount as dm-verity during boot without ramdisk" This reverts commit 96d633371a25212b5e7499bbade42082c5368581. Change-Id: I1b58ee238bdd0c7fc8faacfc398c96a4f560e5cf Signed-off-by: Shumin Qiu Signed-off-by: UtsavBalar1231 --- drivers/md/dm-ioctl.c | 35 ----- drivers/md/dm-ioctrl.h | 20 --- init/Makefile | 1 - init/do_mounts.c | 1 - init/do_mounts.h | 14 -- init/do_mounts_verity.c | 285 ---------------------------------------- 6 files changed, 356 deletions(-) delete mode 100644 drivers/md/dm-ioctrl.h delete mode 100644 init/do_mounts_verity.c diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index 33d6011ac461..787afba77b2e 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -6,7 +6,6 @@ */ #include "dm-core.h" -#include "dm-ioctrl.h" #include #include @@ -2057,37 +2056,3 @@ out: return r; } - -int __init dm_ioctrl(uint cmd, struct dm_ioctl *param) -{ - int r = 0; - int ioctl_flags; - ioctl_fn fn = NULL; - size_t input_param_size; - - /* - * Nothing more to do for the version command. - */ - if (cmd == DM_VERSION_CMD) - return 0; - - DMDEBUG("dm_ctl_ioctl: command 0x%x", cmd); - - fn = lookup_ioctl(cmd, &ioctl_flags); - if (!fn) { - DMWARN("dm_ctl_ioctl: unknown command 0x%x", cmd); - return -ENOTTY; - } - - input_param_size = param->data_size; - param->data_size = sizeof(*param); - - r = fn(NULL, param, input_param_size); - - if (unlikely(param->flags & DM_BUFFER_FULL_FLAG) && - unlikely(ioctl_flags & IOCTL_FLAGS_NO_PARAMS)) - DMERR("ioctl %d but has IOCTL_FLAGS_NO_PARAMS set", cmd); - - return r; -} -EXPORT_SYMBOL(dm_ioctrl); diff --git a/drivers/md/dm-ioctrl.h b/drivers/md/dm-ioctrl.h deleted file mode 100644 index d331fcd83df4..000000000000 --- a/drivers/md/dm-ioctrl.h +++ /dev/null @@ -1,20 +0,0 @@ -/* Copyright (c) 2019, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef DM_IOCTRL_INTERNAL_H -#define DM_IOCTRL_INTERNAL_H - -#include - -int dm_ioctrl(uint cmd, struct dm_ioctl *param); - -#endif diff --git a/init/Makefile b/init/Makefile index 230853115245..58bc56e3e4e7 100644 --- a/init/Makefile +++ b/init/Makefile @@ -20,7 +20,6 @@ mounts-$(CONFIG_BLK_DEV_RAM) += do_mounts_rd.o mounts-$(CONFIG_BLK_DEV_INITRD) += do_mounts_initrd.o mounts-$(CONFIG_BLK_DEV_MD) += do_mounts_md.o mounts-$(CONFIG_BLK_DEV_DM) += do_mounts_dm.o -mounts-$(CONFIG_BLK_DEV_DM) += do_mounts_verity.o # dependencies on generated files need to be listed explicitly $(obj)/version.o: include/generated/compile.h diff --git a/init/do_mounts.c b/init/do_mounts.c index 80716bd5eb05..2006003e448d 100644 --- a/init/do_mounts.c +++ b/init/do_mounts.c @@ -687,7 +687,6 @@ void __init prepare_namespace(void) if ((!is_early_userspace) || (is_early_userspace && first_time)) { md_run_setup(); dm_run_setup(); - dm_verity_setup(); if (saved_root_name[0]) { root_device_name = saved_root_name; diff --git a/init/do_mounts.h b/init/do_mounts.h index 9dfd4138aca8..cd201124714b 100644 --- a/init/do_mounts.h +++ b/init/do_mounts.h @@ -8,8 +8,6 @@ #include #include #include -#include "uapi/linux/dm-ioctl.h" -#include void change_floppy(char *fmt, ...); void mount_block_root(char *name, int flags); @@ -73,15 +71,3 @@ void dm_run_setup(void); static inline void dm_run_setup(void) {} #endif - -#ifdef CONFIG_BLK_DEV_DM - -void dm_verity_setup(void); -extern int dm_ioctrl(uint cmd, struct dm_ioctl *param); -extern void dm_table_destroy(struct dm_table *t); - -#else - -static inline void dm_verity_setup(void) {} - -#endif diff --git a/init/do_mounts_verity.c b/init/do_mounts_verity.c deleted file mode 100644 index 5d7c8a2efec9..000000000000 --- a/init/do_mounts_verity.c +++ /dev/null @@ -1,285 +0,0 @@ -/* Copyright (c) 2019, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include "uapi/linux/dm-ioctl.h" -#include -#include -#include "do_mounts.h" - -#define DM_BUF_SIZE 4096 - -#define DM_MSG_PREFIX "verity" - -#define VERITY_COMMANDLINE_PARAM_LENGTH 32 -#define VERITY_ROOT_HASH_PARAM_LENGTH 65 -#define VERITY_SALT_PARAM_LENGTH 65 - -static char dm_name[VERITY_COMMANDLINE_PARAM_LENGTH]; -static char dm_version[VERITY_COMMANDLINE_PARAM_LENGTH]; -static char dm_data_device[VERITY_COMMANDLINE_PARAM_LENGTH]; -static char dm_hash_device[VERITY_COMMANDLINE_PARAM_LENGTH]; -static char dm_data_block_size[VERITY_COMMANDLINE_PARAM_LENGTH]; -static char dm_hash_block_size[VERITY_COMMANDLINE_PARAM_LENGTH]; -static char dm_number_of_data_blocks[VERITY_COMMANDLINE_PARAM_LENGTH]; -static char dm_hash_start_block[VERITY_COMMANDLINE_PARAM_LENGTH]; -static char dm_algorithm[VERITY_COMMANDLINE_PARAM_LENGTH]; -static char dm_digest[VERITY_ROOT_HASH_PARAM_LENGTH]; -static char dm_salt[VERITY_SALT_PARAM_LENGTH]; -static char dm_opt[VERITY_COMMANDLINE_PARAM_LENGTH]; - -static void __init init_param(struct dm_ioctl *param, const char *name) -{ - memset(param, 0, DM_BUF_SIZE); - param->data_size = DM_BUF_SIZE; - param->data_start = sizeof(struct dm_ioctl); - param->version[0] = 4; - param->version[1] = 0; - param->version[2] = 0; - param->flags = DM_READONLY_FLAG; - strlcpy(param->name, name, sizeof(param->name)); -} - -static int __init dm_name_param(char *line) -{ - strlcpy(dm_name, line, sizeof(dm_name)); - return 1; -} -__setup("dmname=", dm_name_param); - -static int __init dm_version_param(char *line) -{ - strlcpy(dm_version, line, sizeof(dm_version)); - return 1; -} -__setup("version=", dm_version_param); - -static int __init dm_data_device_param(char *line) -{ - strlcpy(dm_data_device, line, sizeof(dm_data_device)); - return 1; -} -__setup("data_device=", dm_data_device_param); - -static int __init dm_hash_device_param(char *line) -{ - strlcpy(dm_hash_device, line, sizeof(dm_hash_device)); - return 1; -} -__setup("hash_device=", dm_hash_device_param); - -static int __init dm_data_block_size_param(char *line) -{ - strlcpy(dm_data_block_size, line, sizeof(dm_data_block_size)); - return 1; -} -__setup("data_block_size=", dm_data_block_size_param); - -static int __init dm_hash_block_size_param(char *line) -{ - strlcpy(dm_hash_block_size, line, sizeof(dm_hash_block_size)); - return 1; -} -__setup("hash_block_size=", dm_hash_block_size_param); - -static int __init dm_number_of_data_blocks_param(char *line) -{ - strlcpy(dm_number_of_data_blocks, line, sizeof(dm_number_of_data_blocks)); - return 1; -} -__setup("number_of_data_blocks=", dm_number_of_data_blocks_param); - -static int __init dm_hash_start_block_param(char *line) -{ - strlcpy(dm_hash_start_block, line, sizeof(dm_hash_start_block)); - return 1; -} -__setup("hash_start_block=", dm_hash_start_block_param); - -static int __init dm_algorithm_param(char *line) -{ - strlcpy(dm_algorithm, line, sizeof(dm_algorithm)); - return 1; -} -__setup("algorithm=", dm_algorithm_param); - -static int __init dm_digest_param(char *line) -{ - strlcpy(dm_digest, line, sizeof(dm_digest)); - return 1; -} -__setup("digest=", dm_digest_param); - -static int __init dm_salt_param(char *line) -{ - strlcpy(dm_salt, line, sizeof(dm_salt)); - return 1; -} -__setup("salt=", dm_salt_param); - -static int __init dm_opt_param(char *line) -{ - strlcpy(dm_opt, line, sizeof(dm_opt)); - return 1; -} -__setup("opt=", dm_opt_param); - -static void __init dm_setup_drive(void) -{ - const char *name; - const char *version; - const char *data_device; - const char *hash_device; - const char *data_block_size; - const char *hash_block_size; - const char *number_of_data_blocks; - const char *hash_start_block; - const char *algorithm; - const char *digest; - const char *salt; - const char *opt; - unsigned long long data_blocks; - char dummy; - char *verity_params; - size_t bufsize; - char *buffer = kzalloc(DM_BUF_SIZE, GFP_KERNEL); - struct dm_ioctl *param = (struct dm_ioctl *) buffer; - size_t dm_sz = sizeof(struct dm_ioctl); - struct dm_target_spec *tgt = (struct dm_target_spec *) &buffer[dm_sz]; - - if (!buffer) - goto fail; - name = dm_name; - if (name == NULL) - goto fail; - DMDEBUG("(I) name=%s", name); - - if (strcmp(name, "disabled") == 0) { - pr_info("dm: dm-verity is disabled."); - kfree(buffer); - return; - } - - version = dm_version; - if (version == NULL) - goto fail; - DMDEBUG("(I) version=%s", version); - - data_device = dm_data_device; - if (data_device == NULL) - goto fail; - DMDEBUG("(I) data_device=%s", data_device); - - hash_device = dm_hash_device; - if (hash_device == NULL) - goto fail; - DMDEBUG("(I) hash_device=%s", hash_device); - - data_block_size = dm_data_block_size; - if (data_block_size == NULL) - goto fail; - DMDEBUG("(I) data_block_size=%s", data_block_size); - - hash_block_size = dm_hash_block_size; - if (hash_block_size == NULL) - goto fail; - DMDEBUG("(I) hash_block_size=%s", hash_block_size); - - number_of_data_blocks = dm_number_of_data_blocks; - if (number_of_data_blocks == NULL) - goto fail; - DMDEBUG("(I) number_of_data_blocks=%s", number_of_data_blocks); - - hash_start_block = dm_hash_start_block; - if (hash_start_block == NULL) - goto fail; - DMDEBUG("(I) hash_start_block=%s", hash_start_block); - - algorithm = dm_algorithm; - if (algorithm == NULL) - goto fail; - DMDEBUG("(I) algorithm=%s", algorithm); - - digest = dm_digest; - if (digest == NULL) - goto fail; - DMDEBUG("(I) digest=%s", digest); - - salt = dm_salt; - if (salt == NULL) - goto fail; - DMDEBUG("(I) salt=%s", salt); - - opt = dm_opt; - if (opt == NULL) - goto fail; - DMDEBUG("(I) opt=%s", opt); - - init_param(param, name); - if (dm_ioctrl(DM_DEV_CREATE_CMD, param)) { - DMERR("(E) failed to create the device"); - goto fail; - } - - init_param(param, name); - param->target_count = 1; - /* set tgt arguments */ - tgt->status = 0; - tgt->sector_start = 0; - if (sscanf(number_of_data_blocks, "%llu%c", &data_blocks, &dummy) != 1) { - DMERR("(E) invalid number of data blocks"); - goto fail; - } - - tgt->length = data_blocks*4096/512; /* size in sector(512b) of data dev */ - strlcpy(tgt->target_type, "verity", sizeof(tgt->target_type)); - /* build the verity params here */ - verity_params = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec); - bufsize = DM_BUF_SIZE - (verity_params - buffer); - - verity_params += snprintf(verity_params, bufsize, "%s %s %s %s %s %s %s %s %s %s 1 %s", - version, - data_device, hash_device, - data_block_size, hash_block_size, - number_of_data_blocks, hash_start_block, - algorithm, digest, salt, opt); - - tgt->next = verity_params - buffer; - if (dm_ioctrl(DM_TABLE_LOAD_CMD, param)) { - DMERR("(E) failed to load the device"); - goto fail; - } - - init_param(param, name); - if (dm_ioctrl(DM_DEV_SUSPEND_CMD, param)) { - DMERR("(E) failed to suspend the device"); - goto fail; - } - - pr_info("dm: dm-0 (%s) is ready", data_device); - kfree(buffer); - return; - -fail: - pr_info("dm: starting dm-0 failed"); - kfree(buffer); - return; - -} - -void __init dm_verity_setup(void) -{ - pr_info("dm: attempting early device configuration."); - dm_setup_drive(); -} From 025d35a3d6b17c130cf018cdc9411c2ba81cd2f0 Mon Sep 17 00:00:00 2001 From: Chandana Kishori Chiluveru Date: Fri, 3 Jul 2020 13:42:51 +0530 Subject: [PATCH 367/592] serial: msm_geni_serial: Fix DMA RX FSM reset sequence Update the DMA RX FSM reset sequence as per HPG recommendations. Currently driver calling msm_geni_serial_rx_fsm_rst() even in case of RX inactive. RX FSM reset command generates RX_RESET_DONE bit. There is a possible race between polling for RX_RESET and ISR for RX_RESET. This can result into introducing delay during BT open. Fix this by updating RX FSM reset sequence only in case of cancel command timeout. Change-Id: I90532aa72fdad462a616eded3e149bc6b721fe7b Signed-off-by: Chandana Kishori Chiluveru --- drivers/tty/serial/msm_geni_serial.c | 45 +++++++++------------------- 1 file changed, 14 insertions(+), 31 deletions(-) diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c index e5245d5316dc..374ecc888e2b 100644 --- a/drivers/tty/serial/msm_geni_serial.c +++ b/drivers/tty/serial/msm_geni_serial.c @@ -1472,33 +1472,6 @@ static void msm_geni_serial_start_rx(struct uart_port *uport) start_rx_sequencer(&port->uport); } - -static void msm_geni_serial_rx_fsm_rst(struct uart_port *uport) -{ - unsigned int rx_irq_en; - int done = 0; - int tries = 0; - struct msm_geni_serial_port *port = GET_DEV_PORT(uport); - - if (port->uart_ssr.is_ssr_down) { - IPC_LOG_MSG(port->ipc_log_misc, "%s: SSR Down event set\n", - __func__); - return; - } - - rx_irq_en = geni_read_reg_nolog(uport->membase, SE_DMA_RX_IRQ_EN); - geni_write_reg_nolog(0, uport->membase, SE_DMA_RX_IRQ_EN_SET); - geni_write_reg_nolog(1, uport->membase, SE_DMA_RX_FSM_RST); - do { - done = msm_geni_serial_poll_bit(uport, SE_DMA_RX_IRQ_STAT, - RX_RESET_DONE, true); - tries++; - } while (!done && tries < 5); - geni_write_reg_nolog(RX_DMA_DONE | RX_RESET_DONE, uport->membase, - SE_DMA_RX_IRQ_CLR); - geni_write_reg_nolog(rx_irq_en, uport->membase, SE_DMA_RX_IRQ_EN_SET); -} - static void msm_geni_serial_set_manual_flow(bool enable, struct msm_geni_serial_port *port) { @@ -1558,7 +1531,7 @@ static void stop_rx_sequencer(struct uart_port *uport) IPC_LOG_MSG(port->ipc_log_misc, "%s: RX is Inactive, geni_sts: 0x%x\n", __func__, geni_status); - goto exit_rx_seq; + return; } port->s_cmd_done = false; @@ -1617,15 +1590,25 @@ static void stop_rx_sequencer(struct uart_port *uport) IPC_LOG_MSG(port->console_log, "%s abort fail 0x%x\n", __func__, geni_status); } + + if (port->xfer_mode == SE_DMA) { + port->s_cmd_done = false; + reinit_completion(&port->s_cmd_timeout); + geni_write_reg_nolog(1, uport->membase, + SE_DMA_RX_FSM_RST); + + timeout = geni_wait_for_cmd_done(uport, + is_irq_masked); + if (timeout) + IPC_LOG_MSG(port->ipc_log_misc, + "%s: rx fsm reset failed\n", __func__); + } } /* Enable the interrupts once the cancel operation is done. */ msm_geni_serial_enable_interrupts(uport); port->s_cmd = false; exit_rx_seq: - if (port->xfer_mode == SE_DMA && port->rx_dma) - msm_geni_serial_rx_fsm_rst(uport); - geni_status = geni_read_reg_nolog(uport->membase, SE_GENI_STATUS); IPC_LOG_MSG(port->ipc_log_misc, "%s: End 0x%x\n", __func__, geni_status); From 49553668099c07d73847cb5a11fd9b995749eac0 Mon Sep 17 00:00:00 2001 From: Pavankumar Vijapur Date: Wed, 29 Jul 2020 15:47:13 +0530 Subject: [PATCH 368/592] ARM: dts: sa2150p: override certain memory regions for sa2150p-nand override wlan, adsp and qseecom region for sa2150p-nand target Change-Id: I3aed994caf4680d06095154faca169d8564d0bee Signed-off-by: Pavankumar Vijapur --- arch/arm64/boot/dts/qcom/sa2145p-ccard-nand-dc.dts | 8 ++++++++ arch/arm64/boot/dts/qcom/sa2150p-ccard-nand-dc.dts | 14 ++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sa2145p-ccard-nand-dc.dts b/arch/arm64/boot/dts/qcom/sa2145p-ccard-nand-dc.dts index 3ebad18c8340..a2e884503dc6 100644 --- a/arch/arm64/boot/dts/qcom/sa2145p-ccard-nand-dc.dts +++ b/arch/arm64/boot/dts/qcom/sa2145p-ccard-nand-dc.dts @@ -36,3 +36,11 @@ &blsp1_uart4_hs { status = "disabled"; }; + +&wlan_fw_mem { + reg = <0x0 0x86400000 0x0 0x100000>; +}; + +&qseecom_mem { + size = <0 0x400000>; +}; diff --git a/arch/arm64/boot/dts/qcom/sa2150p-ccard-nand-dc.dts b/arch/arm64/boot/dts/qcom/sa2150p-ccard-nand-dc.dts index a6183bd11c49..4888ca907038 100644 --- a/arch/arm64/boot/dts/qcom/sa2150p-ccard-nand-dc.dts +++ b/arch/arm64/boot/dts/qcom/sa2150p-ccard-nand-dc.dts @@ -104,3 +104,17 @@ &blsp1_uart4_hs { status = "disabled"; }; + +&wlan_fw_mem { + reg = <0x0 0x86400000 0x0 0x100000>; +}; + +&reserved_mem { + linux,cma { + size = <0 0x400000>; + }; +}; + +&qseecom_mem { + size = <0 0x400000>; +}; From 5b7ee90fd35eee659299aa1173f5659985a52760 Mon Sep 17 00:00:00 2001 From: Pavankumar Vijapur Date: Fri, 31 Jul 2020 22:09:04 +0530 Subject: [PATCH 369/592] ARM: dts: sa2150p: delete wlan related nodes for sa2150p target As WLAN use cases are not PORed for sa2150p target, delete wlan related nodes and reserved memory. Change-Id: I015e2d0f9b5bb2ab7170a2f7cb2302e71f4d24aa Signed-off-by: Pavankumar Vijapur --- arch/arm64/boot/dts/qcom/sa2145p-ccard-nand-dc.dts | 10 ++++++++++ arch/arm64/boot/dts/qcom/sa2150p-ccard-nand-dc.dts | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sa2145p-ccard-nand-dc.dts b/arch/arm64/boot/dts/qcom/sa2145p-ccard-nand-dc.dts index a2e884503dc6..3a5c5aef5c77 100644 --- a/arch/arm64/boot/dts/qcom/sa2145p-ccard-nand-dc.dts +++ b/arch/arm64/boot/dts/qcom/sa2145p-ccard-nand-dc.dts @@ -44,3 +44,13 @@ &qseecom_mem { size = <0 0x400000>; }; + +&soc { + /delete-node/ qcom,wlan_dsp@7000000; + /delete-node/ qcom,icnss@18800000; +}; + +&reserved_mem { + /delete-node/ wlan_msa_region@88E0000; + /delete-node/ wlan_fw_mem@86400000; +}; diff --git a/arch/arm64/boot/dts/qcom/sa2150p-ccard-nand-dc.dts b/arch/arm64/boot/dts/qcom/sa2150p-ccard-nand-dc.dts index 4888ca907038..fb3ae4f7843d 100644 --- a/arch/arm64/boot/dts/qcom/sa2150p-ccard-nand-dc.dts +++ b/arch/arm64/boot/dts/qcom/sa2150p-ccard-nand-dc.dts @@ -118,3 +118,13 @@ &qseecom_mem { size = <0 0x400000>; }; + +&soc { + /delete-node/ qcom,wlan_dsp@7000000; + /delete-node/ qcom,icnss@18800000; +}; + +&reserved_mem { + /delete-node/ wlan_msa_region@88E0000; + /delete-node/ wlan_fw_mem@86400000; +}; From 9ef4d26365df9cb3f15f632c51ddd1ee65f62af1 Mon Sep 17 00:00:00 2001 From: Skylar Chang Date: Wed, 22 Jul 2020 23:25:35 -0700 Subject: [PATCH 370/592] msm: ipa3: put ecm default as vlan in auto config Made the change to put ecm as default in vlan mode on auto configuration to resolve the issue where usb connects to IPA faster than ipa-driver getting vlan info from user-space. Change-Id: I83d876e555e06eba762d98394e155df9b9797820 Signed-off-by: Skylar Chang --- drivers/platform/msm/ipa/ipa_v3/ipa.c | 14 ++++++++++++++ drivers/platform/msm/ipa/ipa_v3/ipa_i.h | 1 + 2 files changed, 15 insertions(+) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c index a1191427c30c..d46d50b82387 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c @@ -6597,6 +6597,9 @@ static ssize_t ipa3_write(struct file *file, const char __user *buf, /* Check MHI configuration on MDM devices */ if (!ipa3_is_msm_device()) { + /* reset ecm default as non-vlan mode */ + if (!ipa3_ctx->vlan_mode_set && ipa3_ctx->ipa_config_is_auto) + ipa3_ctx->vlan_mode_iface[IPA_VLAN_IF_ECM] = false; if (strnstr(dbg_buff, "vlan", strlen(dbg_buff))) { if (strnstr(dbg_buff, "eth", strlen(dbg_buff))) @@ -6613,6 +6616,13 @@ static ssize_t ipa3_write(struct file *file, const char __user *buf, * when vlan mode is passed to our dev we expect * another write */ + ipa3_ctx->vlan_mode_set = true; + IPAERR("emac vlan(%d)\n", + ipa3_ctx->vlan_mode_iface[IPA_VLAN_IF_EMAC]); + IPAERR("rndis vlan(%d)\n", + ipa3_ctx->vlan_mode_iface[IPA_VLAN_IF_RNDIS]); + IPAERR("ecm vlan(%d)\n", + ipa3_ctx->vlan_mode_iface[IPA_VLAN_IF_ECM]); return count; } @@ -7356,6 +7366,10 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p, mutex_init(&ipa3_ctx->app_clock_vote.mutex); + /* put ecm default as vlan mode */ + if (ipa3_ctx->ipa_config_is_auto) + ipa3_ctx->vlan_mode_iface[IPA_VLAN_IF_ECM] = true; + return 0; fail_cdev_add: diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h index 16e5db011bb8..2b1128445688 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h @@ -1986,6 +1986,7 @@ struct ipa3_context { int num_ipa_cne_evt_req; struct mutex ipa_cne_evt_lock; bool use_ipa_pm; + bool vlan_mode_set; bool vlan_mode_iface[IPA_VLAN_IF_MAX]; bool wdi_over_pcie; u32 entire_ipa_block_size; From b73e822d12ecbea7cad3742c46fd1be17aa141c8 Mon Sep 17 00:00:00 2001 From: Srinivasarao P Date: Thu, 30 Jul 2020 01:04:27 +0530 Subject: [PATCH 371/592] Reverting crypto patches c57952b UPSTREAM: ubifs: wire up FS_IOC_GET_ENCRYPTION_NONCE 379237b UPSTREAM: f2fs: wire up FS_IOC_GET_ENCRYPTION_NONCE 10e5acf UPSTREAM: ext4: wire up FS_IOC_GET_ENCRYPTION_NONCE 63bf273 ANDROID: scsi: ufs: add ->map_sg_crypto() variant op 10d4512 FROMLIST: f2fs: Handle casefolding with Encryption 4efb7e2 ANDROID: fscrypt: fall back to filesystem-layer crypto when needed a14fa7b ANDROID: block: require drivers to declare supported crypto key type(s) 5578bea ANDROID: block: make blk_crypto_start_using_mode() properly check for support e9c80bd UPSTREAM: fscrypt: add FS_IOC_GET_ENCRYPTION_NONCE ioctl 9e469e7 UPSTREAM: fscrypt: don't evict dirty inodes after removing key 53f2446 fscrypt: don't evict dirty inodes after removing key 207be96 FROMLIST: fscrypt: Have filesystems handle their d_ops 06ab740 ANDROID: dm: Add wrapped key support in dm-default-key 23e670a ANDROID: dm: add support for passing through derive_raw_secret 166fda7 ANDROID: block: Prevent crypto fallback for wrapped keys fe6e855 fscrypt: improve format of no-key names 216d8ca fscrypt: clarify what is meant by a per-file key 7e25032 fscrypt: derive dirhash key for casefolded directories e16d849 fscrypt: don't allow v1 policies with casefolding 0bc68c1 fscrypt: add "fscrypt_" prefix to fname_encrypt() 85b9c3e fscrypt: don't print name of busy file when removing key 9c5c8c5 fscrypt: document gfp_flags for bounce page allocation bee5bd5 fscrypt: optimize fscrypt_zeroout_range() 1c88eea fscrypt: remove redundant bi_status check 04f5184 fscrypt: Allow modular crypto algorithms 737ae90 fscrypt: include in UAPI header 8842133 fscrypt: don't check for ENOKEY from fscrypt_get_encryption_info() b21b79d fscrypt: remove fscrypt_is_direct_key_policy() 19b132b fscrypt: move fscrypt_valid_enc_modes() to policy.c add6ac4 fscrypt: check for appropriate use of DIRECT_KEY flag earlier 2454b5b fscrypt: split up fscrypt_supported_policy() by policy version bfa4ca6 fscrypt: introduce fscrypt_needs_contents_encryption() 3871977 fscrypt: move fscrypt_d_revalidate() to fname.c 39a0acc fscrypt: constify inode parameter to filename encryption functions 3942229 fscrypt: constify struct fscrypt_hkdf parameter to fscrypt_hkdf_expand() a7b6398 fscrypt: verify that the crypto_skcipher has the correct ivsize 9c1b3af fscrypt: use crypto_skcipher_driver_name() 3529026 fscrypt: support passing a keyring key to FS_IOC_ADD_ENCRYPTION_KEY Change-Id: Ib1abe832e16d5f40bfcc9e34bdccbb063b37dbbc Signed-off-by: Srinivasarao P --- Documentation/filesystems/fscrypt.rst | 86 ++----- block/blk-crypto-fallback.c | 50 ++-- block/blk-crypto-internal.h | 9 - block/blk-crypto.c | 55 +---- block/keyslot-manager.c | 30 +-- drivers/md/dm-default-key.c | 29 +-- drivers/md/dm.c | 80 +------ drivers/scsi/ufs/ufshcd-crypto.c | 12 +- drivers/scsi/ufs/ufshcd-crypto.h | 8 - drivers/scsi/ufs/ufshcd.c | 2 +- drivers/scsi/ufs/ufshcd.h | 1 - fs/crypto/Kconfig | 22 +- fs/crypto/bio.c | 175 ++++---------- fs/crypto/crypto.c | 57 ++++- fs/crypto/fname.c | 314 ++++++-------------------- fs/crypto/fscrypt_private.h | 87 ++++--- fs/crypto/hkdf.c | 2 +- fs/crypto/hooks.c | 48 +--- fs/crypto/inline_crypt.c | 74 ++---- fs/crypto/keyring.c | 160 +++---------- fs/crypto/keysetup.c | 141 +++++------- fs/crypto/keysetup_v1.c | 21 +- fs/crypto/policy.c | 191 +++++----------- fs/ext4/Kconfig | 1 - fs/ext4/dir.c | 9 +- fs/ext4/ioctl.c | 6 - fs/ext4/namei.c | 1 - fs/ext4/super.c | 5 + fs/f2fs/Kconfig | 1 - fs/f2fs/dir.c | 74 +++--- fs/f2fs/f2fs.h | 14 +- fs/f2fs/file.c | 11 - fs/f2fs/hash.c | 25 +- fs/f2fs/inline.c | 9 +- fs/f2fs/namei.c | 1 - fs/f2fs/super.c | 7 + fs/inode.c | 3 +- fs/libfs.c | 50 ---- fs/ubifs/Kconfig | 1 - fs/ubifs/dir.c | 20 +- fs/ubifs/ioctl.c | 4 - include/linux/bio-crypt-ctx.h | 3 - include/linux/blk-crypto.h | 18 +- include/linux/fs.h | 2 - include/linux/fscrypt.h | 134 ++++++----- include/linux/keyslot-manager.h | 14 +- include/uapi/linux/fscrypt.h | 15 +- 47 files changed, 617 insertions(+), 1465 deletions(-) diff --git a/Documentation/filesystems/fscrypt.rst b/Documentation/filesystems/fscrypt.rst index dc444b8d3704..471a511c7508 100644 --- a/Documentation/filesystems/fscrypt.rst +++ b/Documentation/filesystems/fscrypt.rst @@ -234,8 +234,8 @@ HKDF is more flexible, is nonreversible, and evenly distributes entropy from the master key. HKDF is also standardized and widely used by other software, whereas the AES-128-ECB based KDF is ad-hoc. -Per-file encryption keys ------------------------- +Per-file keys +------------- Since each master key can protect many files, it is necessary to "tweak" the encryption of each file so that the same plaintext in two @@ -268,9 +268,9 @@ is greater than that of an AES-256-XTS key. Therefore, to improve performance and save memory, for Adiantum a "direct key" configuration is supported. When the user has enabled this by setting FSCRYPT_POLICY_FLAG_DIRECT_KEY in the fscrypt policy, -per-file encryption keys are not used. Instead, whenever any data -(contents or filenames) is encrypted, the file's 16-byte nonce is -included in the IV. Moreover: +per-file keys are not used. Instead, whenever any data (contents or +filenames) is encrypted, the file's 16-byte nonce is included in the +IV. Moreover: - For v1 encryption policies, the encryption is done directly with the master key. Because of this, users **must not** use the same master @@ -302,16 +302,6 @@ For master keys used for v2 encryption policies, a unique 16-byte "key identifier" is also derived using the KDF. This value is stored in the clear, since it is needed to reliably identify the key itself. -Dirhash keys ------------- - -For directories that are indexed using a secret-keyed dirhash over the -plaintext filenames, the KDF is also used to derive a 128-bit -SipHash-2-4 key per directory in order to hash filenames. This works -just like deriving a per-file encryption key, except that a different -KDF context is used. Currently, only casefolded ("case-insensitive") -encrypted directories use this style of hashing. - Encryption modes and usage ========================== @@ -335,11 +325,11 @@ used. Adiantum is a (primarily) stream cipher-based mode that is fast even on CPUs without dedicated crypto instructions. It's also a true wide-block mode, unlike XTS. It can also eliminate the need to derive -per-file encryption keys. However, it depends on the security of two -primitives, XChaCha12 and AES-256, rather than just one. See the -paper "Adiantum: length-preserving encryption for entry-level -processors" (https://eprint.iacr.org/2018/720.pdf) for more details. -To use Adiantum, CONFIG_CRYPTO_ADIANTUM must be enabled. Also, fast +per-file keys. However, it depends on the security of two primitives, +XChaCha12 and AES-256, rather than just one. See the paper +"Adiantum: length-preserving encryption for entry-level processors" +(https://eprint.iacr.org/2018/720.pdf) for more details. To use +Adiantum, CONFIG_CRYPTO_ADIANTUM must be enabled. Also, fast implementations of ChaCha and NHPoly1305 should be enabled, e.g. CONFIG_CRYPTO_CHACHA20_NEON and CONFIG_CRYPTO_NHPOLY1305_NEON for ARM. @@ -523,9 +513,7 @@ FS_IOC_SET_ENCRYPTION_POLICY can fail with the following errors: - ``EEXIST``: the file is already encrypted with an encryption policy different from the one specified - ``EINVAL``: an invalid encryption policy was specified (invalid - version, mode(s), or flags; or reserved bits were set); or a v1 - encryption policy was specified but the directory has the casefold - flag enabled (casefolding is incompatible with v1 policies). + version, mode(s), or flags; or reserved bits were set) - ``ENOKEY``: a v2 encryption policy was specified, but the key with the specified ``master_key_identifier`` has not been added, nor does the process have the CAP_FOWNER capability in the initial user @@ -633,17 +621,6 @@ from a passphrase or other low-entropy user credential. FS_IOC_GET_ENCRYPTION_PWSALT is deprecated. Instead, prefer to generate and manage any needed salt(s) in userspace. -Getting a file's encryption nonce ---------------------------------- - -Since Linux v5.7, the ioctl FS_IOC_GET_ENCRYPTION_NONCE is supported. -On encrypted files and directories it gets the inode's 16-byte nonce. -On unencrypted files and directories, it fails with ENODATA. - -This ioctl can be useful for automated tests which verify that the -encryption is being done correctly. It is not needed for normal use -of fscrypt. - Adding keys ----------- @@ -661,8 +638,7 @@ follows:: struct fscrypt_add_key_arg { struct fscrypt_key_specifier key_spec; __u32 raw_size; - __u32 key_id; - __u32 __reserved[8]; + __u32 __reserved[9]; __u8 raw[]; }; @@ -679,12 +655,6 @@ follows:: } u; }; - struct fscrypt_provisioning_key_payload { - __u32 type; - __u32 __reserved; - __u8 raw[]; - }; - :c:type:`struct fscrypt_add_key_arg` must be zeroed, then initialized as follows: @@ -707,26 +677,9 @@ as follows: ``Documentation/security/keys/core.rst``). - ``raw_size`` must be the size of the ``raw`` key provided, in bytes. - Alternatively, if ``key_id`` is nonzero, this field must be 0, since - in that case the size is implied by the specified Linux keyring key. - -- ``key_id`` is 0 if the raw key is given directly in the ``raw`` - field. Otherwise ``key_id`` is the ID of a Linux keyring key of - type "fscrypt-provisioning" whose payload is a :c:type:`struct - fscrypt_provisioning_key_payload` whose ``raw`` field contains the - raw key and whose ``type`` field matches ``key_spec.type``. Since - ``raw`` is variable-length, the total size of this key's payload - must be ``sizeof(struct fscrypt_provisioning_key_payload)`` plus the - raw key size. The process must have Search permission on this key. - - Most users should leave this 0 and specify the raw key directly. - The support for specifying a Linux keyring key is intended mainly to - allow re-adding keys after a filesystem is unmounted and re-mounted, - without having to store the raw keys in userspace memory. - ``raw`` is a variable-length field which must contain the actual - key, ``raw_size`` bytes long. Alternatively, if ``key_id`` is - nonzero, then this field is unused. + key, ``raw_size`` bytes long. For v2 policy keys, the kernel keeps track of which user (identified by effective user ID) added the key, and only allows the key to be @@ -748,16 +701,11 @@ FS_IOC_ADD_ENCRYPTION_KEY can fail with the following errors: - ``EACCES``: FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR was specified, but the caller does not have the CAP_SYS_ADMIN capability in the initial - user namespace; or the raw key was specified by Linux key ID but the - process lacks Search permission on the key. + user namespace - ``EDQUOT``: the key quota for this user would be exceeded by adding the key - ``EINVAL``: invalid key size or key specifier type, or reserved bits were set -- ``EKEYREJECTED``: the raw key was specified by Linux key ID, but the - key has the wrong type -- ``ENOKEY``: the raw key was specified by Linux key ID, but no key - exists with that ID - ``ENOTTY``: this type of filesystem does not implement encryption - ``EOPNOTSUPP``: the kernel was not configured with encryption support for this filesystem, or the filesystem superblock has not @@ -1160,8 +1108,8 @@ The context structs contain the same information as the corresponding policy structs (see `Setting an encryption policy`_), except that the context structs also contain a nonce. The nonce is randomly generated by the kernel and is used as KDF input or as a tweak to cause -different files to be encrypted differently; see `Per-file encryption -keys`_ and `DIRECT_KEY policies`_. +different files to be encrypted differently; see `Per-file keys`_ and +`DIRECT_KEY policies`_. Data path changes ----------------- @@ -1213,7 +1161,7 @@ filesystem-specific hash(es) needed for directory lookups. This allows the filesystem to still, with a high degree of confidence, map the filename given in ->lookup() back to a particular directory entry that was previously listed by readdir(). See :c:type:`struct -fscrypt_nokey_name` in the source for more details. +fscrypt_digested_name` in the source for more details. Note that the precise way that filenames are presented to userspace without the key is subject to change in the future. It is only meant diff --git a/block/blk-crypto-fallback.c b/block/blk-crypto-fallback.c index ad83e1077ba3..b8e9ae1c1d5b 100644 --- a/block/blk-crypto-fallback.c +++ b/block/blk-crypto-fallback.c @@ -487,13 +487,21 @@ out: return false; } -/* - * Prepare blk-crypto-fallback for the specified crypto mode. - * Returns -ENOPKG if the needed crypto API support is missing. +/** + * blk_crypto_start_using_mode() - Start using a crypto algorithm on a device + * @mode_num: the blk_crypto_mode we want to allocate ciphers for. + * @data_unit_size: the data unit size that will be used + * @q: the request queue for the device + * + * Upper layers must call this function to ensure that a the crypto API fallback + * has transforms for this algorithm, if they become necessary. + * + * Return: 0 on success and -err on error. */ -int blk_crypto_fallback_start_using_mode(enum blk_crypto_mode_num mode_num) +int blk_crypto_start_using_mode(enum blk_crypto_mode_num mode_num, + unsigned int data_unit_size, + struct request_queue *q) { - const char *cipher_str = blk_crypto_modes[mode_num].cipher_str; struct blk_crypto_keyslot *slotp; unsigned int i; int err = 0; @@ -506,20 +514,25 @@ int blk_crypto_fallback_start_using_mode(enum blk_crypto_mode_num mode_num) if (likely(smp_load_acquire(&tfms_inited[mode_num]))) return 0; + /* + * If the keyslot manager of the request queue supports this + * crypto mode, then we don't need to allocate this mode. + */ + if (keyslot_manager_crypto_mode_supported(q->ksm, mode_num, + data_unit_size)) + return 0; + mutex_lock(&tfms_init_lock); if (likely(tfms_inited[mode_num])) goto out; for (i = 0; i < blk_crypto_num_keyslots; i++) { slotp = &blk_crypto_keyslots[i]; - slotp->tfms[mode_num] = crypto_alloc_skcipher(cipher_str, 0, 0); + slotp->tfms[mode_num] = crypto_alloc_skcipher( + blk_crypto_modes[mode_num].cipher_str, + 0, 0); if (IS_ERR(slotp->tfms[mode_num])) { err = PTR_ERR(slotp->tfms[mode_num]); - if (err == -ENOENT) { - pr_warn_once("Missing crypto API support for \"%s\"\n", - cipher_str); - err = -ENOPKG; - } slotp->tfms[mode_num] = NULL; goto out_free_tfms; } @@ -545,6 +558,7 @@ out: mutex_unlock(&tfms_init_lock); return err; } +EXPORT_SYMBOL_GPL(blk_crypto_start_using_mode); int blk_crypto_fallback_evict_key(const struct blk_crypto_key *key) { @@ -557,12 +571,6 @@ int blk_crypto_fallback_submit_bio(struct bio **bio_ptr) struct bio_crypt_ctx *bc = bio->bi_crypt_context; struct bio_fallback_crypt_ctx *f_ctx; - if (bc->bc_key->is_hw_wrapped) { - pr_warn_once("HW wrapped key cannot be used with fallback.\n"); - bio->bi_status = BLK_STS_NOTSUPP; - return -EOPNOTSUPP; - } - if (!tfms_inited[bc->bc_key->crypto_mode]) { bio->bi_status = BLK_STS_IOERR; return -EIO; @@ -600,11 +608,9 @@ int __init blk_crypto_fallback_init(void) crypto_mode_supported[i] = 0xFFFFFFFF; crypto_mode_supported[BLK_ENCRYPTION_MODE_INVALID] = 0; - blk_crypto_ksm = keyslot_manager_create( - NULL, blk_crypto_num_keyslots, - &blk_crypto_ksm_ll_ops, - BLK_CRYPTO_FEATURE_STANDARD_KEYS, - crypto_mode_supported, NULL); + blk_crypto_ksm = keyslot_manager_create(NULL, blk_crypto_num_keyslots, + &blk_crypto_ksm_ll_ops, + crypto_mode_supported, NULL); if (!blk_crypto_ksm) return -ENOMEM; diff --git a/block/blk-crypto-internal.h b/block/blk-crypto-internal.h index 4da998c803f2..40d826b743da 100644 --- a/block/blk-crypto-internal.h +++ b/block/blk-crypto-internal.h @@ -19,8 +19,6 @@ extern const struct blk_crypto_mode blk_crypto_modes[]; #ifdef CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK -int blk_crypto_fallback_start_using_mode(enum blk_crypto_mode_num mode_num); - int blk_crypto_fallback_submit_bio(struct bio **bio_ptr); bool blk_crypto_queue_decrypt_bio(struct bio *bio); @@ -31,13 +29,6 @@ bool bio_crypt_fallback_crypted(const struct bio_crypt_ctx *bc); #else /* CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK */ -static inline int -blk_crypto_fallback_start_using_mode(enum blk_crypto_mode_num mode_num) -{ - pr_warn_once("crypto API fallback is disabled\n"); - return -ENOPKG; -} - static inline bool bio_crypt_fallback_crypted(const struct bio_crypt_ctx *bc) { return false; diff --git a/block/blk-crypto.c b/block/blk-crypto.c index f56bbec1132f..a8de0d9680e0 100644 --- a/block/blk-crypto.c +++ b/block/blk-crypto.c @@ -109,8 +109,7 @@ int blk_crypto_submit_bio(struct bio **bio_ptr) /* Get device keyslot if supported */ if (keyslot_manager_crypto_mode_supported(q->ksm, bc->bc_key->crypto_mode, - bc->bc_key->data_unit_size, - bc->bc_key->is_hw_wrapped)) { + bc->bc_key->data_unit_size)) { err = bio_crypt_ctx_acquire_keyslot(bc, q->ksm); if (!err) return 0; @@ -176,9 +175,7 @@ bool blk_crypto_endio(struct bio *bio) * @raw_key_size: Size of raw key. Must be at least the required size for the * chosen @crypto_mode; see blk_crypto_modes[]. (It's allowed * to be longer than the mode's actual key size, in order to - * support inline encryption hardware that accepts wrapped keys. - * @is_hw_wrapped has to be set for such keys) - * @is_hw_wrapped: Denotes @raw_key is wrapped. + * support inline encryption hardware that accepts wrapped keys.) * @crypto_mode: identifier for the encryption algorithm to use * @data_unit_size: the data unit size to use for en/decryption * @@ -187,7 +184,6 @@ bool blk_crypto_endio(struct bio *bio) */ int blk_crypto_init_key(struct blk_crypto_key *blk_key, const u8 *raw_key, unsigned int raw_key_size, - bool is_hw_wrapped, enum blk_crypto_mode_num crypto_mode, unsigned int data_unit_size) { @@ -202,14 +198,9 @@ int blk_crypto_init_key(struct blk_crypto_key *blk_key, BUILD_BUG_ON(BLK_CRYPTO_MAX_WRAPPED_KEY_SIZE < BLK_CRYPTO_MAX_KEY_SIZE); mode = &blk_crypto_modes[crypto_mode]; - if (is_hw_wrapped) { - if (raw_key_size < mode->keysize || - raw_key_size > BLK_CRYPTO_MAX_WRAPPED_KEY_SIZE) - return -EINVAL; - } else { - if (raw_key_size != mode->keysize) - return -EINVAL; - } + if (raw_key_size < mode->keysize || + raw_key_size > BLK_CRYPTO_MAX_WRAPPED_KEY_SIZE) + return -EINVAL; if (!is_power_of_2(data_unit_size)) return -EINVAL; @@ -218,7 +209,6 @@ int blk_crypto_init_key(struct blk_crypto_key *blk_key, blk_key->data_unit_size = data_unit_size; blk_key->data_unit_size_bits = ilog2(data_unit_size); blk_key->size = raw_key_size; - blk_key->is_hw_wrapped = is_hw_wrapped; memcpy(blk_key->raw, raw_key, raw_key_size); /* @@ -233,38 +223,6 @@ int blk_crypto_init_key(struct blk_crypto_key *blk_key, } EXPORT_SYMBOL_GPL(blk_crypto_init_key); -/** - * blk_crypto_start_using_mode() - Start using blk-crypto on a device - * @crypto_mode: the crypto mode that will be used - * @data_unit_size: the data unit size that will be used - * @is_hw_wrapped_key: whether the key will be hardware-wrapped - * @q: the request queue for the device - * - * Upper layers must call this function to ensure that either the hardware - * supports the needed crypto settings, or the crypto API fallback has - * transforms for the needed mode allocated and ready to go. - * - * Return: 0 on success; -ENOPKG if the hardware doesn't support the crypto - * settings and blk-crypto-fallback is either disabled or the needed - * algorithm is disabled in the crypto API; or another -errno code. - */ -int blk_crypto_start_using_mode(enum blk_crypto_mode_num crypto_mode, - unsigned int data_unit_size, - bool is_hw_wrapped_key, - struct request_queue *q) -{ - if (keyslot_manager_crypto_mode_supported(q->ksm, crypto_mode, - data_unit_size, - is_hw_wrapped_key)) - return 0; - if (is_hw_wrapped_key) { - pr_warn_once("hardware doesn't support wrapped keys\n"); - return -EOPNOTSUPP; - } - return blk_crypto_fallback_start_using_mode(crypto_mode); -} -EXPORT_SYMBOL_GPL(blk_crypto_start_using_mode); - /** * blk_crypto_evict_key() - Evict a key from any inline encryption hardware * it may have been programmed into @@ -285,8 +243,7 @@ int blk_crypto_evict_key(struct request_queue *q, { if (q->ksm && keyslot_manager_crypto_mode_supported(q->ksm, key->crypto_mode, - key->data_unit_size, - key->is_hw_wrapped)) + key->data_unit_size)) return keyslot_manager_evict_key(q->ksm, key); return blk_crypto_fallback_evict_key(key); diff --git a/block/keyslot-manager.c b/block/keyslot-manager.c index fe7dff3cae79..0b6dd460645e 100644 --- a/block/keyslot-manager.c +++ b/block/keyslot-manager.c @@ -44,7 +44,6 @@ struct keyslot { struct keyslot_manager { unsigned int num_slots; struct keyslot_mgmt_ll_ops ksm_ll_ops; - unsigned int features; unsigned int crypto_mode_supported[BLK_ENCRYPTION_MODE_MAX]; void *ll_priv_data; @@ -137,8 +136,6 @@ static inline void keyslot_manager_hw_exit(struct keyslot_manager *ksm) * @ksm_ll_ops: The struct keyslot_mgmt_ll_ops for the device that this keyslot * manager will use to perform operations like programming and * evicting keys. - * @features: The supported features as a bitmask of BLK_CRYPTO_FEATURE_* flags. - * Most drivers should set BLK_CRYPTO_FEATURE_STANDARD_KEYS here. * @crypto_mode_supported: Array of size BLK_ENCRYPTION_MODE_MAX of * bitmasks that represents whether a crypto mode * and data unit size are supported. The i'th bit @@ -158,7 +155,6 @@ struct keyslot_manager *keyslot_manager_create( struct device *dev, unsigned int num_slots, const struct keyslot_mgmt_ll_ops *ksm_ll_ops, - unsigned int features, const unsigned int crypto_mode_supported[BLK_ENCRYPTION_MODE_MAX], void *ll_priv_data) { @@ -180,7 +176,6 @@ struct keyslot_manager *keyslot_manager_create( ksm->num_slots = num_slots; ksm->ksm_ll_ops = *ksm_ll_ops; - ksm->features = features; memcpy(ksm->crypto_mode_supported, crypto_mode_supported, sizeof(ksm->crypto_mode_supported)); ksm->ll_priv_data = ll_priv_data; @@ -387,24 +382,23 @@ void keyslot_manager_put_slot(struct keyslot_manager *ksm, unsigned int slot) } /** - * keyslot_manager_crypto_mode_supported() - Find out if a crypto_mode / - * data unit size / is_hw_wrapped_key - * combination is supported by a ksm. + * keyslot_manager_crypto_mode_supported() - Find out if a crypto_mode/data + * unit size combination is supported + * by a ksm. * @ksm: The keyslot manager to check * @crypto_mode: The crypto mode to check for. * @data_unit_size: The data_unit_size for the mode. - * @is_hw_wrapped_key: Whether a hardware-wrapped key will be used. * * Calls and returns the result of the crypto_mode_supported function specified * by the ksm. * * Context: Process context. - * Return: Whether or not this ksm supports the specified crypto settings. + * Return: Whether or not this ksm supports the specified crypto_mode/ + * data_unit_size combo. */ bool keyslot_manager_crypto_mode_supported(struct keyslot_manager *ksm, enum blk_crypto_mode_num crypto_mode, - unsigned int data_unit_size, - bool is_hw_wrapped_key) + unsigned int data_unit_size) { if (!ksm) return false; @@ -412,13 +406,6 @@ bool keyslot_manager_crypto_mode_supported(struct keyslot_manager *ksm, return false; if (WARN_ON(!is_power_of_2(data_unit_size))) return false; - if (is_hw_wrapped_key) { - if (!(ksm->features & BLK_CRYPTO_FEATURE_WRAPPED_KEYS)) - return false; - } else { - if (!(ksm->features & BLK_CRYPTO_FEATURE_STANDARD_KEYS)) - return false; - } return ksm->crypto_mode_supported[crypto_mode] & data_unit_size; } @@ -534,7 +521,6 @@ EXPORT_SYMBOL_GPL(keyslot_manager_destroy); * keyslot_manager_create_passthrough() - Create a passthrough keyslot manager * @dev: Device for runtime power management (NULL if none) * @ksm_ll_ops: The struct keyslot_mgmt_ll_ops - * @features: Bitmask of BLK_CRYPTO_FEATURE_* flags * @crypto_mode_supported: Bitmasks for supported encryption modes * @ll_priv_data: Private data passed as is to the functions in ksm_ll_ops. * @@ -552,7 +538,6 @@ EXPORT_SYMBOL_GPL(keyslot_manager_destroy); struct keyslot_manager *keyslot_manager_create_passthrough( struct device *dev, const struct keyslot_mgmt_ll_ops *ksm_ll_ops, - unsigned int features, const unsigned int crypto_mode_supported[BLK_ENCRYPTION_MODE_MAX], void *ll_priv_data) { @@ -563,7 +548,6 @@ struct keyslot_manager *keyslot_manager_create_passthrough( return NULL; ksm->ksm_ll_ops = *ksm_ll_ops; - ksm->features = features; memcpy(ksm->crypto_mode_supported, crypto_mode_supported, sizeof(ksm->crypto_mode_supported)); ksm->ll_priv_data = ll_priv_data; @@ -592,13 +576,11 @@ void keyslot_manager_intersect_modes(struct keyslot_manager *parent, if (child) { unsigned int i; - parent->features &= child->features; for (i = 0; i < ARRAY_SIZE(child->crypto_mode_supported); i++) { parent->crypto_mode_supported[i] &= child->crypto_mode_supported[i]; } } else { - parent->features = 0; memset(parent->crypto_mode_supported, 0, sizeof(parent->crypto_mode_supported)); } diff --git a/drivers/md/dm-default-key.c b/drivers/md/dm-default-key.c index 3d0bd0645f7a..43a30c076aa6 100644 --- a/drivers/md/dm-default-key.c +++ b/drivers/md/dm-default-key.c @@ -9,7 +9,7 @@ #define DM_MSG_PREFIX "default-key" -#define DM_DEFAULT_KEY_MAX_WRAPPED_KEY_SIZE 128 +#define DM_DEFAULT_KEY_MAX_KEY_SIZE 64 #define SECTOR_SIZE (1 << SECTOR_SHIFT) @@ -49,7 +49,6 @@ struct default_key_c { unsigned int sector_size; unsigned int sector_bits; struct blk_crypto_key key; - bool is_hw_wrapped; }; static const struct dm_default_key_cipher * @@ -85,7 +84,7 @@ static int default_key_ctr_optional(struct dm_target *ti, struct default_key_c *dkc = ti->private; struct dm_arg_set as; static const struct dm_arg _args[] = { - {0, 4, "Invalid number of feature args"}, + {0, 3, "Invalid number of feature args"}, }; unsigned int opt_params; const char *opt_string; @@ -118,8 +117,6 @@ static int default_key_ctr_optional(struct dm_target *ti, } } else if (!strcmp(opt_string, "iv_large_sectors")) { iv_large_sectors = true; - } else if (!strcmp(opt_string, "wrappedkey_v0")) { - dkc->is_hw_wrapped = true; } else { ti->error = "Invalid feature arguments"; return -EINVAL; @@ -147,8 +144,7 @@ static int default_key_ctr(struct dm_target *ti, unsigned int argc, char **argv) { struct default_key_c *dkc; const struct dm_default_key_cipher *cipher; - u8 raw_key[DM_DEFAULT_KEY_MAX_WRAPPED_KEY_SIZE]; - unsigned int raw_key_size; + u8 raw_key[DM_DEFAULT_KEY_MAX_KEY_SIZE]; unsigned long long tmpll; char dummy; int err; @@ -180,15 +176,12 @@ static int default_key_ctr(struct dm_target *ti, unsigned int argc, char **argv) } /* */ - raw_key_size = strlen(argv[1]); - if (raw_key_size > 2 * DM_DEFAULT_KEY_MAX_WRAPPED_KEY_SIZE || - raw_key_size % 2) { - ti->error = "Invalid keysize"; + if (strlen(argv[1]) != 2 * cipher->key_size) { + ti->error = "Incorrect key size for cipher"; err = -EINVAL; goto bad; } - raw_key_size /= 2; - if (hex2bin(raw_key, argv[1], raw_key_size) != 0) { + if (hex2bin(raw_key, argv[1], cipher->key_size) != 0) { ti->error = "Malformed key string"; err = -EINVAL; goto bad; @@ -233,15 +226,13 @@ static int default_key_ctr(struct dm_target *ti, unsigned int argc, char **argv) } err = blk_crypto_init_key(&dkc->key, raw_key, cipher->key_size, - dkc->is_hw_wrapped, cipher->mode_num, - dkc->sector_size); + cipher->mode_num, dkc->sector_size); if (err) { ti->error = "Error initializing blk-crypto key"; goto bad; } err = blk_crypto_start_using_mode(cipher->mode_num, dkc->sector_size, - dkc->is_hw_wrapped, dkc->dev->bdev->bd_queue); if (err) { ti->error = "Error starting to use blk-crypto"; @@ -328,8 +319,6 @@ static void default_key_status(struct dm_target *ti, status_type_t type, num_feature_args += !!ti->num_discard_bios; if (dkc->sector_size != SECTOR_SIZE) num_feature_args += 2; - if (dkc->is_hw_wrapped) - num_feature_args += 1; if (num_feature_args != 0) { DMEMIT(" %d", num_feature_args); if (ti->num_discard_bios) @@ -338,8 +327,6 @@ static void default_key_status(struct dm_target *ti, status_type_t type, DMEMIT(" sector_size:%u", dkc->sector_size); DMEMIT(" iv_large_sectors"); } - if (dkc->is_hw_wrapped) - DMEMIT(" wrappedkey_v0"); } break; } @@ -385,7 +372,7 @@ static void default_key_io_hints(struct dm_target *ti, static struct target_type default_key_target = { .name = "default-key", - .version = {2, 1, 0}, + .version = {2, 0, 0}, .module = THIS_MODULE, .ctr = default_key_ctr, .dtr = default_key_dtr, diff --git a/drivers/md/dm.c b/drivers/md/dm.c index e4f0b67cd015..0271ca072453 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -2088,98 +2088,22 @@ static int dm_keyslot_evict(struct keyslot_manager *ksm, return args.err; } -struct dm_derive_raw_secret_args { - const u8 *wrapped_key; - unsigned int wrapped_key_size; - u8 *secret; - unsigned int secret_size; - int err; -}; - -static int dm_derive_raw_secret_callback(struct dm_target *ti, - struct dm_dev *dev, sector_t start, - sector_t len, void *data) -{ - struct dm_derive_raw_secret_args *args = data; - struct request_queue *q = dev->bdev->bd_queue; - - if (!args->err) - return 0; - - if (!q->ksm) { - args->err = -EOPNOTSUPP; - return 0; - } - - args->err = keyslot_manager_derive_raw_secret(q->ksm, args->wrapped_key, - args->wrapped_key_size, - args->secret, - args->secret_size); - /* Try another device in case this fails. */ - return 0; -} - -/* - * Retrieve the raw_secret from the underlying device. Given that - * only only one raw_secret can exist for a particular wrappedkey, - * retrieve it only from the first device that supports derive_raw_secret() - */ -static int dm_derive_raw_secret(struct keyslot_manager *ksm, - const u8 *wrapped_key, - unsigned int wrapped_key_size, - u8 *secret, unsigned int secret_size) -{ - struct mapped_device *md = keyslot_manager_private(ksm); - struct dm_derive_raw_secret_args args = { - .wrapped_key = wrapped_key, - .wrapped_key_size = wrapped_key_size, - .secret = secret, - .secret_size = secret_size, - .err = -EOPNOTSUPP, - }; - struct dm_table *t; - int srcu_idx; - int i; - struct dm_target *ti; - - t = dm_get_live_table(md, &srcu_idx); - if (!t) - return -EOPNOTSUPP; - for (i = 0; i < dm_table_get_num_targets(t); i++) { - ti = dm_table_get_target(t, i); - if (!ti->type->iterate_devices) - continue; - ti->type->iterate_devices(ti, dm_derive_raw_secret_callback, - &args); - if (!args.err) - break; - } - dm_put_live_table(md, srcu_idx); - return args.err; -} - static struct keyslot_mgmt_ll_ops dm_ksm_ll_ops = { .keyslot_evict = dm_keyslot_evict, - .derive_raw_secret = dm_derive_raw_secret, }; static int dm_init_inline_encryption(struct mapped_device *md) { - unsigned int features; unsigned int mode_masks[BLK_ENCRYPTION_MODE_MAX]; /* - * Initially declare support for all crypto settings. Anything - * unsupported by a child device will be removed later when calculating - * the device restrictions. + * Start out with all crypto mode support bits set. Any unsupported + * bits will be cleared later when calculating the device restrictions. */ - features = BLK_CRYPTO_FEATURE_STANDARD_KEYS | - BLK_CRYPTO_FEATURE_WRAPPED_KEYS; memset(mode_masks, 0xFF, sizeof(mode_masks)); md->queue->ksm = keyslot_manager_create_passthrough(NULL, &dm_ksm_ll_ops, - features, mode_masks, md); if (!md->queue->ksm) return -ENOMEM; diff --git a/drivers/scsi/ufs/ufshcd-crypto.c b/drivers/scsi/ufs/ufshcd-crypto.c index d62ab7a9faff..e3de448c9bbe 100644 --- a/drivers/scsi/ufs/ufshcd-crypto.c +++ b/drivers/scsi/ufs/ufshcd-crypto.c @@ -336,9 +336,7 @@ int ufshcd_hba_init_crypto_spec(struct ufs_hba *hba, ufshcd_clear_all_keyslots(hba); hba->ksm = keyslot_manager_create(hba->dev, ufshcd_num_keyslots(hba), - ksm_ops, - BLK_CRYPTO_FEATURE_STANDARD_KEYS, - crypto_modes_supported, hba); + ksm_ops, crypto_modes_supported, hba); if (!hba->ksm) { err = -ENOMEM; @@ -458,14 +456,6 @@ int ufshcd_prepare_lrbp_crypto(struct ufs_hba *hba, return ufshcd_prepare_lrbp_crypto_spec(hba, cmd, lrbp); } -int ufshcd_map_sg_crypto(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) -{ - if (hba->crypto_vops && hba->crypto_vops->map_sg_crypto) - return hba->crypto_vops->map_sg_crypto(hba, lrbp); - - return 0; -} - int ufshcd_complete_lrbp_crypto(struct ufs_hba *hba, struct scsi_cmnd *cmd, struct ufshcd_lrb *lrbp) diff --git a/drivers/scsi/ufs/ufshcd-crypto.h b/drivers/scsi/ufs/ufshcd-crypto.h index f223a06fbf93..95f37c9f7672 100644 --- a/drivers/scsi/ufs/ufshcd-crypto.h +++ b/drivers/scsi/ufs/ufshcd-crypto.h @@ -80,8 +80,6 @@ int ufshcd_prepare_lrbp_crypto(struct ufs_hba *hba, struct scsi_cmnd *cmd, struct ufshcd_lrb *lrbp); -int ufshcd_map_sg_crypto(struct ufs_hba *hba, struct ufshcd_lrb *lrbp); - int ufshcd_complete_lrbp_crypto(struct ufs_hba *hba, struct scsi_cmnd *cmd, struct ufshcd_lrb *lrbp); @@ -135,12 +133,6 @@ static inline int ufshcd_prepare_lrbp_crypto(struct ufs_hba *hba, return 0; } -static inline int ufshcd_map_sg_crypto(struct ufs_hba *hba, - struct ufshcd_lrb *lrbp) -{ - return 0; -} - static inline bool ufshcd_lrbp_crypto_enabled(struct ufshcd_lrb *lrbp) { return false; diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index b04967823764..64050a44ae9b 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -2023,7 +2023,7 @@ static int ufshcd_map_sg(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) lrbp->utr_descriptor_ptr->prd_table_length = 0; } - return ufshcd_map_sg_crypto(hba, lrbp); + return 0; } /** diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 52b5a070afa8..73124e85dada 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -354,7 +354,6 @@ struct ufs_hba_crypto_variant_ops { int (*prepare_lrbp_crypto)(struct ufs_hba *hba, struct scsi_cmnd *cmd, struct ufshcd_lrb *lrbp); - int (*map_sg_crypto)(struct ufs_hba *hba, struct ufshcd_lrb *lrbp); int (*complete_lrbp_crypto)(struct ufs_hba *hba, struct scsi_cmnd *cmd, struct ufshcd_lrb *lrbp); diff --git a/fs/crypto/Kconfig b/fs/crypto/Kconfig index 97c0a113f4cc..0701bb90f99c 100644 --- a/fs/crypto/Kconfig +++ b/fs/crypto/Kconfig @@ -1,8 +1,13 @@ config FS_ENCRYPTION bool "FS Encryption (Per-file encryption)" select CRYPTO - select CRYPTO_HASH - select CRYPTO_BLKCIPHER + select CRYPTO_AES + select CRYPTO_CBC + select CRYPTO_ECB + select CRYPTO_XTS + select CRYPTO_CTS + select CRYPTO_SHA512 + select CRYPTO_HMAC select KEYS help Enable encryption of files and directories. This @@ -11,19 +16,6 @@ config FS_ENCRYPTION decrypted pages in the page cache. Currently Ext4, F2FS and UBIFS make use of this feature. -# Filesystems supporting encryption must select this if FS_ENCRYPTION. This -# allows the algorithms to be built as modules when all the filesystems are. -config FS_ENCRYPTION_ALGS - tristate - select CRYPTO_AES - select CRYPTO_CBC - select CRYPTO_CTS - select CRYPTO_ECB - select CRYPTO_HMAC - select CRYPTO_SHA256 - select CRYPTO_SHA512 - select CRYPTO_XTS - config FS_ENCRYPTION_INLINE_CRYPT bool "Enable fscrypt to use inline crypto" depends on FS_ENCRYPTION && BLK_INLINE_ENCRYPTION diff --git a/fs/crypto/bio.c b/fs/crypto/bio.c index 0242088d213f..f62375d39b0f 100644 --- a/fs/crypto/bio.c +++ b/fs/crypto/bio.c @@ -41,154 +41,63 @@ void fscrypt_decrypt_bio(struct bio *bio) } EXPORT_SYMBOL(fscrypt_decrypt_bio); -static int fscrypt_zeroout_range_inlinecrypt(const struct inode *inode, - pgoff_t lblk, - sector_t pblk, unsigned int len) -{ - const unsigned int blockbits = inode->i_blkbits; - const unsigned int blocks_per_page_bits = PAGE_SHIFT - blockbits; - const unsigned int blocks_per_page = 1 << blocks_per_page_bits; - unsigned int i; - struct bio *bio; - int ret, err; - - /* This always succeeds since __GFP_DIRECT_RECLAIM is set. */ - bio = bio_alloc(GFP_NOFS, BIO_MAX_PAGES); - - do { - bio_set_dev(bio, inode->i_sb->s_bdev); - bio->bi_iter.bi_sector = pblk << (blockbits - 9); - bio_set_op_attrs(bio, REQ_OP_WRITE, 0); - fscrypt_set_bio_crypt_ctx(bio, inode, lblk, GFP_NOFS); - - i = 0; - do { - unsigned int blocks_this_page = - min(len, blocks_per_page); - unsigned int bytes_this_page = - blocks_this_page << blockbits; - - ret = bio_add_page(bio, ZERO_PAGE(0), - bytes_this_page, 0); - if (WARN_ON(ret != bytes_this_page)) { - err = -EIO; - goto out; - } - lblk += blocks_this_page; - pblk += blocks_this_page; - len -= blocks_this_page; - } while (++i != BIO_MAX_PAGES && len != 0); - - err = submit_bio_wait(bio); - if (err) - goto out; - bio_reset(bio); - } while (len != 0); - err = 0; -out: - bio_put(bio); - return err; -} - -/** - * fscrypt_zeroout_range() - zero out a range of blocks in an encrypted file - * @inode: the file's inode - * @lblk: the first file logical block to zero out - * @pblk: the first filesystem physical block to zero out - * @len: number of blocks to zero out - * - * Zero out filesystem blocks in an encrypted regular file on-disk, i.e. write - * ciphertext blocks which decrypt to the all-zeroes block. The blocks must be - * both logically and physically contiguous. It's also assumed that the - * filesystem only uses a single block device, ->s_bdev. - * - * Note that since each block uses a different IV, this involves writing a - * different ciphertext to each block; we can't simply reuse the same one. - * - * Return: 0 on success; -errno on failure. - */ int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk, - sector_t pblk, unsigned int len) + sector_t pblk, unsigned int len) { const unsigned int blockbits = inode->i_blkbits; const unsigned int blocksize = 1 << blockbits; - const unsigned int blocks_per_page_bits = PAGE_SHIFT - blockbits; - const unsigned int blocks_per_page = 1 << blocks_per_page_bits; - struct page *pages[16]; /* write up to 16 pages at a time */ - unsigned int nr_pages; - unsigned int i; - unsigned int offset; + const bool inlinecrypt = fscrypt_inode_uses_inline_crypto(inode); + struct page *ciphertext_page; struct bio *bio; - int ret, err; + int ret, err = 0; - if (len == 0) - return 0; - - if (fscrypt_inode_uses_inline_crypto(inode)) - return fscrypt_zeroout_range_inlinecrypt(inode, lblk, pblk, - len); - - BUILD_BUG_ON(ARRAY_SIZE(pages) > BIO_MAX_PAGES); - nr_pages = min_t(unsigned int, ARRAY_SIZE(pages), - (len + blocks_per_page - 1) >> blocks_per_page_bits); - - /* - * We need at least one page for ciphertext. Allocate the first one - * from a mempool, with __GFP_DIRECT_RECLAIM set so that it can't fail. - * - * Any additional page allocations are allowed to fail, as they only - * help performance, and waiting on the mempool for them could deadlock. - */ - for (i = 0; i < nr_pages; i++) { - pages[i] = fscrypt_alloc_bounce_page(i == 0 ? GFP_NOFS : - GFP_NOWAIT | __GFP_NOWARN); - if (!pages[i]) - break; + if (inlinecrypt) { + ciphertext_page = ZERO_PAGE(0); + } else { + ciphertext_page = fscrypt_alloc_bounce_page(GFP_NOWAIT); + if (!ciphertext_page) + return -ENOMEM; } - nr_pages = i; - if (WARN_ON(nr_pages <= 0)) - return -EINVAL; - /* This always succeeds since __GFP_DIRECT_RECLAIM is set. */ - bio = bio_alloc(GFP_NOFS, nr_pages); + while (len--) { + if (!inlinecrypt) { + err = fscrypt_crypt_block(inode, FS_ENCRYPT, lblk, + ZERO_PAGE(0), ciphertext_page, + blocksize, 0, GFP_NOFS); + if (err) + goto errout; + } + + bio = bio_alloc(GFP_NOWAIT, 1); + if (!bio) { + err = -ENOMEM; + goto errout; + } + fscrypt_set_bio_crypt_ctx(bio, inode, lblk, GFP_NOIO); - do { bio_set_dev(bio, inode->i_sb->s_bdev); bio->bi_iter.bi_sector = pblk << (blockbits - 9); bio_set_op_attrs(bio, REQ_OP_WRITE, 0); - - i = 0; - offset = 0; - do { - err = fscrypt_crypt_block(inode, FS_ENCRYPT, lblk, - ZERO_PAGE(0), pages[i], - blocksize, offset, GFP_NOFS); - if (err) - goto out; - lblk++; - pblk++; - len--; - offset += blocksize; - if (offset == PAGE_SIZE || len == 0) { - ret = bio_add_page(bio, pages[i++], offset, 0); - if (WARN_ON(ret != offset)) { - err = -EIO; - goto out; - } - offset = 0; - } - } while (i != nr_pages && len != 0); - + ret = bio_add_page(bio, ciphertext_page, blocksize, 0); + if (WARN_ON(ret != blocksize)) { + /* should never happen! */ + bio_put(bio); + err = -EIO; + goto errout; + } err = submit_bio_wait(bio); + if (err == 0 && bio->bi_status) + err = -EIO; + bio_put(bio); if (err) - goto out; - bio_reset(bio); - } while (len != 0); + goto errout; + lblk++; + pblk++; + } err = 0; -out: - bio_put(bio); - for (i = 0; i < nr_pages; i++) - fscrypt_free_bounce_page(pages[i]); +errout: + if (!inlinecrypt) + fscrypt_free_bounce_page(ciphertext_page); return err; } EXPORT_SYMBOL(fscrypt_zeroout_range); diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c index ed6ea28dbdad..41b4fe15b4b6 100644 --- a/fs/crypto/crypto.c +++ b/fs/crypto/crypto.c @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include #include "fscrypt_private.h" @@ -137,7 +139,7 @@ int fscrypt_crypt_block(const struct inode *inode, fscrypt_direction_t rw, * multiple of the filesystem's block size. * @offs: Byte offset within @page of the first block to encrypt. Must be * a multiple of the filesystem's block size. - * @gfp_flags: Memory allocation flags. See details below. + * @gfp_flags: Memory allocation flags * * A new bounce page is allocated, and the specified block(s) are encrypted into * it. In the bounce page, the ciphertext block(s) will be located at the same @@ -147,11 +149,6 @@ int fscrypt_crypt_block(const struct inode *inode, fscrypt_direction_t rw, * * This is for use by the filesystem's ->writepages() method. * - * The bounce page allocation is mempool-backed, so it will always succeed when - * @gfp_flags includes __GFP_DIRECT_RECLAIM, e.g. when it's GFP_NOFS. However, - * only the first page of each bio can be allocated this way. To prevent - * deadlocks, for any additional pages a mask like GFP_NOWAIT must be used. - * * Return: the new encrypted bounce page on success; an ERR_PTR() on failure */ struct page *fscrypt_encrypt_pagecache_blocks(struct page *page, @@ -288,6 +285,54 @@ int fscrypt_decrypt_block_inplace(const struct inode *inode, struct page *page, } EXPORT_SYMBOL(fscrypt_decrypt_block_inplace); +/* + * Validate dentries in encrypted directories to make sure we aren't potentially + * caching stale dentries after a key has been added. + */ +static int fscrypt_d_revalidate(struct dentry *dentry, unsigned int flags) +{ + struct dentry *dir; + int err; + int valid; + + /* + * Plaintext names are always valid, since fscrypt doesn't support + * reverting to ciphertext names without evicting the directory's inode + * -- which implies eviction of the dentries in the directory. + */ + if (!(dentry->d_flags & DCACHE_ENCRYPTED_NAME)) + return 1; + + /* + * Ciphertext name; valid if the directory's key is still unavailable. + * + * Although fscrypt forbids rename() on ciphertext names, we still must + * use dget_parent() here rather than use ->d_parent directly. That's + * because a corrupted fs image may contain directory hard links, which + * the VFS handles by moving the directory's dentry tree in the dcache + * each time ->lookup() finds the directory and it already has a dentry + * elsewhere. Thus ->d_parent can be changing, and we must safely grab + * a reference to some ->d_parent to prevent it from being freed. + */ + + if (flags & LOOKUP_RCU) + return -ECHILD; + + dir = dget_parent(dentry); + err = fscrypt_get_encryption_info(d_inode(dir)); + valid = !fscrypt_has_encryption_key(d_inode(dir)); + dput(dir); + + if (err < 0) + return err; + + return valid; +} + +const struct dentry_operations fscrypt_d_ops = { + .d_revalidate = fscrypt_d_revalidate, +}; + /** * fscrypt_initialize() - allocate major buffers for fs encryption. * @cop_flags: fscrypt operations flags diff --git a/fs/crypto/fname.c b/fs/crypto/fname.c index 63bfe5e8accd..3aafddaab703 100644 --- a/fs/crypto/fname.c +++ b/fs/crypto/fname.c @@ -11,88 +11,10 @@ * This has not yet undergone a rigorous security audit. */ -#include #include -#include -#include #include #include "fscrypt_private.h" -/** - * struct fscrypt_nokey_name - identifier for directory entry when key is absent - * - * When userspace lists an encrypted directory without access to the key, the - * filesystem must present a unique "no-key name" for each filename that allows - * it to find the directory entry again if requested. Naively, that would just - * mean using the ciphertext filenames. However, since the ciphertext filenames - * can contain illegal characters ('\0' and '/'), they must be encoded in some - * way. We use base64. But that can cause names to exceed NAME_MAX (255 - * bytes), so we also need to use a strong hash to abbreviate long names. - * - * The filesystem may also need another kind of hash, the "dirhash", to quickly - * find the directory entry. Since filesystems normally compute the dirhash - * over the on-disk filename (i.e. the ciphertext), it's not computable from - * no-key names that abbreviate the ciphertext using the strong hash to fit in - * NAME_MAX. It's also not computable if it's a keyed hash taken over the - * plaintext (but it may still be available in the on-disk directory entry); - * casefolded directories use this type of dirhash. At least in these cases, - * each no-key name must include the name's dirhash too. - * - * To meet all these requirements, we base64-encode the following - * variable-length structure. It contains the dirhash, or 0's if the filesystem - * didn't provide one; up to 149 bytes of the ciphertext name; and for - * ciphertexts longer than 149 bytes, also the SHA-256 of the remaining bytes. - * - * This ensures that each no-key name contains everything needed to find the - * directory entry again, contains only legal characters, doesn't exceed - * NAME_MAX, is unambiguous unless there's a SHA-256 collision, and that we only - * take the performance hit of SHA-256 on very long filenames (which are rare). - */ -struct fscrypt_nokey_name { - u32 dirhash[2]; - u8 bytes[149]; - u8 sha256[SHA256_DIGEST_SIZE]; -}; /* 189 bytes => 252 bytes base64-encoded, which is <= NAME_MAX (255) */ - -/* - * Decoded size of max-size nokey name, i.e. a name that was abbreviated using - * the strong hash and thus includes the 'sha256' field. This isn't simply - * sizeof(struct fscrypt_nokey_name), as the padding at the end isn't included. - */ -#define FSCRYPT_NOKEY_NAME_MAX offsetofend(struct fscrypt_nokey_name, sha256) - -static struct crypto_shash *sha256_hash_tfm; - -static int fscrypt_do_sha256(const u8 *data, unsigned int data_len, u8 *result) -{ - struct crypto_shash *tfm = READ_ONCE(sha256_hash_tfm); - - if (unlikely(!tfm)) { - struct crypto_shash *prev_tfm; - - tfm = crypto_alloc_shash("sha256", 0, 0); - if (IS_ERR(tfm)) { - fscrypt_err(NULL, - "Error allocating SHA-256 transform: %ld", - PTR_ERR(tfm)); - return PTR_ERR(tfm); - } - prev_tfm = cmpxchg(&sha256_hash_tfm, NULL, tfm); - if (prev_tfm) { - crypto_free_shash(tfm); - tfm = prev_tfm; - } - } - { - SHASH_DESC_ON_STACK(desc, tfm); - - desc->tfm = tfm; - desc->flags = 0; - - return crypto_shash_digest(desc, data, data_len, result); - } -} - static inline bool fscrypt_is_dot_dotdot(const struct qstr *str) { if (str->len == 1 && str->name[0] == '.') @@ -105,19 +27,19 @@ static inline bool fscrypt_is_dot_dotdot(const struct qstr *str) } /** - * fscrypt_fname_encrypt() - encrypt a filename + * fname_encrypt() - encrypt a filename * * The output buffer must be at least as large as the input buffer. * Any extra space is filled with NUL padding before encryption. * * Return: 0 on success, -errno on failure */ -int fscrypt_fname_encrypt(const struct inode *inode, const struct qstr *iname, - u8 *out, unsigned int olen) +int fname_encrypt(struct inode *inode, const struct qstr *iname, + u8 *out, unsigned int olen) { struct skcipher_request *req = NULL; DECLARE_CRYPTO_WAIT(wait); - const struct fscrypt_info *ci = inode->i_crypt_info; + struct fscrypt_info *ci = inode->i_crypt_info; struct crypto_skcipher *tfm = ci->ci_key.tfm; union fscrypt_iv iv; struct scatterlist sg; @@ -163,14 +85,14 @@ int fscrypt_fname_encrypt(const struct inode *inode, const struct qstr *iname, * * Return: 0 on success, -errno on failure */ -static int fname_decrypt(const struct inode *inode, - const struct fscrypt_str *iname, - struct fscrypt_str *oname) +static int fname_decrypt(struct inode *inode, + const struct fscrypt_str *iname, + struct fscrypt_str *oname) { struct skcipher_request *req = NULL; DECLARE_CRYPTO_WAIT(wait); struct scatterlist src_sg, dst_sg; - const struct fscrypt_info *ci = inode->i_crypt_info; + struct fscrypt_info *ci = inode->i_crypt_info; struct crypto_skcipher *tfm = ci->ci_key.tfm; union fscrypt_iv iv; int res; @@ -284,7 +206,9 @@ int fscrypt_fname_alloc_buffer(const struct inode *inode, u32 max_encrypted_len, struct fscrypt_str *crypto_str) { - const u32 max_encoded_len = BASE64_CHARS(FSCRYPT_NOKEY_NAME_MAX); + const u32 max_encoded_len = + max_t(u32, BASE64_CHARS(FSCRYPT_FNAME_MAX_UNDIGESTED_SIZE), + 1 + BASE64_CHARS(sizeof(struct fscrypt_digested_name))); u32 max_presented_len; max_presented_len = max(max_encoded_len, max_encrypted_len); @@ -317,21 +241,19 @@ EXPORT_SYMBOL(fscrypt_fname_free_buffer); * * The caller must have allocated sufficient memory for the @oname string. * - * If the key is available, we'll decrypt the disk name. Otherwise, we'll - * encode it for presentation in fscrypt_nokey_name format. - * See struct fscrypt_nokey_name for details. + * If the key is available, we'll decrypt the disk name; otherwise, we'll encode + * it for presentation. Short names are directly base64-encoded, while long + * names are encoded in fscrypt_digested_name format. * * Return: 0 on success, -errno on failure */ -int fscrypt_fname_disk_to_usr(const struct inode *inode, - u32 hash, u32 minor_hash, - const struct fscrypt_str *iname, - struct fscrypt_str *oname) +int fscrypt_fname_disk_to_usr(struct inode *inode, + u32 hash, u32 minor_hash, + const struct fscrypt_str *iname, + struct fscrypt_str *oname) { const struct qstr qname = FSTR_TO_QSTR(iname); - struct fscrypt_nokey_name nokey_name; - u32 size; /* size of the unencoded no-key name */ - int err; + struct fscrypt_digested_name digested_name; if (fscrypt_is_dot_dotdot(&qname)) { oname->name[0] = '.'; @@ -346,37 +268,24 @@ int fscrypt_fname_disk_to_usr(const struct inode *inode, if (fscrypt_has_encryption_key(inode)) return fname_decrypt(inode, iname, oname); - /* - * Sanity check that struct fscrypt_nokey_name doesn't have padding - * between fields and that its encoded size never exceeds NAME_MAX. - */ - BUILD_BUG_ON(offsetofend(struct fscrypt_nokey_name, dirhash) != - offsetof(struct fscrypt_nokey_name, bytes)); - BUILD_BUG_ON(offsetofend(struct fscrypt_nokey_name, bytes) != - offsetof(struct fscrypt_nokey_name, sha256)); - BUILD_BUG_ON(BASE64_CHARS(FSCRYPT_NOKEY_NAME_MAX) > NAME_MAX); - + if (iname->len <= FSCRYPT_FNAME_MAX_UNDIGESTED_SIZE) { + oname->len = base64_encode(iname->name, iname->len, + oname->name); + return 0; + } if (hash) { - nokey_name.dirhash[0] = hash; - nokey_name.dirhash[1] = minor_hash; + digested_name.hash = hash; + digested_name.minor_hash = minor_hash; } else { - nokey_name.dirhash[0] = 0; - nokey_name.dirhash[1] = 0; + digested_name.hash = 0; + digested_name.minor_hash = 0; } - if (iname->len <= sizeof(nokey_name.bytes)) { - memcpy(nokey_name.bytes, iname->name, iname->len); - size = offsetof(struct fscrypt_nokey_name, bytes[iname->len]); - } else { - memcpy(nokey_name.bytes, iname->name, sizeof(nokey_name.bytes)); - /* Compute strong hash of remaining part of name. */ - err = fscrypt_do_sha256(&iname->name[sizeof(nokey_name.bytes)], - iname->len - sizeof(nokey_name.bytes), - nokey_name.sha256); - if (err) - return err; - size = FSCRYPT_NOKEY_NAME_MAX; - } - oname->len = base64_encode((const u8 *)&nokey_name, size, oname->name); + memcpy(digested_name.digest, + FSCRYPT_FNAME_DIGEST(iname->name, iname->len), + FSCRYPT_FNAME_DIGEST_SIZE); + oname->name[0] = '_'; + oname->len = 1 + base64_encode((const u8 *)&digested_name, + sizeof(digested_name), oname->name + 1); return 0; } EXPORT_SYMBOL(fscrypt_fname_disk_to_usr); @@ -397,7 +306,8 @@ EXPORT_SYMBOL(fscrypt_fname_disk_to_usr); * get the disk_name. * * Else, for keyless @lookup operations, @iname is the presented ciphertext, so - * we decode it to get the fscrypt_nokey_name. Non-@lookup operations will be + * we decode it to get either the ciphertext disk_name (for short names) or the + * fscrypt_digested_name (for long names). Non-@lookup operations will be * impossible in this case, so we fail them with ENOKEY. * * If successful, fscrypt_free_filename() must be called later to clean up. @@ -407,8 +317,8 @@ EXPORT_SYMBOL(fscrypt_fname_disk_to_usr); int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname, int lookup, struct fscrypt_name *fname) { - struct fscrypt_nokey_name *nokey_name; int ret; + int digested; memset(fname, 0, sizeof(struct fscrypt_name)); fname->usr_fname = iname; @@ -432,8 +342,8 @@ int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname, if (!fname->crypto_buf.name) return -ENOMEM; - ret = fscrypt_fname_encrypt(dir, iname, fname->crypto_buf.name, - fname->crypto_buf.len); + ret = fname_encrypt(dir, iname, fname->crypto_buf.name, + fname->crypto_buf.len); if (ret) goto errout; fname->disk_name.name = fname->crypto_buf.name; @@ -448,31 +358,40 @@ int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname, * We don't have the key and we are doing a lookup; decode the * user-supplied name */ + if (iname->name[0] == '_') { + if (iname->len != + 1 + BASE64_CHARS(sizeof(struct fscrypt_digested_name))) + return -ENOENT; + digested = 1; + } else { + if (iname->len > + BASE64_CHARS(FSCRYPT_FNAME_MAX_UNDIGESTED_SIZE)) + return -ENOENT; + digested = 0; + } - if (iname->len > BASE64_CHARS(FSCRYPT_NOKEY_NAME_MAX)) - return -ENOENT; - - fname->crypto_buf.name = kmalloc(FSCRYPT_NOKEY_NAME_MAX, GFP_KERNEL); + fname->crypto_buf.name = + kmalloc(max_t(size_t, FSCRYPT_FNAME_MAX_UNDIGESTED_SIZE, + sizeof(struct fscrypt_digested_name)), + GFP_KERNEL); if (fname->crypto_buf.name == NULL) return -ENOMEM; - ret = base64_decode(iname->name, iname->len, fname->crypto_buf.name); - if (ret < (int)offsetof(struct fscrypt_nokey_name, bytes[1]) || - (ret > offsetof(struct fscrypt_nokey_name, sha256) && - ret != FSCRYPT_NOKEY_NAME_MAX)) { + ret = base64_decode(iname->name + digested, iname->len - digested, + fname->crypto_buf.name); + if (ret < 0) { ret = -ENOENT; goto errout; } fname->crypto_buf.len = ret; - - nokey_name = (void *)fname->crypto_buf.name; - fname->hash = nokey_name->dirhash[0]; - fname->minor_hash = nokey_name->dirhash[1]; - if (ret != FSCRYPT_NOKEY_NAME_MAX) { - /* The full ciphertext filename is available. */ - fname->disk_name.name = nokey_name->bytes; - fname->disk_name.len = - ret - offsetof(struct fscrypt_nokey_name, bytes); + if (digested) { + const struct fscrypt_digested_name *n = + (const void *)fname->crypto_buf.name; + fname->hash = n->hash; + fname->minor_hash = n->minor_hash; + } else { + fname->disk_name.name = fname->crypto_buf.name; + fname->disk_name.len = fname->crypto_buf.len; } return 0; @@ -481,106 +400,3 @@ errout: return ret; } EXPORT_SYMBOL(fscrypt_setup_filename); - -/** - * fscrypt_match_name() - test whether the given name matches a directory entry - * @fname: the name being searched for - * @de_name: the name from the directory entry - * @de_name_len: the length of @de_name in bytes - * - * Normally @fname->disk_name will be set, and in that case we simply compare - * that to the name stored in the directory entry. The only exception is that - * if we don't have the key for an encrypted directory and the name we're - * looking for is very long, then we won't have the full disk_name and instead - * we'll need to match against a fscrypt_nokey_name that includes a strong hash. - * - * Return: %true if the name matches, otherwise %false. - */ -bool fscrypt_match_name(const struct fscrypt_name *fname, - const u8 *de_name, u32 de_name_len) -{ - const struct fscrypt_nokey_name *nokey_name = - (const void *)fname->crypto_buf.name; - u8 sha256[SHA256_DIGEST_SIZE]; - - if (likely(fname->disk_name.name)) { - if (de_name_len != fname->disk_name.len) - return false; - return !memcmp(de_name, fname->disk_name.name, de_name_len); - } - if (de_name_len <= sizeof(nokey_name->bytes)) - return false; - if (memcmp(de_name, nokey_name->bytes, sizeof(nokey_name->bytes))) - return false; - if (fscrypt_do_sha256(&de_name[sizeof(nokey_name->bytes)], - de_name_len - sizeof(nokey_name->bytes), sha256)) - return false; - return !memcmp(sha256, nokey_name->sha256, sizeof(sha256)); -} -EXPORT_SYMBOL_GPL(fscrypt_match_name); - -/** - * fscrypt_fname_siphash() - calculate the SipHash of a filename - * @dir: the parent directory - * @name: the filename to calculate the SipHash of - * - * Given a plaintext filename @name and a directory @dir which uses SipHash as - * its dirhash method and has had its fscrypt key set up, this function - * calculates the SipHash of that name using the directory's secret dirhash key. - * - * Return: the SipHash of @name using the hash key of @dir - */ -u64 fscrypt_fname_siphash(const struct inode *dir, const struct qstr *name) -{ - const struct fscrypt_info *ci = dir->i_crypt_info; - - WARN_ON(!ci->ci_dirhash_key_initialized); - - return siphash(name->name, name->len, &ci->ci_dirhash_key); -} -EXPORT_SYMBOL_GPL(fscrypt_fname_siphash); - -/* - * Validate dentries in encrypted directories to make sure we aren't potentially - * caching stale dentries after a key has been added. - */ -int fscrypt_d_revalidate(struct dentry *dentry, unsigned int flags) -{ - struct dentry *dir; - int err; - int valid; - - /* - * Plaintext names are always valid, since fscrypt doesn't support - * reverting to ciphertext names without evicting the directory's inode - * -- which implies eviction of the dentries in the directory. - */ - if (!(dentry->d_flags & DCACHE_ENCRYPTED_NAME)) - return 1; - - /* - * Ciphertext name; valid if the directory's key is still unavailable. - * - * Although fscrypt forbids rename() on ciphertext names, we still must - * use dget_parent() here rather than use ->d_parent directly. That's - * because a corrupted fs image may contain directory hard links, which - * the VFS handles by moving the directory's dentry tree in the dcache - * each time ->lookup() finds the directory and it already has a dentry - * elsewhere. Thus ->d_parent can be changing, and we must safely grab - * a reference to some ->d_parent to prevent it from being freed. - */ - - if (flags & LOOKUP_RCU) - return -ECHILD; - - dir = dget_parent(dentry); - err = fscrypt_get_encryption_info(d_inode(dir)); - valid = !fscrypt_has_encryption_key(d_inode(dir)); - dput(dir); - - if (err < 0) - return err; - - return valid; -} -EXPORT_SYMBOL(fscrypt_d_revalidate); diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index 0753681cb156..5d7b20fead86 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -12,7 +12,6 @@ #define _FSCRYPT_PRIVATE_H #include -#include #include #include @@ -78,26 +77,6 @@ static inline int fscrypt_context_size(const union fscrypt_context *ctx) return 0; } -/* Check whether an fscrypt_context has a recognized version number and size */ -static inline bool fscrypt_context_is_valid(const union fscrypt_context *ctx, - int ctx_size) -{ - return ctx_size >= 1 && ctx_size == fscrypt_context_size(ctx); -} - -/* Retrieve the context's nonce, assuming the context was already validated */ -static inline const u8 *fscrypt_context_nonce(const union fscrypt_context *ctx) -{ - switch (ctx->version) { - case FSCRYPT_CONTEXT_V1: - return ctx->v1.nonce; - case FSCRYPT_CONTEXT_V2: - return ctx->v2.nonce; - } - WARN_ON(1); - return NULL; -} - #undef fscrypt_policy union fscrypt_policy { u8 version; @@ -159,6 +138,12 @@ fscrypt_policy_flags(const union fscrypt_policy *policy) BUG(); } +static inline bool +fscrypt_is_direct_key_policy(const union fscrypt_policy *policy) +{ + return fscrypt_policy_flags(policy) & FSCRYPT_POLICY_FLAG_DIRECT_KEY; +} + /** * For encrypted symlinks, the ciphertext length is stored at the beginning * of the string in little-endian format. @@ -233,14 +218,6 @@ struct fscrypt_info { */ struct fscrypt_direct_key *ci_direct_key; - /* - * This inode's hash key for filenames. This is a 128-bit SipHash-2-4 - * key. This is only set for directories that use a keyed dirhash over - * the plaintext filenames -- currently just casefolded directories. - */ - siphash_key_t ci_dirhash_key; - bool ci_dirhash_key_initialized; - /* The encryption policy used by this inode */ union fscrypt_policy ci_policy; @@ -253,6 +230,24 @@ typedef enum { FS_ENCRYPT, } fscrypt_direction_t; +static inline bool fscrypt_valid_enc_modes(u32 contents_mode, + u32 filenames_mode) +{ + if (contents_mode == FSCRYPT_MODE_AES_128_CBC && + filenames_mode == FSCRYPT_MODE_AES_128_CTS) + return true; + + if (contents_mode == FSCRYPT_MODE_AES_256_XTS && + filenames_mode == FSCRYPT_MODE_AES_256_CTS) + return true; + + if (contents_mode == FSCRYPT_MODE_ADIANTUM && + filenames_mode == FSCRYPT_MODE_ADIANTUM) + return true; + + return false; +} + /* crypto.c */ extern struct kmem_cache *fscrypt_info_cachep; extern int fscrypt_initialize(unsigned int cop_flags); @@ -262,6 +257,7 @@ extern int fscrypt_crypt_block(const struct inode *inode, unsigned int len, unsigned int offs, gfp_t gfp_flags); extern struct page *fscrypt_alloc_bounce_page(gfp_t gfp_flags); +extern const struct dentry_operations fscrypt_d_ops; extern void __printf(3, 4) __cold fscrypt_msg(const struct inode *inode, const char *level, const char *fmt, ...); @@ -289,9 +285,8 @@ void fscrypt_generate_iv(union fscrypt_iv *iv, u64 lblk_num, const struct fscrypt_info *ci); /* fname.c */ -extern int fscrypt_fname_encrypt(const struct inode *inode, - const struct qstr *iname, - u8 *out, unsigned int olen); +extern int fname_encrypt(struct inode *inode, const struct qstr *iname, + u8 *out, unsigned int olen); extern bool fscrypt_fname_encrypted_size(const struct inode *inode, u32 orig_len, u32 max_len, u32 *encrypted_len_ret); @@ -313,12 +308,11 @@ extern int fscrypt_init_hkdf(struct fscrypt_hkdf *hkdf, const u8 *master_key, * output doesn't reveal another. */ #define HKDF_CONTEXT_KEY_IDENTIFIER 1 -#define HKDF_CONTEXT_PER_FILE_ENC_KEY 2 +#define HKDF_CONTEXT_PER_FILE_KEY 2 #define HKDF_CONTEXT_DIRECT_KEY 3 #define HKDF_CONTEXT_IV_INO_LBLK_64_KEY 4 -#define HKDF_CONTEXT_DIRHASH_KEY 5 -extern int fscrypt_hkdf_expand(const struct fscrypt_hkdf *hkdf, u8 context, +extern int fscrypt_hkdf_expand(struct fscrypt_hkdf *hkdf, u8 context, const u8 *info, unsigned int infolen, u8 *okm, unsigned int okmlen); @@ -326,8 +320,7 @@ extern void fscrypt_destroy_hkdf(struct fscrypt_hkdf *hkdf); /* inline_crypt.c */ #ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT -extern int fscrypt_select_encryption_impl(struct fscrypt_info *ci, - bool is_hw_wrapped_key); +extern void fscrypt_select_encryption_impl(struct fscrypt_info *ci); static inline bool fscrypt_using_inline_encryption(const struct fscrypt_info *ci) @@ -339,7 +332,6 @@ extern int fscrypt_prepare_inline_crypt_key( struct fscrypt_prepared_key *prep_key, const u8 *raw_key, unsigned int raw_key_size, - bool is_hw_wrapped, const struct fscrypt_info *ci); extern void fscrypt_destroy_inline_crypt_key( @@ -371,10 +363,8 @@ fscrypt_is_key_prepared(struct fscrypt_prepared_key *prep_key, #else /* CONFIG_FS_ENCRYPTION_INLINE_CRYPT */ -static inline int fscrypt_select_encryption_impl(struct fscrypt_info *ci, - bool is_hw_wrapped_key) +static inline void fscrypt_select_encryption_impl(struct fscrypt_info *ci) { - return 0; } static inline bool fscrypt_using_inline_encryption( @@ -386,7 +376,6 @@ static inline bool fscrypt_using_inline_encryption( static inline int fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key, const u8 *raw_key, unsigned int raw_key_size, - bool is_hw_wrapped, const struct fscrypt_info *ci) { WARN_ON(1); @@ -579,18 +568,20 @@ struct fscrypt_mode { extern struct fscrypt_mode fscrypt_modes[]; +static inline bool +fscrypt_mode_supports_direct_key(const struct fscrypt_mode *mode) +{ + return mode->ivsize >= offsetofend(union fscrypt_iv, nonce); +} + extern int fscrypt_prepare_key(struct fscrypt_prepared_key *prep_key, const u8 *raw_key, unsigned int raw_key_size, - bool is_hw_wrapped, const struct fscrypt_info *ci); extern void fscrypt_destroy_prepared_key(struct fscrypt_prepared_key *prep_key); -extern int fscrypt_set_per_file_enc_key(struct fscrypt_info *ci, - const u8 *raw_key); - -extern int fscrypt_derive_dirhash_key(struct fscrypt_info *ci, - const struct fscrypt_master_key *mk); +extern int fscrypt_set_derived_key(struct fscrypt_info *ci, + const u8 *derived_key); /* keysetup_v1.c */ diff --git a/fs/crypto/hkdf.c b/fs/crypto/hkdf.c index fd7f67628561..2c026009c6e7 100644 --- a/fs/crypto/hkdf.c +++ b/fs/crypto/hkdf.c @@ -113,7 +113,7 @@ out: * adds to its application-specific info strings to guarantee that it doesn't * accidentally repeat an info string when using HKDF for different purposes.) */ -int fscrypt_hkdf_expand(const struct fscrypt_hkdf *hkdf, u8 context, +int fscrypt_hkdf_expand(struct fscrypt_hkdf *hkdf, u8 context, const u8 *info, unsigned int infolen, u8 *okm, unsigned int okmlen) { diff --git a/fs/crypto/hooks.c b/fs/crypto/hooks.c index a6396bf721ac..30b1ca661249 100644 --- a/fs/crypto/hooks.c +++ b/fs/crypto/hooks.c @@ -4,8 +4,6 @@ * Encryption hooks for higher-level filesystem operations. */ -#include - #include "fscrypt_private.h" /** @@ -117,53 +115,12 @@ int __fscrypt_prepare_lookup(struct inode *dir, struct dentry *dentry, spin_lock(&dentry->d_lock); dentry->d_flags |= DCACHE_ENCRYPTED_NAME; spin_unlock(&dentry->d_lock); + d_set_d_op(dentry, &fscrypt_d_ops); } return err; } EXPORT_SYMBOL_GPL(__fscrypt_prepare_lookup); -/** - * fscrypt_prepare_setflags() - prepare to change flags with FS_IOC_SETFLAGS - * @inode: the inode on which flags are being changed - * @oldflags: the old flags - * @flags: the new flags - * - * The caller should be holding i_rwsem for write. - * - * Return: 0 on success; -errno if the flags change isn't allowed or if - * another error occurs. - */ -int fscrypt_prepare_setflags(struct inode *inode, - unsigned int oldflags, unsigned int flags) -{ - struct fscrypt_info *ci; - struct fscrypt_master_key *mk; - int err; - - /* - * When the CASEFOLD flag is set on an encrypted directory, we must - * derive the secret key needed for the dirhash. This is only possible - * if the directory uses a v2 encryption policy. - */ - if (IS_ENCRYPTED(inode) && (flags & ~oldflags & FS_CASEFOLD_FL)) { - err = fscrypt_require_key(inode); - if (err) - return err; - ci = inode->i_crypt_info; - if (ci->ci_policy.version != FSCRYPT_POLICY_V2) - return -EINVAL; - mk = ci->ci_master_key->payload.data[0]; - down_read(&mk->mk_secret_sem); - if (is_master_key_secret_present(&mk->mk_secret)) - err = fscrypt_derive_dirhash_key(ci, mk); - else - err = -ENOKEY; - up_read(&mk->mk_secret_sem); - return err; - } - return 0; -} - int __fscrypt_prepare_symlink(struct inode *dir, unsigned int len, unsigned int max_len, struct fscrypt_str *disk_link) @@ -230,8 +187,7 @@ int __fscrypt_encrypt_symlink(struct inode *inode, const char *target, ciphertext_len = disk_link->len - sizeof(*sd); sd->len = cpu_to_le16(ciphertext_len); - err = fscrypt_fname_encrypt(inode, &iname, sd->encrypted_path, - ciphertext_len); + err = fname_encrypt(inode, &iname, sd->encrypted_path, ciphertext_len); if (err) goto err_free_sd; diff --git a/fs/crypto/inline_crypt.c b/fs/crypto/inline_crypt.c index e1bbaeff1c43..92c471d3db73 100644 --- a/fs/crypto/inline_crypt.c +++ b/fs/crypto/inline_crypt.c @@ -26,94 +26,44 @@ struct fscrypt_blk_crypto_key { struct request_queue *devs[]; }; -static int fscrypt_get_num_devices(struct super_block *sb) -{ - if (sb->s_cop->get_num_devices) - return sb->s_cop->get_num_devices(sb); - return 1; -} - -static void fscrypt_get_devices(struct super_block *sb, int num_devs, - struct request_queue **devs) -{ - if (num_devs == 1) - devs[0] = bdev_get_queue(sb->s_bdev); - else - sb->s_cop->get_devices(sb, devs); -} - /* Enable inline encryption for this file if supported. */ -int fscrypt_select_encryption_impl(struct fscrypt_info *ci, - bool is_hw_wrapped_key) +void fscrypt_select_encryption_impl(struct fscrypt_info *ci) { const struct inode *inode = ci->ci_inode; struct super_block *sb = inode->i_sb; - enum blk_crypto_mode_num crypto_mode = ci->ci_mode->blk_crypto_mode; - struct request_queue **devs; - int num_devs; - int i; /* The file must need contents encryption, not filenames encryption */ if (!S_ISREG(inode->i_mode)) - return 0; + return; /* blk-crypto must implement the needed encryption algorithm */ - if (crypto_mode == BLK_ENCRYPTION_MODE_INVALID) - return 0; + if (ci->ci_mode->blk_crypto_mode == BLK_ENCRYPTION_MODE_INVALID) + return; /* The filesystem must be mounted with -o inlinecrypt */ if (!sb->s_cop->inline_crypt_enabled || !sb->s_cop->inline_crypt_enabled(sb)) - return 0; - - /* - * The needed encryption settings must be supported either by - * blk-crypto-fallback, or by hardware on all the filesystem's devices. - */ - - if (IS_ENABLED(CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK) && - !is_hw_wrapped_key) { - ci->ci_inlinecrypt = true; - return 0; - } - - num_devs = fscrypt_get_num_devices(sb); - devs = kmalloc_array(num_devs, sizeof(*devs), GFP_NOFS); - if (!devs) - return -ENOMEM; - - fscrypt_get_devices(sb, num_devs, devs); - - for (i = 0; i < num_devs; i++) { - if (!keyslot_manager_crypto_mode_supported(devs[i]->ksm, - crypto_mode, - sb->s_blocksize, - is_hw_wrapped_key)) - goto out_free_devs; - } + return; ci->ci_inlinecrypt = true; -out_free_devs: - kfree(devs); - return 0; } int fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key, const u8 *raw_key, unsigned int raw_key_size, - bool is_hw_wrapped, const struct fscrypt_info *ci) { const struct inode *inode = ci->ci_inode; struct super_block *sb = inode->i_sb; enum blk_crypto_mode_num crypto_mode = ci->ci_mode->blk_crypto_mode; - int num_devs; + int num_devs = 1; int queue_refs = 0; struct fscrypt_blk_crypto_key *blk_key; int err; int i; - num_devs = fscrypt_get_num_devices(sb); + if (sb->s_cop->get_num_devices) + num_devs = sb->s_cop->get_num_devices(sb); if (WARN_ON(num_devs < 1)) return -EINVAL; @@ -122,13 +72,16 @@ int fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key, return -ENOMEM; blk_key->num_devs = num_devs; - fscrypt_get_devices(sb, num_devs, blk_key->devs); + if (num_devs == 1) + blk_key->devs[0] = bdev_get_queue(sb->s_bdev); + else + sb->s_cop->get_devices(sb, blk_key->devs); BUILD_BUG_ON(FSCRYPT_MAX_HW_WRAPPED_KEY_SIZE > BLK_CRYPTO_MAX_WRAPPED_KEY_SIZE); err = blk_crypto_init_key(&blk_key->base, raw_key, raw_key_size, - is_hw_wrapped, crypto_mode, sb->s_blocksize); + crypto_mode, sb->s_blocksize); if (err) { fscrypt_err(inode, "error %d initializing blk-crypto key", err); goto fail; @@ -150,7 +103,6 @@ int fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key, queue_refs++; err = blk_crypto_start_using_mode(crypto_mode, sb->s_blocksize, - is_hw_wrapped, blk_key->devs[i]); if (err) { fscrypt_err(inode, diff --git a/fs/crypto/keyring.c b/fs/crypto/keyring.c index 0081fd48e96f..7facb5993b03 100644 --- a/fs/crypto/keyring.c +++ b/fs/crypto/keyring.c @@ -465,111 +465,6 @@ out_unlock: return err; } -static int fscrypt_provisioning_key_preparse(struct key_preparsed_payload *prep) -{ - const struct fscrypt_provisioning_key_payload *payload = prep->data; - - BUILD_BUG_ON(FSCRYPT_MAX_HW_WRAPPED_KEY_SIZE < FSCRYPT_MAX_KEY_SIZE); - - if (prep->datalen < sizeof(*payload) + FSCRYPT_MIN_KEY_SIZE || - prep->datalen > sizeof(*payload) + FSCRYPT_MAX_HW_WRAPPED_KEY_SIZE) - return -EINVAL; - - if (payload->type != FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR && - payload->type != FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER) - return -EINVAL; - - if (payload->__reserved) - return -EINVAL; - - prep->payload.data[0] = kmemdup(payload, prep->datalen, GFP_KERNEL); - if (!prep->payload.data[0]) - return -ENOMEM; - - prep->quotalen = prep->datalen; - return 0; -} - -static void fscrypt_provisioning_key_free_preparse( - struct key_preparsed_payload *prep) -{ - kzfree(prep->payload.data[0]); -} - -static void fscrypt_provisioning_key_describe(const struct key *key, - struct seq_file *m) -{ - seq_puts(m, key->description); - if (key_is_positive(key)) { - const struct fscrypt_provisioning_key_payload *payload = - key->payload.data[0]; - - seq_printf(m, ": %u [%u]", key->datalen, payload->type); - } -} - -static void fscrypt_provisioning_key_destroy(struct key *key) -{ - kzfree(key->payload.data[0]); -} - -static struct key_type key_type_fscrypt_provisioning = { - .name = "fscrypt-provisioning", - .preparse = fscrypt_provisioning_key_preparse, - .free_preparse = fscrypt_provisioning_key_free_preparse, - .instantiate = generic_key_instantiate, - .describe = fscrypt_provisioning_key_describe, - .destroy = fscrypt_provisioning_key_destroy, -}; - -/* - * Retrieve the raw key from the Linux keyring key specified by 'key_id', and - * store it into 'secret'. - * - * The key must be of type "fscrypt-provisioning" and must have the field - * fscrypt_provisioning_key_payload::type set to 'type', indicating that it's - * only usable with fscrypt with the particular KDF version identified by - * 'type'. We don't use the "logon" key type because there's no way to - * completely restrict the use of such keys; they can be used by any kernel API - * that accepts "logon" keys and doesn't require a specific service prefix. - * - * The ability to specify the key via Linux keyring key is intended for cases - * where userspace needs to re-add keys after the filesystem is unmounted and - * re-mounted. Most users should just provide the raw key directly instead. - */ -static int get_keyring_key(u32 key_id, u32 type, - struct fscrypt_master_key_secret *secret) -{ - key_ref_t ref; - struct key *key; - const struct fscrypt_provisioning_key_payload *payload; - int err; - - ref = lookup_user_key(key_id, 0, KEY_NEED_SEARCH); - if (IS_ERR(ref)) - return PTR_ERR(ref); - key = key_ref_to_ptr(ref); - - if (key->type != &key_type_fscrypt_provisioning) - goto bad_key; - payload = key->payload.data[0]; - - /* Don't allow fscrypt v1 keys to be used as v2 keys and vice versa. */ - if (payload->type != type) - goto bad_key; - - secret->size = key->datalen - sizeof(*payload); - memcpy(secret->raw, payload->raw, secret->size); - err = 0; - goto out_put; - -bad_key: - err = -EKEYREJECTED; -out_put: - key_ref_put(ref); - return err; -} - /* Size of software "secret" derived from hardware-wrapped key */ #define RAW_SECRET_SIZE 32 @@ -617,28 +512,20 @@ int fscrypt_ioctl_add_key(struct file *filp, void __user *_uarg) if (memchr_inv(arg.__reserved, 0, sizeof(arg.__reserved))) return -EINVAL; + BUILD_BUG_ON(FSCRYPT_MAX_HW_WRAPPED_KEY_SIZE < + FSCRYPT_MAX_KEY_SIZE); + + if (arg.raw_size < FSCRYPT_MIN_KEY_SIZE || + arg.raw_size > + ((arg.__flags & __FSCRYPT_ADD_KEY_FLAG_HW_WRAPPED) ? + FSCRYPT_MAX_HW_WRAPPED_KEY_SIZE : FSCRYPT_MAX_KEY_SIZE)) + return -EINVAL; + memset(&secret, 0, sizeof(secret)); - if (arg.key_id) { - if (arg.raw_size != 0) - return -EINVAL; - err = get_keyring_key(arg.key_id, arg.key_spec.type, &secret); - if (err) - goto out_wipe_secret; - err = -EINVAL; - if (!(arg.__flags & __FSCRYPT_ADD_KEY_FLAG_HW_WRAPPED) && - secret.size > FSCRYPT_MAX_KEY_SIZE) - goto out_wipe_secret; - } else { - if (arg.raw_size < FSCRYPT_MIN_KEY_SIZE || - arg.raw_size > - ((arg.__flags & __FSCRYPT_ADD_KEY_FLAG_HW_WRAPPED) ? - FSCRYPT_MAX_HW_WRAPPED_KEY_SIZE : FSCRYPT_MAX_KEY_SIZE)) - return -EINVAL; - secret.size = arg.raw_size; - err = -EFAULT; - if (copy_from_user(secret.raw, uarg->raw, secret.size)) - goto out_wipe_secret; - } + secret.size = arg.raw_size; + err = -EFAULT; + if (copy_from_user(secret.raw, uarg->raw, secret.size)) + goto out_wipe_secret; switch (arg.key_spec.type) { case FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR: @@ -809,6 +696,9 @@ static int check_for_busy_inodes(struct super_block *sb, struct list_head *pos; size_t busy_count = 0; unsigned long ino; + struct dentry *dentry; + char _path[256]; + char *path = NULL; spin_lock(&mk->mk_decrypted_inodes_lock); @@ -827,14 +717,22 @@ static int check_for_busy_inodes(struct super_block *sb, struct fscrypt_info, ci_master_key_link)->ci_inode; ino = inode->i_ino; + dentry = d_find_alias(inode); } spin_unlock(&mk->mk_decrypted_inodes_lock); + if (dentry) { + path = dentry_path(dentry, _path, sizeof(_path)); + dput(dentry); + } + if (IS_ERR_OR_NULL(path)) + path = "(unknown)"; + fscrypt_warn(NULL, - "%s: %zu inode(s) still busy after removing key with %s %*phN, including ino %lu", + "%s: %zu inode(s) still busy after removing key with %s %*phN, including ino %lu (%s)", sb->s_id, busy_count, master_key_spec_type(&mk->mk_spec), master_key_spec_len(&mk->mk_spec), (u8 *)&mk->mk_spec.u, - ino); + ino, path); return -EBUSY; } @@ -1132,14 +1030,8 @@ int __init fscrypt_init_keyring(void) if (err) goto err_unregister_fscrypt; - err = register_key_type(&key_type_fscrypt_provisioning); - if (err) - goto err_unregister_fscrypt_user; - return 0; -err_unregister_fscrypt_user: - unregister_key_type(&key_type_fscrypt_user); err_unregister_fscrypt: unregister_key_type(&key_type_fscrypt); return err; diff --git a/fs/crypto/keysetup.c b/fs/crypto/keysetup.c index 6b98ca38fc44..f87daf215ac9 100644 --- a/fs/crypto/keysetup.c +++ b/fs/crypto/keysetup.c @@ -92,11 +92,8 @@ fscrypt_allocate_skcipher(struct fscrypt_mode *mode, const u8 *raw_key, * first time a mode is used. */ pr_info("fscrypt: %s using implementation \"%s\"\n", - mode->friendly_name, crypto_skcipher_driver_name(tfm)); - } - if (WARN_ON(crypto_skcipher_ivsize(tfm) != mode->ivsize)) { - err = -EINVAL; - goto err_free_tfm; + mode->friendly_name, + crypto_skcipher_alg(tfm)->base.cra_driver_name); } crypto_skcipher_set_flags(tfm, CRYPTO_TFM_REQ_WEAK_KEY); err = crypto_skcipher_setkey(tfm, raw_key, mode->keysize); @@ -117,15 +114,15 @@ err_free_tfm: */ int fscrypt_prepare_key(struct fscrypt_prepared_key *prep_key, const u8 *raw_key, unsigned int raw_key_size, - bool is_hw_wrapped, const struct fscrypt_info *ci) + const struct fscrypt_info *ci) { struct crypto_skcipher *tfm; if (fscrypt_using_inline_encryption(ci)) return fscrypt_prepare_inline_crypt_key(prep_key, - raw_key, raw_key_size, is_hw_wrapped, ci); + raw_key, raw_key_size, ci); - if (WARN_ON(is_hw_wrapped || raw_key_size != ci->ci_mode->keysize)) + if (WARN_ON(raw_key_size != ci->ci_mode->keysize)) return -EINVAL; tfm = fscrypt_allocate_skcipher(ci->ci_mode, raw_key, ci->ci_inode); @@ -146,18 +143,18 @@ void fscrypt_destroy_prepared_key(struct fscrypt_prepared_key *prep_key) fscrypt_destroy_inline_crypt_key(prep_key); } -/* Given a per-file encryption key, set up the file's crypto transform object */ -int fscrypt_set_per_file_enc_key(struct fscrypt_info *ci, const u8 *raw_key) +/* Given the per-file key, set up the file's crypto transform object */ +int fscrypt_set_derived_key(struct fscrypt_info *ci, const u8 *derived_key) { ci->ci_owns_key = true; - return fscrypt_prepare_key(&ci->ci_key, raw_key, ci->ci_mode->keysize, - false /*is_hw_wrapped*/, ci); + return fscrypt_prepare_key(&ci->ci_key, derived_key, + ci->ci_mode->keysize, ci); } -static int setup_per_mode_enc_key(struct fscrypt_info *ci, - struct fscrypt_master_key *mk, - struct fscrypt_prepared_key *keys, - u8 hkdf_context, bool include_fs_uuid) +static int setup_per_mode_key(struct fscrypt_info *ci, + struct fscrypt_master_key *mk, + struct fscrypt_prepared_key *keys, + u8 hkdf_context, bool include_fs_uuid) { static DEFINE_MUTEX(mode_key_setup_mutex); const struct inode *inode = ci->ci_inode; @@ -202,7 +199,7 @@ static int setup_per_mode_enc_key(struct fscrypt_info *ci, } } err = fscrypt_prepare_key(prep_key, mk->mk_secret.raw, - mk->mk_secret.size, true, ci); + mk->mk_secret.size, ci); if (err) goto out_unlock; } else { @@ -221,7 +218,7 @@ static int setup_per_mode_enc_key(struct fscrypt_info *ci, if (err) goto out_unlock; err = fscrypt_prepare_key(prep_key, mode_key, mode->keysize, - false /*is_hw_wrapped*/, ci); + ci); memzero_explicit(mode_key, mode->keysize); if (err) goto out_unlock; @@ -234,24 +231,10 @@ out_unlock: return err; } -int fscrypt_derive_dirhash_key(struct fscrypt_info *ci, - const struct fscrypt_master_key *mk) -{ - int err; - - err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf, HKDF_CONTEXT_DIRHASH_KEY, - ci->ci_nonce, FS_KEY_DERIVATION_NONCE_SIZE, - (u8 *)&ci->ci_dirhash_key, - sizeof(ci->ci_dirhash_key)); - if (err) - return err; - ci->ci_dirhash_key_initialized = true; - return 0; -} - static int fscrypt_setup_v2_file_key(struct fscrypt_info *ci, struct fscrypt_master_key *mk) { + u8 derived_key[FSCRYPT_MAX_KEY_SIZE]; int err; if (mk->mk_secret.is_hw_wrapped && @@ -263,15 +246,21 @@ static int fscrypt_setup_v2_file_key(struct fscrypt_info *ci, if (ci->ci_policy.v2.flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) { /* - * DIRECT_KEY: instead of deriving per-file encryption keys, the - * per-file nonce will be included in all the IVs. But unlike - * v1 policies, for v2 policies in this case we don't encrypt - * with the master key directly but rather derive a per-mode - * encryption key. This ensures that the master key is - * consistently used only for HKDF, avoiding key reuse issues. + * DIRECT_KEY: instead of deriving per-file keys, the per-file + * nonce will be included in all the IVs. But unlike v1 + * policies, for v2 policies in this case we don't encrypt with + * the master key directly but rather derive a per-mode key. + * This ensures that the master key is consistently used only + * for HKDF, avoiding key reuse issues. */ - err = setup_per_mode_enc_key(ci, mk, mk->mk_direct_keys, - HKDF_CONTEXT_DIRECT_KEY, false); + if (!fscrypt_mode_supports_direct_key(ci->ci_mode)) { + fscrypt_warn(ci->ci_inode, + "Direct key flag not allowed with %s", + ci->ci_mode->friendly_name); + return -EINVAL; + } + return setup_per_mode_key(ci, mk, mk->mk_direct_keys, + HKDF_CONTEXT_DIRECT_KEY, false); } else if (ci->ci_policy.v2.flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64) { /* @@ -280,34 +269,21 @@ static int fscrypt_setup_v2_file_key(struct fscrypt_info *ci, * the IVs. This format is optimized for use with inline * encryption hardware compliant with the UFS or eMMC standards. */ - err = setup_per_mode_enc_key(ci, mk, mk->mk_iv_ino_lblk_64_keys, - HKDF_CONTEXT_IV_INO_LBLK_64_KEY, - true); - } else { - u8 derived_key[FSCRYPT_MAX_KEY_SIZE]; - - err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf, - HKDF_CONTEXT_PER_FILE_ENC_KEY, - ci->ci_nonce, - FS_KEY_DERIVATION_NONCE_SIZE, - derived_key, ci->ci_mode->keysize); - if (err) - return err; - - err = fscrypt_set_per_file_enc_key(ci, derived_key); - memzero_explicit(derived_key, ci->ci_mode->keysize); + return setup_per_mode_key(ci, mk, mk->mk_iv_ino_lblk_64_keys, + HKDF_CONTEXT_IV_INO_LBLK_64_KEY, + true); } + + err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf, + HKDF_CONTEXT_PER_FILE_KEY, + ci->ci_nonce, FS_KEY_DERIVATION_NONCE_SIZE, + derived_key, ci->ci_mode->keysize); if (err) return err; - /* Derive a secret dirhash key for directories that need it. */ - if (S_ISDIR(ci->ci_inode->i_mode) && IS_CASEFOLDED(ci->ci_inode)) { - err = fscrypt_derive_dirhash_key(ci, mk); - if (err) - return err; - } - - return 0; + err = fscrypt_set_derived_key(ci, derived_key); + memzero_explicit(derived_key, ci->ci_mode->keysize); + return err; } /* @@ -328,6 +304,8 @@ static int setup_file_encryption_key(struct fscrypt_info *ci, struct fscrypt_key_specifier mk_spec; int err; + fscrypt_select_encryption_impl(ci); + switch (ci->ci_policy.version) { case FSCRYPT_POLICY_V1: mk_spec.type = FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR; @@ -352,10 +330,6 @@ static int setup_file_encryption_key(struct fscrypt_info *ci, ci->ci_policy.version != FSCRYPT_POLICY_V1) return PTR_ERR(key); - err = fscrypt_select_encryption_impl(ci, false); - if (err) - return err; - /* * As a legacy fallback for v1 policies, search for the key in * the current task's subscribed keyrings too. Don't move this @@ -390,10 +364,6 @@ static int setup_file_encryption_key(struct fscrypt_info *ci, goto out_release_key; } - err = fscrypt_select_encryption_impl(ci, mk->mk_secret.is_hw_wrapped); - if (err) - goto out_release_key; - switch (ci->ci_policy.version) { case FSCRYPT_POLICY_V1: err = fscrypt_setup_v1_file_key(ci, mk->mk_secret.raw); @@ -500,8 +470,20 @@ int fscrypt_get_encryption_info(struct inode *inode) goto out; } - memcpy(crypt_info->ci_nonce, fscrypt_context_nonce(&ctx), - FS_KEY_DERIVATION_NONCE_SIZE); + switch (ctx.version) { + case FSCRYPT_CONTEXT_V1: + memcpy(crypt_info->ci_nonce, ctx.v1.nonce, + FS_KEY_DERIVATION_NONCE_SIZE); + break; + case FSCRYPT_CONTEXT_V2: + memcpy(crypt_info->ci_nonce, ctx.v2.nonce, + FS_KEY_DERIVATION_NONCE_SIZE); + break; + default: + WARN_ON(1); + res = -EINVAL; + goto out; + } if (!fscrypt_supported_policy(&crypt_info->ci_policy, inode)) { res = -EINVAL; @@ -601,15 +583,6 @@ int fscrypt_drop_inode(struct inode *inode) return 0; mk = ci->ci_master_key->payload.data[0]; - /* - * With proper, non-racy use of FS_IOC_REMOVE_ENCRYPTION_KEY, all inodes - * protected by the key were cleaned by sync_filesystem(). But if - * userspace is still using the files, inodes can be dirtied between - * then and now. We mustn't lose any writes, so skip dirty inodes here. - */ - if (inode->i_state & I_DIRTY_ALL) - return 0; - /* * Note: since we aren't holding ->mk_secret_sem, the result here can * immediately become outdated. But there's no correctness problem with diff --git a/fs/crypto/keysetup_v1.c b/fs/crypto/keysetup_v1.c index 3f7bb48f7317..47591c54dc3d 100644 --- a/fs/crypto/keysetup_v1.c +++ b/fs/crypto/keysetup_v1.c @@ -9,7 +9,7 @@ * This file implements compatibility functions for the original encryption * policy version ("v1"), including: * - * - Deriving per-file encryption keys using the AES-128-ECB based KDF + * - Deriving per-file keys using the AES-128-ECB based KDF * (rather than the new method of using HKDF-SHA512) * * - Retrieving fscrypt master keys from process-subscribed keyrings @@ -234,7 +234,7 @@ fscrypt_get_direct_key(const struct fscrypt_info *ci, const u8 *raw_key) refcount_set(&dk->dk_refcount, 1); dk->dk_mode = ci->ci_mode; err = fscrypt_prepare_key(&dk->dk_key, raw_key, ci->ci_mode->keysize, - false /*is_hw_wrapped*/, ci); + ci); if (err) goto err_free_dk; memcpy(dk->dk_descriptor, ci->ci_policy.v1.master_key_descriptor, @@ -252,8 +252,23 @@ err_free_dk: static int setup_v1_file_key_direct(struct fscrypt_info *ci, const u8 *raw_master_key) { + const struct fscrypt_mode *mode = ci->ci_mode; struct fscrypt_direct_key *dk; + if (!fscrypt_mode_supports_direct_key(mode)) { + fscrypt_warn(ci->ci_inode, + "Direct key mode not allowed with %s", + mode->friendly_name); + return -EINVAL; + } + + if (ci->ci_policy.v1.contents_encryption_mode != + ci->ci_policy.v1.filenames_encryption_mode) { + fscrypt_warn(ci->ci_inode, + "Direct key mode not allowed with different contents and filenames modes"); + return -EINVAL; + } + dk = fscrypt_get_direct_key(ci, raw_master_key); if (IS_ERR(dk)) return PTR_ERR(dk); @@ -282,7 +297,7 @@ static int setup_v1_file_key_derived(struct fscrypt_info *ci, if (err) goto out; - err = fscrypt_set_per_file_enc_key(ci, derived_key); + err = fscrypt_set_derived_key(ci, derived_key); out: kzfree(derived_key); return err; diff --git a/fs/crypto/policy.c b/fs/crypto/policy.c index 10ccf945020c..96f528071bed 100644 --- a/fs/crypto/policy.c +++ b/fs/crypto/policy.c @@ -29,43 +29,6 @@ bool fscrypt_policies_equal(const union fscrypt_policy *policy1, return !memcmp(policy1, policy2, fscrypt_policy_size(policy1)); } -static bool fscrypt_valid_enc_modes(u32 contents_mode, u32 filenames_mode) -{ - if (contents_mode == FSCRYPT_MODE_AES_256_XTS && - filenames_mode == FSCRYPT_MODE_AES_256_CTS) - return true; - - if (contents_mode == FSCRYPT_MODE_AES_128_CBC && - filenames_mode == FSCRYPT_MODE_AES_128_CTS) - return true; - - if (contents_mode == FSCRYPT_MODE_ADIANTUM && - filenames_mode == FSCRYPT_MODE_ADIANTUM) - return true; - - return false; -} - -static bool supported_direct_key_modes(const struct inode *inode, - u32 contents_mode, u32 filenames_mode) -{ - const struct fscrypt_mode *mode; - - if (contents_mode != filenames_mode) { - fscrypt_warn(inode, - "Direct key flag not allowed with different contents and filenames modes"); - return false; - } - mode = &fscrypt_modes[contents_mode]; - - if (mode->ivsize < offsetofend(union fscrypt_iv, nonce)) { - fscrypt_warn(inode, "Direct key flag not allowed with %s", - mode->friendly_name); - return false; - } - return true; -} - static bool supported_iv_ino_lblk_64_policy( const struct fscrypt_policy_v2 *policy, const struct inode *inode) @@ -100,82 +63,13 @@ static bool supported_iv_ino_lblk_64_policy( return true; } -static bool fscrypt_supported_v1_policy(const struct fscrypt_policy_v1 *policy, - const struct inode *inode) -{ - if (!fscrypt_valid_enc_modes(policy->contents_encryption_mode, - policy->filenames_encryption_mode)) { - fscrypt_warn(inode, - "Unsupported encryption modes (contents %d, filenames %d)", - policy->contents_encryption_mode, - policy->filenames_encryption_mode); - return false; - } - - if (policy->flags & ~(FSCRYPT_POLICY_FLAGS_PAD_MASK | - FSCRYPT_POLICY_FLAG_DIRECT_KEY)) { - fscrypt_warn(inode, "Unsupported encryption flags (0x%02x)", - policy->flags); - return false; - } - - if ((policy->flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) && - !supported_direct_key_modes(inode, policy->contents_encryption_mode, - policy->filenames_encryption_mode)) - return false; - - if (IS_CASEFOLDED(inode)) { - /* With v1, there's no way to derive dirhash keys. */ - fscrypt_warn(inode, - "v1 policies can't be used on casefolded directories"); - return false; - } - - return true; -} - -static bool fscrypt_supported_v2_policy(const struct fscrypt_policy_v2 *policy, - const struct inode *inode) -{ - if (!fscrypt_valid_enc_modes(policy->contents_encryption_mode, - policy->filenames_encryption_mode)) { - fscrypt_warn(inode, - "Unsupported encryption modes (contents %d, filenames %d)", - policy->contents_encryption_mode, - policy->filenames_encryption_mode); - return false; - } - - if (policy->flags & ~FSCRYPT_POLICY_FLAGS_VALID) { - fscrypt_warn(inode, "Unsupported encryption flags (0x%02x)", - policy->flags); - return false; - } - - if ((policy->flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) && - !supported_direct_key_modes(inode, policy->contents_encryption_mode, - policy->filenames_encryption_mode)) - return false; - - if ((policy->flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64) && - !supported_iv_ino_lblk_64_policy(policy, inode)) - return false; - - if (memchr_inv(policy->__reserved, 0, sizeof(policy->__reserved))) { - fscrypt_warn(inode, "Reserved bits set in encryption policy"); - return false; - } - - return true; -} - /** * fscrypt_supported_policy - check whether an encryption policy is supported * * Given an encryption policy, check whether all its encryption modes and other - * settings are supported by this kernel on the given inode. (But we don't - * currently don't check for crypto API support here, so attempting to use an - * algorithm not configured into the crypto API will still fail later.) + * settings are supported by this kernel. (But we don't currently don't check + * for crypto API support here, so attempting to use an algorithm not configured + * into the crypto API will still fail later.) * * Return: %true if supported, else %false */ @@ -183,10 +77,60 @@ bool fscrypt_supported_policy(const union fscrypt_policy *policy_u, const struct inode *inode) { switch (policy_u->version) { - case FSCRYPT_POLICY_V1: - return fscrypt_supported_v1_policy(&policy_u->v1, inode); - case FSCRYPT_POLICY_V2: - return fscrypt_supported_v2_policy(&policy_u->v2, inode); + case FSCRYPT_POLICY_V1: { + const struct fscrypt_policy_v1 *policy = &policy_u->v1; + + if (!fscrypt_valid_enc_modes(policy->contents_encryption_mode, + policy->filenames_encryption_mode)) { + fscrypt_warn(inode, + "Unsupported encryption modes (contents %d, filenames %d)", + policy->contents_encryption_mode, + policy->filenames_encryption_mode); + return false; + } + + if (policy->flags & ~(FSCRYPT_POLICY_FLAGS_PAD_MASK | + FSCRYPT_POLICY_FLAG_DIRECT_KEY)) { + fscrypt_warn(inode, + "Unsupported encryption flags (0x%02x)", + policy->flags); + return false; + } + + return true; + } + case FSCRYPT_POLICY_V2: { + const struct fscrypt_policy_v2 *policy = &policy_u->v2; + + if (!fscrypt_valid_enc_modes(policy->contents_encryption_mode, + policy->filenames_encryption_mode)) { + fscrypt_warn(inode, + "Unsupported encryption modes (contents %d, filenames %d)", + policy->contents_encryption_mode, + policy->filenames_encryption_mode); + return false; + } + + if (policy->flags & ~FSCRYPT_POLICY_FLAGS_VALID) { + fscrypt_warn(inode, + "Unsupported encryption flags (0x%02x)", + policy->flags); + return false; + } + + if ((policy->flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64) && + !supported_iv_ino_lblk_64_policy(policy, inode)) + return false; + + if (memchr_inv(policy->__reserved, 0, + sizeof(policy->__reserved))) { + fscrypt_warn(inode, + "Reserved bits set in encryption policy"); + return false; + } + + return true; + } } return false; } @@ -258,7 +202,7 @@ int fscrypt_policy_from_context(union fscrypt_policy *policy_u, { memset(policy_u, 0, sizeof(*policy_u)); - if (!fscrypt_context_is_valid(ctx_u, ctx_size)) + if (ctx_size <= 0 || ctx_size != fscrypt_context_size(ctx_u)) return -EINVAL; switch (ctx_u->version) { @@ -481,25 +425,6 @@ int fscrypt_ioctl_get_policy_ex(struct file *filp, void __user *uarg) } EXPORT_SYMBOL_GPL(fscrypt_ioctl_get_policy_ex); -/* FS_IOC_GET_ENCRYPTION_NONCE: retrieve file's encryption nonce for testing */ -int fscrypt_ioctl_get_nonce(struct file *filp, void __user *arg) -{ - struct inode *inode = file_inode(filp); - union fscrypt_context ctx; - int ret; - - ret = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx)); - if (ret < 0) - return ret; - if (!fscrypt_context_is_valid(&ctx, ret)) - return -EINVAL; - if (copy_to_user(arg, fscrypt_context_nonce(&ctx), - FS_KEY_DERIVATION_NONCE_SIZE)) - return -EFAULT; - return 0; -} -EXPORT_SYMBOL_GPL(fscrypt_ioctl_get_nonce); - /** * fscrypt_has_permitted_context() - is a file's encryption policy permitted * within its directory? diff --git a/fs/ext4/Kconfig b/fs/ext4/Kconfig index 39cd2c054339..e2cfd33fd759 100644 --- a/fs/ext4/Kconfig +++ b/fs/ext4/Kconfig @@ -37,7 +37,6 @@ config EXT4_FS select CRC16 select CRYPTO select CRYPTO_CRC32C - select FS_ENCRYPTION_ALGS if FS_ENCRYPTION help This is the next generation of the ext3 filesystem. diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c index ee766e3bed8b..e4d13c6ac931 100644 --- a/fs/ext4/dir.c +++ b/fs/ext4/dir.c @@ -117,7 +117,7 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx) if (IS_ENCRYPTED(inode)) { err = fscrypt_get_encryption_info(inode); - if (err) + if (err && err != -ENOKEY) return err; } @@ -664,3 +664,10 @@ const struct file_operations ext4_dir_operations = { .open = ext4_dir_open, .release = ext4_release_dir, }; + +#ifdef CONFIG_UNICODE +const struct dentry_operations ext4_dentry_ops = { + .d_hash = generic_ci_d_hash, + .d_compare = generic_ci_d_compare, +}; +#endif diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index 3e5ca2107998..e7c7a6737a46 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c @@ -1100,11 +1100,6 @@ resizefs_out: return -EOPNOTSUPP; return fscrypt_ioctl_get_key_status(filp, (void __user *)arg); - case FS_IOC_GET_ENCRYPTION_NONCE: - if (!ext4_has_feature_encrypt(sb)) - return -EOPNOTSUPP; - return fscrypt_ioctl_get_nonce(filp, (void __user *)arg); - case EXT4_IOC_FSGETXATTR: { struct fsxattr fa; @@ -1248,7 +1243,6 @@ long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case FS_IOC_REMOVE_ENCRYPTION_KEY: case FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS: case FS_IOC_GET_ENCRYPTION_KEY_STATUS: - case FS_IOC_GET_ENCRYPTION_NONCE: case EXT4_IOC_SHUTDOWN: case FS_IOC_GETFSMAP: case FS_IOC_ENABLE_VERITY: diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index b134add5a5ad..0e6a7cb9e9cf 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -1608,7 +1608,6 @@ static struct buffer_head *ext4_lookup_entry(struct inode *dir, struct buffer_head *bh; err = ext4_fname_prepare_lookup(dir, dentry, &fname); - generic_set_encrypted_ci_d_ops(dir, dentry); if (err == -ENOENT) return NULL; if (err) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 782d4a26aace..34fbd95d9b3d 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -4490,6 +4490,11 @@ no_journal: goto failed_mount4; } +#ifdef CONFIG_UNICODE + if (sb->s_encoding) + sb->s_d_op = &ext4_dentry_ops; +#endif + sb->s_root = d_make_root(root); if (!sb->s_root) { ext4_msg(sb, KERN_ERR, "get root dentry failed"); diff --git a/fs/f2fs/Kconfig b/fs/f2fs/Kconfig index 1940a6574b66..675af7cd29d3 100644 --- a/fs/f2fs/Kconfig +++ b/fs/f2fs/Kconfig @@ -5,7 +5,6 @@ config F2FS_FS select CRYPTO select CRYPTO_CRC32 select F2FS_FS_XATTR if FS_ENCRYPTION - select FS_ENCRYPTION_ALGS if FS_ENCRYPTION help F2FS is based on Log-structured File System (LFS), which supports versatile "flash-friendly" features. The design has been focused on diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c index 7fd0b08d7518..0898fff69259 100644 --- a/fs/f2fs/dir.c +++ b/fs/f2fs/dir.c @@ -108,52 +108,34 @@ static struct f2fs_dir_entry *find_in_block(struct inode *dir, * Test whether a case-insensitive directory entry matches the filename * being searched for. * - * Only called for encrypted names if the key is available. - * * Returns: 0 if the directory entry matches, more than 0 if it * doesn't match or less than zero on error. */ -static int f2fs_ci_compare(const struct inode *parent, const struct qstr *name, - u8 *de_name, size_t de_name_len, bool quick) +int f2fs_ci_compare(const struct inode *parent, const struct qstr *name, + const struct qstr *entry, bool quick) { const struct super_block *sb = parent->i_sb; const struct unicode_map *um = sb->s_encoding; - struct fscrypt_str decrypted_name = FSTR_INIT(NULL, de_name_len); - struct qstr entry = QSTR_INIT(de_name, de_name_len); int ret; - if (IS_ENCRYPTED(parent)) { - const struct fscrypt_str encrypted_name = - FSTR_INIT(de_name, de_name_len); - - decrypted_name.name = kmalloc(de_name_len, GFP_KERNEL); - if (!decrypted_name.name) - return -ENOMEM; - ret = fscrypt_fname_disk_to_usr(parent, 0, 0, &encrypted_name, - &decrypted_name); - if (ret < 0) - goto out; - entry.name = decrypted_name.name; - entry.len = decrypted_name.len; - } - if (quick) - ret = utf8_strncasecmp_folded(um, name, &entry); + ret = utf8_strncasecmp_folded(um, name, entry); else - ret = utf8_strncasecmp(um, name, &entry); + ret = utf8_strncasecmp(um, name, entry); + if (ret < 0) { /* Handle invalid character sequence as either an error * or as an opaque byte sequence. */ if (sb_has_enc_strict_mode(sb)) - ret = -EINVAL; - else if (name->len != entry.len) - ret = 1; - else - ret = !!memcmp(name->name, entry.name, entry.len); + return -EINVAL; + + if (name->len != entry->len) + return 1; + + return !!memcmp(name->name, entry->name, name->len); } -out: - kfree(decrypted_name.name); + return ret; } @@ -191,24 +173,24 @@ static inline bool f2fs_match_name(struct f2fs_dentry_ptr *d, { #ifdef CONFIG_UNICODE struct inode *parent = d->inode; - u8 *name; - int len; + struct super_block *sb = parent->i_sb; + struct qstr entry; #endif if (de->hash_code != namehash) return false; #ifdef CONFIG_UNICODE - name = d->filename[bit_pos]; - len = le16_to_cpu(de->name_len); + entry.name = d->filename[bit_pos]; + entry.len = de->name_len; - if (needs_casefold(parent)) { + if (sb->s_encoding && IS_CASEFOLDED(parent)) { if (cf_str->name) { struct qstr cf = {.name = cf_str->name, .len = cf_str->len}; - return !f2fs_ci_compare(parent, &cf, name, len, true); + return !f2fs_ci_compare(parent, &cf, &entry, true); } - return !f2fs_ci_compare(parent, fname->usr_fname, name, len, + return !f2fs_ci_compare(parent, fname->usr_fname, &entry, false); } #endif @@ -632,13 +614,13 @@ void f2fs_update_dentry(nid_t ino, umode_t mode, struct f2fs_dentry_ptr *d, int f2fs_add_regular_entry(struct inode *dir, const struct qstr *new_name, const struct qstr *orig_name, - f2fs_hash_t dentry_hash, struct inode *inode, nid_t ino, umode_t mode) { unsigned int bit_pos; unsigned int level; unsigned int current_depth; unsigned long bidx, block; + f2fs_hash_t dentry_hash; unsigned int nbucket, nblock; struct page *dentry_page = NULL; struct f2fs_dentry_block *dentry_blk = NULL; @@ -648,6 +630,7 @@ int f2fs_add_regular_entry(struct inode *dir, const struct qstr *new_name, level = 0; slots = GET_DENTRY_SLOTS(new_name->len); + dentry_hash = f2fs_dentry_hash(dir, new_name, NULL); current_depth = F2FS_I(dir)->i_current_depth; if (F2FS_I(dir)->chash == dentry_hash) { @@ -733,19 +716,17 @@ int f2fs_add_dentry(struct inode *dir, struct fscrypt_name *fname, struct inode *inode, nid_t ino, umode_t mode) { struct qstr new_name; - f2fs_hash_t dentry_hash; int err = -EAGAIN; new_name.name = fname_name(fname); new_name.len = fname_len(fname); if (f2fs_has_inline_dentry(dir)) - err = f2fs_add_inline_entry(dir, &new_name, fname, + err = f2fs_add_inline_entry(dir, &new_name, fname->usr_fname, inode, ino, mode); - dentry_hash = f2fs_dentry_hash(dir, &new_name, fname); if (err == -EAGAIN) err = f2fs_add_regular_entry(dir, &new_name, fname->usr_fname, - dentry_hash, inode, ino, mode); + inode, ino, mode); f2fs_update_time(F2FS_I_SB(dir), REQ_TIME); return err; @@ -1018,7 +999,7 @@ static int f2fs_readdir(struct file *file, struct dir_context *ctx) if (IS_ENCRYPTED(inode)) { err = fscrypt_get_encryption_info(inode); - if (err) + if (err && err != -ENOKEY) goto out; err = fscrypt_fname_alloc_buffer(inode, F2FS_NAME_LEN, &fstr); @@ -1094,3 +1075,10 @@ const struct file_operations f2fs_dir_operations = { .compat_ioctl = f2fs_compat_ioctl, #endif }; + +#ifdef CONFIG_UNICODE +const struct dentry_operations f2fs_dentry_ops = { + .d_hash = generic_ci_d_hash, + .d_compare = generic_ci_d_compare, +}; +#endif diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index e3304b6ba778..dd4a2cd5762e 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -3137,6 +3137,11 @@ int f2fs_update_extension_list(struct f2fs_sb_info *sbi, const char *name, bool hot, bool set); struct dentry *f2fs_get_parent(struct dentry *child); +extern int f2fs_ci_compare(const struct inode *parent, + const struct qstr *name, + const struct qstr *entry, + bool quick); + /* * dir.c */ @@ -3170,7 +3175,7 @@ void f2fs_update_dentry(nid_t ino, umode_t mode, struct f2fs_dentry_ptr *d, const struct qstr *name, f2fs_hash_t name_hash, unsigned int bit_pos); int f2fs_add_regular_entry(struct inode *dir, const struct qstr *new_name, - const struct qstr *orig_name, f2fs_hash_t dentry_hash, + const struct qstr *orig_name, struct inode *inode, nid_t ino, umode_t mode); int f2fs_add_dentry(struct inode *dir, struct fscrypt_name *fname, struct inode *inode, nid_t ino, umode_t mode); @@ -3203,7 +3208,7 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi); * hash.c */ f2fs_hash_t f2fs_dentry_hash(const struct inode *dir, - const struct qstr *name_info, const struct fscrypt_name *fname); + const struct qstr *name_info, struct fscrypt_name *fname); /* * node.c @@ -3683,6 +3688,9 @@ static inline void update_sit_info(struct f2fs_sb_info *sbi) {} #endif extern const struct file_operations f2fs_dir_operations; +#ifdef CONFIG_UNICODE +extern const struct dentry_operations f2fs_dentry_ops; +#endif extern const struct file_operations f2fs_file_operations; extern const struct inode_operations f2fs_file_inode_operations; extern const struct address_space_operations f2fs_dblock_aops; @@ -3713,7 +3721,7 @@ struct f2fs_dir_entry *f2fs_find_in_inline_dir(struct inode *dir, int f2fs_make_empty_inline_dir(struct inode *inode, struct inode *parent, struct page *ipage); int f2fs_add_inline_entry(struct inode *dir, const struct qstr *new_name, - const struct fscrypt_name *fname, + const struct qstr *orig_name, struct inode *inode, nid_t ino, umode_t mode); void f2fs_delete_inline_entry(struct f2fs_dir_entry *dentry, struct page *page, struct inode *dir, diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 311a36cba330..b0c432c0fbb2 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -2444,14 +2444,6 @@ static int f2fs_ioc_get_encryption_key_status(struct file *filp, return fscrypt_ioctl_get_key_status(filp, (void __user *)arg); } -static int f2fs_ioc_get_encryption_nonce(struct file *filp, unsigned long arg) -{ - if (!f2fs_sb_has_encrypt(F2FS_I_SB(file_inode(filp)))) - return -EOPNOTSUPP; - - return fscrypt_ioctl_get_nonce(filp, (void __user *)arg); -} - static int f2fs_ioc_gc(struct file *filp, unsigned long arg) { struct inode *inode = file_inode(filp); @@ -3419,8 +3411,6 @@ long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return f2fs_ioc_remove_encryption_key_all_users(filp, arg); case FS_IOC_GET_ENCRYPTION_KEY_STATUS: return f2fs_ioc_get_encryption_key_status(filp, arg); - case FS_IOC_GET_ENCRYPTION_NONCE: - return f2fs_ioc_get_encryption_nonce(filp, arg); case F2FS_IOC_GARBAGE_COLLECT: return f2fs_ioc_gc(filp, arg); case F2FS_IOC_GARBAGE_COLLECT_RANGE: @@ -3600,7 +3590,6 @@ long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case FS_IOC_REMOVE_ENCRYPTION_KEY: case FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS: case FS_IOC_GET_ENCRYPTION_KEY_STATUS: - case FS_IOC_GET_ENCRYPTION_NONCE: case F2FS_IOC_GARBAGE_COLLECT: case F2FS_IOC_GARBAGE_COLLECT_RANGE: case F2FS_IOC_WRITE_CHECKPOINT: diff --git a/fs/f2fs/hash.c b/fs/f2fs/hash.c index 8f7ee4362312..28acb24e7a7a 100644 --- a/fs/f2fs/hash.c +++ b/fs/f2fs/hash.c @@ -68,9 +68,8 @@ static void str2hashbuf(const unsigned char *msg, size_t len, *buf++ = pad; } -static f2fs_hash_t __f2fs_dentry_hash(const struct inode *dir, - const struct qstr *name_info, - const struct fscrypt_name *fname) +static f2fs_hash_t __f2fs_dentry_hash(const struct qstr *name_info, + struct fscrypt_name *fname) { __u32 hash; f2fs_hash_t f2fs_hash; @@ -80,17 +79,12 @@ static f2fs_hash_t __f2fs_dentry_hash(const struct inode *dir, size_t len = name_info->len; /* encrypted bigname case */ - if (fname && fname->is_ciphertext_name) + if (fname && !fname->disk_name.name) return cpu_to_le32(fname->hash); if (is_dot_dotdot(name_info)) return 0; - if (IS_CASEFOLDED(dir) && IS_ENCRYPTED(dir)) { - f2fs_hash = cpu_to_le32(fscrypt_fname_siphash(dir, name_info)); - return f2fs_hash; - } - /* Initialize the default seed for the hash checksum functions */ buf[0] = 0x67452301; buf[1] = 0xefcdab89; @@ -112,7 +106,7 @@ static f2fs_hash_t __f2fs_dentry_hash(const struct inode *dir, } f2fs_hash_t f2fs_dentry_hash(const struct inode *dir, - const struct qstr *name_info, const struct fscrypt_name *fname) + const struct qstr *name_info, struct fscrypt_name *fname) { #ifdef CONFIG_UNICODE struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb); @@ -120,30 +114,27 @@ f2fs_hash_t f2fs_dentry_hash(const struct inode *dir, int r, dlen; unsigned char *buff; struct qstr folded; - const struct qstr *name = fname ? fname->usr_fname : name_info; if (!name_info->len || !IS_CASEFOLDED(dir)) goto opaque_seq; - if (IS_ENCRYPTED(dir) && !fscrypt_has_encryption_key(dir)) - goto opaque_seq; - buff = f2fs_kzalloc(sbi, sizeof(char) * PATH_MAX, GFP_KERNEL); if (!buff) return -ENOMEM; - dlen = utf8_casefold(um, name, buff, PATH_MAX); + + dlen = utf8_casefold(um, name_info, buff, PATH_MAX); if (dlen < 0) { kvfree(buff); goto opaque_seq; } folded.name = buff; folded.len = dlen; - r = __f2fs_dentry_hash(dir, &folded, fname); + r = __f2fs_dentry_hash(&folded, fname); kvfree(buff); return r; opaque_seq: #endif - return __f2fs_dentry_hash(dir, name_info, fname); + return __f2fs_dentry_hash(name_info, fname); } diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c index c68a32369f44..cabc7a69cee4 100644 --- a/fs/f2fs/inline.c +++ b/fs/f2fs/inline.c @@ -483,8 +483,8 @@ static int f2fs_add_inline_entries(struct inode *dir, void *inline_dentry) ino = le32_to_cpu(de->ino); fake_mode = f2fs_get_de_type(de) << S_SHIFT; - err = f2fs_add_regular_entry(dir, &new_name, NULL, - de->hash_code, NULL, ino, fake_mode); + err = f2fs_add_regular_entry(dir, &new_name, NULL, NULL, + ino, fake_mode); if (err) goto punch_dentry_pages; @@ -596,7 +596,7 @@ out: } int f2fs_add_inline_entry(struct inode *dir, const struct qstr *new_name, - const struct fscrypt_name *fname, + const struct qstr *orig_name, struct inode *inode, nid_t ino, umode_t mode) { struct f2fs_sb_info *sbi = F2FS_I_SB(dir); @@ -607,7 +607,6 @@ int f2fs_add_inline_entry(struct inode *dir, const struct qstr *new_name, struct f2fs_dentry_ptr d; int slots = GET_DENTRY_SLOTS(new_name->len); struct page *page = NULL; - const struct qstr *orig_name = fname->usr_fname; int err = 0; ipage = f2fs_get_node_page(sbi, dir->i_ino); @@ -638,7 +637,7 @@ int f2fs_add_inline_entry(struct inode *dir, const struct qstr *new_name, f2fs_wait_on_page_writeback(ipage, NODE, true, true); - name_hash = f2fs_dentry_hash(dir, new_name, fname); + name_hash = f2fs_dentry_hash(dir, new_name, NULL); f2fs_update_dentry(ino, mode, &d, new_name, name_hash, bit_pos); set_page_dirty(ipage); diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c index a8959c64bf3a..23d6cccdb4c1 100644 --- a/fs/f2fs/namei.c +++ b/fs/f2fs/namei.c @@ -492,7 +492,6 @@ static struct dentry *f2fs_lookup(struct inode *dir, struct dentry *dentry, } err = fscrypt_prepare_lookup(dir, dentry, &fname); - generic_set_encrypted_ci_d_ops(dir, dentry); if (err == -ENOENT) goto out_splice; if (err) diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index ce4d1930f369..e3e37be7f214 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -3309,6 +3309,12 @@ static int f2fs_setup_casefold(struct f2fs_sb_info *sbi) struct unicode_map *encoding; __u16 encoding_flags; + if (f2fs_sb_has_encrypt(sbi)) { + f2fs_err(sbi, + "Can't mount with encoding and encryption"); + return -EINVAL; + } + if (f2fs_sb_read_encoding(sbi->raw_super, &encoding_info, &encoding_flags)) { f2fs_err(sbi, @@ -3331,6 +3337,7 @@ static int f2fs_setup_casefold(struct f2fs_sb_info *sbi) sbi->sb->s_encoding = encoding; sbi->sb->s_encoding_flags = encoding_flags; + sbi->sb->s_d_op = &f2fs_dentry_ops; } #else if (f2fs_sb_has_casefold(sbi)) { diff --git a/fs/inode.c b/fs/inode.c index 8c25e0df7a0e..4e30a37ef712 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -2167,7 +2166,7 @@ int vfs_ioc_setflags_prepare(struct inode *inode, unsigned int oldflags, !capable(CAP_LINUX_IMMUTABLE)) return -EPERM; - return fscrypt_prepare_setflags(inode, oldflags, flags); + return 0; } EXPORT_SYMBOL(vfs_ioc_setflags_prepare); diff --git a/fs/libfs.c b/fs/libfs.c index 4f2ac9ac0c9a..f66eb521d4f8 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -1281,54 +1281,4 @@ err: return ret; } EXPORT_SYMBOL(generic_ci_d_hash); - -static const struct dentry_operations generic_ci_dentry_ops = { - .d_hash = generic_ci_d_hash, - .d_compare = generic_ci_d_compare, -}; #endif - -#ifdef CONFIG_FS_ENCRYPTION -static const struct dentry_operations generic_encrypted_dentry_ops = { - .d_revalidate = fscrypt_d_revalidate, -}; -#endif - -#if IS_ENABLED(CONFIG_UNICODE) && IS_ENABLED(CONFIG_FS_ENCRYPTION) -static const struct dentry_operations generic_encrypted_ci_dentry_ops = { - .d_hash = generic_ci_d_hash, - .d_compare = generic_ci_d_compare, - .d_revalidate = fscrypt_d_revalidate, -}; -#endif - -/** - * generic_set_encrypted_ci_d_ops - helper for setting d_ops for given dentry - * @dir: parent of dentry whose ops to set - * @dentry: detnry to set ops on - * - * This function sets the dentry ops for the given dentry to handle both - * casefolding and encryption of the dentry name. - */ -void generic_set_encrypted_ci_d_ops(struct inode *dir, struct dentry *dentry) -{ -#ifdef CONFIG_FS_ENCRYPTION - if (dentry->d_flags & DCACHE_ENCRYPTED_NAME) { -#ifdef CONFIG_UNICODE - if (dir->i_sb->s_encoding) { - d_set_d_op(dentry, &generic_encrypted_ci_dentry_ops); - return; - } -#endif - d_set_d_op(dentry, &generic_encrypted_dentry_ops); - return; - } -#endif -#ifdef CONFIG_UNICODE - if (dir->i_sb->s_encoding) { - d_set_d_op(dentry, &generic_ci_dentry_ops); - return; - } -#endif -} -EXPORT_SYMBOL(generic_set_encrypted_ci_d_ops); diff --git a/fs/ubifs/Kconfig b/fs/ubifs/Kconfig index fe221d7d99d6..dfc6fdf019d7 100644 --- a/fs/ubifs/Kconfig +++ b/fs/ubifs/Kconfig @@ -7,7 +7,6 @@ config UBIFS_FS select CRYPTO if UBIFS_FS_ZLIB select CRYPTO_LZO if UBIFS_FS_LZO select CRYPTO_DEFLATE if UBIFS_FS_ZLIB - select FS_ENCRYPTION_ALGS if FS_ENCRYPTION depends on MTD_UBI help UBIFS is a file system for flash devices which works on top of UBI. diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c index 7d5c2cf95353..26ac11d0eb4b 100644 --- a/fs/ubifs/dir.c +++ b/fs/ubifs/dir.c @@ -208,7 +208,6 @@ static int dbg_check_name(const struct ubifs_info *c, return 0; } -static void ubifs_set_d_ops(struct inode *dir, struct dentry *dentry); static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) { @@ -222,7 +221,6 @@ static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry, dbg_gen("'%pd' in dir ino %lu", dentry, dir->i_ino); err = fscrypt_prepare_lookup(dir, dentry, &nm); - ubifs_set_d_ops(dir, dentry); if (err == -ENOENT) return d_splice_alias(NULL, dentry); if (err) @@ -539,7 +537,7 @@ static int ubifs_readdir(struct file *file, struct dir_context *ctx) if (encrypted) { err = fscrypt_get_encryption_info(dir); - if (err) + if (err && err != -ENOKEY) return err; err = fscrypt_fname_alloc_buffer(dir, UBIFS_MAX_NLEN, &fstr); @@ -1686,19 +1684,3 @@ const struct file_operations ubifs_dir_operations = { .compat_ioctl = ubifs_compat_ioctl, #endif }; - -#ifdef CONFIG_FS_ENCRYPTION -static const struct dentry_operations ubifs_encrypted_dentry_ops = { - .d_revalidate = fscrypt_d_revalidate, -}; -#endif - -static void ubifs_set_d_ops(struct inode *dir, struct dentry *dentry) -{ -#ifdef CONFIG_FS_ENCRYPTION - if (dentry->d_flags & DCACHE_ENCRYPTED_NAME) { - d_set_d_op(dentry, &ubifs_encrypted_dentry_ops); - return; - } -#endif -} diff --git a/fs/ubifs/ioctl.c b/fs/ubifs/ioctl.c index daa59b98c8b4..203067d39855 100644 --- a/fs/ubifs/ioctl.c +++ b/fs/ubifs/ioctl.c @@ -229,9 +229,6 @@ long ubifs_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case FS_IOC_GET_ENCRYPTION_KEY_STATUS: return fscrypt_ioctl_get_key_status(file, (void __user *)arg); - case FS_IOC_GET_ENCRYPTION_NONCE: - return fscrypt_ioctl_get_nonce(file, (void __user *)arg); - default: return -ENOTTY; } @@ -254,7 +251,6 @@ long ubifs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case FS_IOC_REMOVE_ENCRYPTION_KEY: case FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS: case FS_IOC_GET_ENCRYPTION_KEY_STATUS: - case FS_IOC_GET_ENCRYPTION_NONCE: break; default: return -ENOIOCTLCMD; diff --git a/include/linux/bio-crypt-ctx.h b/include/linux/bio-crypt-ctx.h index 8456a409fc21..ab22dbe7b880 100644 --- a/include/linux/bio-crypt-ctx.h +++ b/include/linux/bio-crypt-ctx.h @@ -31,8 +31,6 @@ enum blk_crypto_mode_num { * @data_unit_size_bits: log2 of data_unit_size * @size: size of this key in bytes (determined by @crypto_mode) * @hash: hash of this key, for keyslot manager use only - * @is_hw_wrapped: @raw points to a wrapped key to be used by an inline - * encryption hardware that accepts wrapped keys. * @raw: the raw bytes of this key. Only the first @size bytes are used. * * A blk_crypto_key is immutable once created, and many bios can reference it at @@ -44,7 +42,6 @@ struct blk_crypto_key { unsigned int data_unit_size_bits; unsigned int size; unsigned int hash; - bool is_hw_wrapped; u8 raw[BLK_CRYPTO_MAX_WRAPPED_KEY_SIZE]; }; diff --git a/include/linux/blk-crypto.h b/include/linux/blk-crypto.h index 7dc478a8c3ed..485cee0b92dd 100644 --- a/include/linux/blk-crypto.h +++ b/include/linux/blk-crypto.h @@ -18,15 +18,9 @@ bool blk_crypto_endio(struct bio *bio); int blk_crypto_init_key(struct blk_crypto_key *blk_key, const u8 *raw_key, unsigned int raw_key_size, - bool is_hw_wrapped, enum blk_crypto_mode_num crypto_mode, unsigned int data_unit_size); -int blk_crypto_start_using_mode(enum blk_crypto_mode_num crypto_mode, - unsigned int data_unit_size, - bool is_hw_wrapped_key, - struct request_queue *q); - int blk_crypto_evict_key(struct request_queue *q, const struct blk_crypto_key *key); @@ -46,10 +40,22 @@ static inline bool blk_crypto_endio(struct bio *bio) #ifdef CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK +int blk_crypto_start_using_mode(enum blk_crypto_mode_num mode_num, + unsigned int data_unit_size, + struct request_queue *q); + int blk_crypto_fallback_init(void); #else /* CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK */ +static inline int +blk_crypto_start_using_mode(enum blk_crypto_mode_num mode_num, + unsigned int data_unit_size, + struct request_queue *q) +{ + return 0; +} + static inline int blk_crypto_fallback_init(void) { return 0; diff --git a/include/linux/fs.h b/include/linux/fs.h index a15c86a92a08..31a6ae9e28c8 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -3212,8 +3212,6 @@ static inline bool needs_casefold(const struct inode *dir) return 0; } #endif -extern void generic_set_encrypted_ci_d_ops(struct inode *dir, - struct dentry *dentry); #ifdef CONFIG_MIGRATION extern int buffer_migrate_page(struct address_space *, diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h index 2a9cd6c5f361..6ac092cc4067 100644 --- a/include/linux/fscrypt.h +++ b/include/linux/fscrypt.h @@ -76,21 +76,6 @@ static inline bool fscrypt_has_encryption_key(const struct inode *inode) return READ_ONCE(inode->i_crypt_info) != NULL; } -/** - * fscrypt_needs_contents_encryption() - check whether an inode needs - * contents encryption - * - * Return: %true iff the inode is an encrypted regular file and the kernel was - * built with fscrypt support. - * - * If you need to know whether the encrypt bit is set even when the kernel was - * built without fscrypt support, you must use IS_ENCRYPTED() directly instead. - */ -static inline bool fscrypt_needs_contents_encryption(const struct inode *inode) -{ - return IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode); -} - static inline bool fscrypt_dummy_context_enabled(struct inode *inode) { return inode->i_sb->s_cop->dummy_context && @@ -138,13 +123,11 @@ static inline struct page *fscrypt_pagecache_page(struct page *bounce_page) } extern void fscrypt_free_bounce_page(struct page *bounce_page); -extern int fscrypt_d_revalidate(struct dentry *dentry, unsigned int flags); /* policy.c */ extern int fscrypt_ioctl_set_policy(struct file *, const void __user *); extern int fscrypt_ioctl_get_policy(struct file *, void __user *); extern int fscrypt_ioctl_get_policy_ex(struct file *, void __user *); -extern int fscrypt_ioctl_get_nonce(struct file *filp, void __user *arg); extern int fscrypt_has_permitted_context(struct inode *, struct inode *); extern int fscrypt_inherit_context(struct inode *, struct inode *, void *, bool); @@ -176,14 +159,82 @@ static inline void fscrypt_free_filename(struct fscrypt_name *fname) extern int fscrypt_fname_alloc_buffer(const struct inode *, u32, struct fscrypt_str *); extern void fscrypt_fname_free_buffer(struct fscrypt_str *); -extern int fscrypt_fname_disk_to_usr(const struct inode *inode, - u32 hash, u32 minor_hash, - const struct fscrypt_str *iname, - struct fscrypt_str *oname); -extern bool fscrypt_match_name(const struct fscrypt_name *fname, - const u8 *de_name, u32 de_name_len); -extern u64 fscrypt_fname_siphash(const struct inode *dir, - const struct qstr *name); +extern int fscrypt_fname_disk_to_usr(struct inode *, u32, u32, + const struct fscrypt_str *, struct fscrypt_str *); + +#define FSCRYPT_FNAME_MAX_UNDIGESTED_SIZE 32 + +/* Extracts the second-to-last ciphertext block; see explanation below */ +#define FSCRYPT_FNAME_DIGEST(name, len) \ + ((name) + round_down((len) - FS_CRYPTO_BLOCK_SIZE - 1, \ + FS_CRYPTO_BLOCK_SIZE)) + +#define FSCRYPT_FNAME_DIGEST_SIZE FS_CRYPTO_BLOCK_SIZE + +/** + * fscrypt_digested_name - alternate identifier for an on-disk filename + * + * When userspace lists an encrypted directory without access to the key, + * filenames whose ciphertext is longer than FSCRYPT_FNAME_MAX_UNDIGESTED_SIZE + * bytes are shown in this abbreviated form (base64-encoded) rather than as the + * full ciphertext (base64-encoded). This is necessary to allow supporting + * filenames up to NAME_MAX bytes, since base64 encoding expands the length. + * + * To make it possible for filesystems to still find the correct directory entry + * despite not knowing the full on-disk name, we encode any filesystem-specific + * 'hash' and/or 'minor_hash' which the filesystem may need for its lookups, + * followed by the second-to-last ciphertext block of the filename. Due to the + * use of the CBC-CTS encryption mode, the second-to-last ciphertext block + * depends on the full plaintext. (Note that ciphertext stealing causes the + * last two blocks to appear "flipped".) This makes accidental collisions very + * unlikely: just a 1 in 2^128 chance for two filenames to collide even if they + * share the same filesystem-specific hashes. + * + * However, this scheme isn't immune to intentional collisions, which can be + * created by anyone able to create arbitrary plaintext filenames and view them + * without the key. Making the "digest" be a real cryptographic hash like + * SHA-256 over the full ciphertext would prevent this, although it would be + * less efficient and harder to implement, especially since the filesystem would + * need to calculate it for each directory entry examined during a search. + */ +struct fscrypt_digested_name { + u32 hash; + u32 minor_hash; + u8 digest[FSCRYPT_FNAME_DIGEST_SIZE]; +}; + +/** + * fscrypt_match_name() - test whether the given name matches a directory entry + * @fname: the name being searched for + * @de_name: the name from the directory entry + * @de_name_len: the length of @de_name in bytes + * + * Normally @fname->disk_name will be set, and in that case we simply compare + * that to the name stored in the directory entry. The only exception is that + * if we don't have the key for an encrypted directory and a filename in it is + * very long, then we won't have the full disk_name and we'll instead need to + * match against the fscrypt_digested_name. + * + * Return: %true if the name matches, otherwise %false. + */ +static inline bool fscrypt_match_name(const struct fscrypt_name *fname, + const u8 *de_name, u32 de_name_len) +{ + if (unlikely(!fname->disk_name.name)) { + const struct fscrypt_digested_name *n = + (const void *)fname->crypto_buf.name; + if (WARN_ON_ONCE(fname->usr_fname->name[0] != '_')) + return false; + if (de_name_len <= FSCRYPT_FNAME_MAX_UNDIGESTED_SIZE) + return false; + return !memcmp(FSCRYPT_FNAME_DIGEST(de_name, de_name_len), + n->digest, FSCRYPT_FNAME_DIGEST_SIZE); + } + + if (de_name_len != fname->disk_name.len) + return false; + return !memcmp(de_name, fname->disk_name.name, fname->disk_name.len); +} /* bio.c */ extern void fscrypt_decrypt_bio(struct bio *); @@ -201,8 +252,6 @@ extern int __fscrypt_prepare_rename(struct inode *old_dir, unsigned int flags); extern int __fscrypt_prepare_lookup(struct inode *dir, struct dentry *dentry, struct fscrypt_name *fname); -extern int fscrypt_prepare_setflags(struct inode *inode, - unsigned int oldflags, unsigned int flags); extern int __fscrypt_prepare_symlink(struct inode *dir, unsigned int len, unsigned int max_len, struct fscrypt_str *disk_link); @@ -219,11 +268,6 @@ static inline bool fscrypt_has_encryption_key(const struct inode *inode) return false; } -static inline bool fscrypt_needs_contents_encryption(const struct inode *inode) -{ - return false; -} - static inline bool fscrypt_dummy_context_enabled(struct inode *inode) { return false; @@ -303,11 +347,6 @@ static inline int fscrypt_ioctl_get_policy_ex(struct file *filp, return -EOPNOTSUPP; } -static inline int fscrypt_ioctl_get_nonce(struct file *filp, void __user *arg) -{ - return -EOPNOTSUPP; -} - static inline int fscrypt_has_permitted_context(struct inode *parent, struct inode *child) { @@ -412,7 +451,7 @@ static inline void fscrypt_fname_free_buffer(struct fscrypt_str *crypto_str) return; } -static inline int fscrypt_fname_disk_to_usr(const struct inode *inode, +static inline int fscrypt_fname_disk_to_usr(struct inode *inode, u32 hash, u32 minor_hash, const struct fscrypt_str *iname, struct fscrypt_str *oname) @@ -429,13 +468,6 @@ static inline bool fscrypt_match_name(const struct fscrypt_name *fname, return !memcmp(de_name, fname->disk_name.name, fname->disk_name.len); } -static inline u64 fscrypt_fname_siphash(const struct inode *dir, - const struct qstr *name) -{ - WARN_ON_ONCE(1); - return 0; -} - /* bio.c */ static inline void fscrypt_decrypt_bio(struct bio *bio) { @@ -478,13 +510,6 @@ static inline int __fscrypt_prepare_lookup(struct inode *dir, return -EOPNOTSUPP; } -static inline int fscrypt_prepare_setflags(struct inode *inode, - unsigned int oldflags, - unsigned int flags) -{ - return 0; -} - static inline int __fscrypt_prepare_symlink(struct inode *dir, unsigned int len, unsigned int max_len, @@ -677,9 +702,8 @@ static inline int fscrypt_prepare_rename(struct inode *old_dir, * filenames are presented in encrypted form. Therefore, we'll try to set up * the directory's encryption key, but even without it the lookup can continue. * - * After calling this function, a filesystem should ensure that it's dentry - * operations contain fscrypt_d_revalidate if DCACHE_ENCRYPTED_NAME was set, - * so that the dentry can be invalidated if the key is later added. + * This also installs a custom ->d_revalidate() method which will invalidate the + * dentry if it was created without the key and the key is later added. * * Return: 0 on success; -ENOENT if key is unavailable but the filename isn't a * correctly formed encoded ciphertext name, so a negative dentry should be diff --git a/include/linux/keyslot-manager.h b/include/linux/keyslot-manager.h index cd65bea927db..2f4aac2851bf 100644 --- a/include/linux/keyslot-manager.h +++ b/include/linux/keyslot-manager.h @@ -8,15 +8,6 @@ #include -/* Inline crypto feature bits. Must set at least one. */ -enum { - /* Support for standard software-specified keys */ - BLK_CRYPTO_FEATURE_STANDARD_KEYS = BIT(0), - - /* Support for hardware-wrapped keys */ - BLK_CRYPTO_FEATURE_WRAPPED_KEYS = BIT(1), -}; - #ifdef CONFIG_BLK_INLINE_ENCRYPTION struct keyslot_manager; @@ -54,7 +45,6 @@ struct keyslot_manager *keyslot_manager_create( struct device *dev, unsigned int num_slots, const struct keyslot_mgmt_ll_ops *ksm_ops, - unsigned int features, const unsigned int crypto_mode_supported[BLK_ENCRYPTION_MODE_MAX], void *ll_priv_data); @@ -67,8 +57,7 @@ void keyslot_manager_put_slot(struct keyslot_manager *ksm, unsigned int slot); bool keyslot_manager_crypto_mode_supported(struct keyslot_manager *ksm, enum blk_crypto_mode_num crypto_mode, - unsigned int data_unit_size, - bool is_hw_wrapped_key); + unsigned int data_unit_size); int keyslot_manager_evict_key(struct keyslot_manager *ksm, const struct blk_crypto_key *key); @@ -82,7 +71,6 @@ void keyslot_manager_destroy(struct keyslot_manager *ksm); struct keyslot_manager *keyslot_manager_create_passthrough( struct device *dev, const struct keyslot_mgmt_ll_ops *ksm_ops, - unsigned int features, const unsigned int crypto_mode_supported[BLK_ENCRYPTION_MODE_MAX], void *ll_priv_data); diff --git a/include/uapi/linux/fscrypt.h b/include/uapi/linux/fscrypt.h index 320a6381576e..7d150d800abc 100644 --- a/include/uapi/linux/fscrypt.h +++ b/include/uapi/linux/fscrypt.h @@ -8,7 +8,6 @@ #ifndef _UAPI_LINUX_FSCRYPT_H #define _UAPI_LINUX_FSCRYPT_H -#include #include /* Encryption policy flags */ @@ -110,22 +109,11 @@ struct fscrypt_key_specifier { } u; }; -/* - * Payload of Linux keyring key of type "fscrypt-provisioning", referenced by - * fscrypt_add_key_arg::key_id as an alternative to fscrypt_add_key_arg::raw. - */ -struct fscrypt_provisioning_key_payload { - __u32 type; - __u32 __reserved; - __u8 raw[]; -}; - /* Struct passed to FS_IOC_ADD_ENCRYPTION_KEY */ struct fscrypt_add_key_arg { struct fscrypt_key_specifier key_spec; __u32 raw_size; - __u32 key_id; - __u32 __reserved[7]; + __u32 __reserved[8]; /* N.B.: "temporary" flag, not reserved upstream */ #define __FSCRYPT_ADD_KEY_FLAG_HW_WRAPPED 0x00000001 __u32 __flags; @@ -166,7 +154,6 @@ struct fscrypt_get_key_status_arg { #define FS_IOC_REMOVE_ENCRYPTION_KEY _IOWR('f', 24, struct fscrypt_remove_key_arg) #define FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS _IOWR('f', 25, struct fscrypt_remove_key_arg) #define FS_IOC_GET_ENCRYPTION_KEY_STATUS _IOWR('f', 26, struct fscrypt_get_key_status_arg) -#define FS_IOC_GET_ENCRYPTION_NONCE _IOR('f', 27, __u8[16]) /**********************************************************************/ From d6fb207052dc6c3fd1a3928a978096d66fd50bfd Mon Sep 17 00:00:00 2001 From: Srinivasarao P Date: Tue, 4 Aug 2020 14:21:14 +0530 Subject: [PATCH 372/592] Revert "clk: qcom: rcg2: Don't crash if our parent can't be found; return an error" This reverts commit ef7339a38eccc07dbbc6a4dde0c0d4d3be157a87. Change-Id: I4ca79e90de2ab00a7d679ca038661f5605c06947 Signed-off-by: Srinivasarao P --- drivers/clk/qcom/clk-rcg2.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c index 6091d9b6a27b..2e23f8754f8e 100644 --- a/drivers/clk/qcom/clk-rcg2.c +++ b/drivers/clk/qcom/clk-rcg2.c @@ -210,9 +210,6 @@ static int _freq_tbl_determine_rate(struct clk_hw *hw, const struct freq_tbl *f, clk_flags = clk_hw_get_flags(hw); p = clk_hw_get_parent_by_index(hw, index); - if (!p) - return -EINVAL; - if (clk_flags & CLK_SET_RATE_PARENT) { if (f->pre_div) { if (!rate) From 3a156abd24346a3188eb7e88cf86386a409e0d02 Mon Sep 17 00:00:00 2001 From: Jason Yan Date: Fri, 8 Dec 2017 17:42:09 +0800 Subject: [PATCH 373/592] scsi: libsas: direct call probe and destruct [ Upstream commit 0558f33c06bb910e2879e355192227a8e8f0219d ] In commit 87c8331fcf72 ("[SCSI] libsas: prevent domain rediscovery competing with ata error handling") introduced disco mutex to prevent rediscovery competing with ata error handling and put the whole revalidation in the mutex. But the rphy add/remove needs to wait for the error handling which also grabs the disco mutex. This may leads to dead lock.So the probe and destruct event were introduce to do the rphy add/remove asynchronously and out of the lock. The asynchronously processed workers makes the whole discovery process not atomic, the other events may interrupt the process. For example, if a loss of signal event inserted before the probe event, the sas_deform_port() is called and the port will be deleted. And sas_port_delete() may run before the destruct event, but the port-x:x is the top parent of end device or expander. This leads to a kernel WARNING such as: [ 82.042979] sysfs group 'power' not found for kobject 'phy-1:0:22' [ 82.042983] ------------[ cut here ]------------ [ 82.042986] WARNING: CPU: 54 PID: 1714 at fs/sysfs/group.c:237 sysfs_remove_group+0x94/0xa0 [ 82.043059] Call trace: [ 82.043082] [] sysfs_remove_group+0x94/0xa0 [ 82.043085] [] dpm_sysfs_remove+0x60/0x70 [ 82.043086] [] device_del+0x138/0x308 [ 82.043089] [] sas_phy_delete+0x38/0x60 [ 82.043091] [] do_sas_phy_delete+0x6c/0x80 [ 82.043093] [] device_for_each_child+0x58/0xa0 [ 82.043095] [] sas_remove_children+0x40/0x50 [ 82.043100] [] sas_destruct_devices+0x64/0xa0 [ 82.043102] [] process_one_work+0x1fc/0x4b0 [ 82.043104] [] worker_thread+0x50/0x490 [ 82.043105] [] kthread+0xfc/0x128 [ 82.043107] [] ret_from_fork+0x10/0x50 Make probe and destruct a direct call in the disco and revalidate function, but put them outside the lock. The whole discovery or revalidate won't be interrupted by other events. And the DISCE_PROBE and DISCE_DESTRUCT event are deleted as a result of the direct call. Introduce a new list to destruct the sas_port and put the port delete after the destruct. This makes sure the right order of destroying the sysfs kobject and fix the warning above. In sas_ex_revalidate_domain() have a loop to find all broadcasted device, and sometimes we have a chance to find the same expander twice. Because the sas_port will be deleted at the end of the whole revalidate process, sas_port with the same name cannot be added before this. Otherwise the sysfs will complain of creating duplicate filename. Since the LLDD will send broadcast for every device change, we can only process one expander's revalidation. [mkp: kbuild test robot warning] Signed-off-by: Jason Yan CC: John Garry CC: Johannes Thumshirn CC: Ewan Milne CC: Christoph Hellwig CC: Tomas Henzl CC: Dan Williams Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen Signed-off-by: Sasha Levin --- drivers/scsi/libsas/sas_ata.c | 1 - drivers/scsi/libsas/sas_discover.c | 32 +++++++++++++++++------------- drivers/scsi/libsas/sas_expander.c | 8 +++----- drivers/scsi/libsas/sas_internal.h | 1 + drivers/scsi/libsas/sas_port.c | 3 +++ include/scsi/libsas.h | 3 +-- include/scsi/scsi_transport_sas.h | 1 + 7 files changed, 27 insertions(+), 22 deletions(-) diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index 70be4425ae0b..2b3637b40dde 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c @@ -730,7 +730,6 @@ int sas_discover_sata(struct domain_device *dev) if (res) return res; - sas_discover_event(dev->port, DISCE_PROBE); return 0; } diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c index b200edc665a5..d6365e2fcc60 100644 --- a/drivers/scsi/libsas/sas_discover.c +++ b/drivers/scsi/libsas/sas_discover.c @@ -221,13 +221,9 @@ void sas_notify_lldd_dev_gone(struct domain_device *dev) } } -static void sas_probe_devices(struct work_struct *work) +static void sas_probe_devices(struct asd_sas_port *port) { struct domain_device *dev, *n; - struct sas_discovery_event *ev = to_sas_discovery_event(work); - struct asd_sas_port *port = ev->port; - - clear_bit(DISCE_PROBE, &port->disc.pending); /* devices must be domain members before link recovery and probe */ list_for_each_entry(dev, &port->disco_list, disco_list_node) { @@ -303,7 +299,6 @@ int sas_discover_end_dev(struct domain_device *dev) res = sas_notify_lldd_dev_found(dev); if (res) return res; - sas_discover_event(dev->port, DISCE_PROBE); return 0; } @@ -362,13 +357,9 @@ static void sas_unregister_common_dev(struct asd_sas_port *port, struct domain_d sas_put_device(dev); } -static void sas_destruct_devices(struct work_struct *work) +void sas_destruct_devices(struct asd_sas_port *port) { struct domain_device *dev, *n; - struct sas_discovery_event *ev = to_sas_discovery_event(work); - struct asd_sas_port *port = ev->port; - - clear_bit(DISCE_DESTRUCT, &port->disc.pending); list_for_each_entry_safe(dev, n, &port->destroy_list, disco_list_node) { list_del_init(&dev->disco_list_node); @@ -379,6 +370,16 @@ static void sas_destruct_devices(struct work_struct *work) } } +static void sas_destruct_ports(struct asd_sas_port *port) +{ + struct sas_port *sas_port, *p; + + list_for_each_entry_safe(sas_port, p, &port->sas_port_del_list, del_list) { + list_del_init(&sas_port->del_list); + sas_port_delete(sas_port); + } +} + void sas_unregister_dev(struct asd_sas_port *port, struct domain_device *dev) { if (!test_bit(SAS_DEV_DESTROY, &dev->state) && @@ -393,7 +394,6 @@ void sas_unregister_dev(struct asd_sas_port *port, struct domain_device *dev) if (!test_and_set_bit(SAS_DEV_DESTROY, &dev->state)) { sas_rphy_unlink(dev->rphy); list_move_tail(&dev->disco_list_node, &port->destroy_list); - sas_discover_event(dev->port, DISCE_DESTRUCT); } } @@ -499,6 +499,8 @@ static void sas_discover_domain(struct work_struct *work) port->port_dev = NULL; } + sas_probe_devices(port); + SAS_DPRINTK("DONE DISCOVERY on port %d, pid:%d, result:%d\n", port->id, task_pid_nr(current), error); } @@ -532,6 +534,10 @@ static void sas_revalidate_domain(struct work_struct *work) port->id, task_pid_nr(current), res); out: mutex_unlock(&ha->disco_mutex); + + sas_destruct_devices(port); + sas_destruct_ports(port); + sas_probe_devices(port); } /* ---------- Events ---------- */ @@ -587,10 +593,8 @@ void sas_init_disc(struct sas_discovery *disc, struct asd_sas_port *port) static const work_func_t sas_event_fns[DISC_NUM_EVENTS] = { [DISCE_DISCOVER_DOMAIN] = sas_discover_domain, [DISCE_REVALIDATE_DOMAIN] = sas_revalidate_domain, - [DISCE_PROBE] = sas_probe_devices, [DISCE_SUSPEND] = sas_suspend_devices, [DISCE_RESUME] = sas_resume_devices, - [DISCE_DESTRUCT] = sas_destruct_devices, }; disc->pending = 0; diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index f77d72f01da9..84df6cf46760 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c @@ -1946,7 +1946,8 @@ static void sas_unregister_devs_sas_addr(struct domain_device *parent, sas_port_delete_phy(phy->port, phy->phy); sas_device_set_phy(found, phy->port); if (phy->port->num_phys == 0) - sas_port_delete(phy->port); + list_add_tail(&phy->port->del_list, + &parent->port->sas_port_del_list); phy->port = NULL; } } @@ -2156,7 +2157,7 @@ int sas_ex_revalidate_domain(struct domain_device *port_dev) struct domain_device *dev = NULL; res = sas_find_bcast_dev(port_dev, &dev); - while (res == 0 && dev) { + if (res == 0 && dev) { struct expander_device *ex = &dev->ex_dev; int i = 0, phy_id; @@ -2168,9 +2169,6 @@ int sas_ex_revalidate_domain(struct domain_device *port_dev) res = sas_rediscover(dev, phy_id); i = phy_id + 1; } while (i < ex->num_phys); - - dev = NULL; - res = sas_find_bcast_dev(port_dev, &dev); } return res; } diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h index c07e08136491..f3449fde9c5f 100644 --- a/drivers/scsi/libsas/sas_internal.h +++ b/drivers/scsi/libsas/sas_internal.h @@ -98,6 +98,7 @@ int sas_try_ata_reset(struct asd_sas_phy *phy); void sas_hae_reset(struct work_struct *work); void sas_free_device(struct kref *kref); +void sas_destruct_devices(struct asd_sas_port *port); #ifdef CONFIG_SCSI_SAS_HOST_SMP extern void sas_smp_host_handler(struct bsg_job *job, struct Scsi_Host *shost); diff --git a/drivers/scsi/libsas/sas_port.c b/drivers/scsi/libsas/sas_port.c index d3c5297c6c89..5d3244c8f280 100644 --- a/drivers/scsi/libsas/sas_port.c +++ b/drivers/scsi/libsas/sas_port.c @@ -66,6 +66,7 @@ static void sas_resume_port(struct asd_sas_phy *phy) rc = sas_notify_lldd_dev_found(dev); if (rc) { sas_unregister_dev(port, dev); + sas_destruct_devices(port); continue; } @@ -219,6 +220,7 @@ void sas_deform_port(struct asd_sas_phy *phy, int gone) if (port->num_phys == 1) { sas_unregister_domain_devices(port, gone); + sas_destruct_devices(port); sas_port_delete(port->port); port->port = NULL; } else { @@ -323,6 +325,7 @@ static void sas_init_port(struct asd_sas_port *port, INIT_LIST_HEAD(&port->dev_list); INIT_LIST_HEAD(&port->disco_list); INIT_LIST_HEAD(&port->destroy_list); + INIT_LIST_HEAD(&port->sas_port_del_list); spin_lock_init(&port->phy_list_lock); INIT_LIST_HEAD(&port->phy_list); port->ha = sas_ha; diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index a966d281dedc..1b1cf9eff3b5 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -87,10 +87,8 @@ enum discover_event { DISCE_DISCOVER_DOMAIN = 0U, DISCE_REVALIDATE_DOMAIN = 1, DISCE_PORT_GONE = 2, - DISCE_PROBE = 3, DISCE_SUSPEND = 4, DISCE_RESUME = 5, - DISCE_DESTRUCT = 6, DISC_NUM_EVENTS = 7, }; @@ -269,6 +267,7 @@ struct asd_sas_port { struct list_head dev_list; struct list_head disco_list; struct list_head destroy_list; + struct list_head sas_port_del_list; enum sas_linkrate linkrate; struct sas_work work; diff --git a/include/scsi/scsi_transport_sas.h b/include/scsi/scsi_transport_sas.h index 62895b405933..05ec927a3c72 100644 --- a/include/scsi/scsi_transport_sas.h +++ b/include/scsi/scsi_transport_sas.h @@ -156,6 +156,7 @@ struct sas_port { struct mutex phy_list_mutex; struct list_head phy_list; + struct list_head del_list; /* libsas only */ }; #define dev_to_sas_port(d) \ From 9e06953ee2a406c4bf4ff08c700d3ce1254974d1 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Thu, 11 Jan 2018 11:21:51 +0000 Subject: [PATCH 374/592] net: phy: mdio-bcm-unimac: fix potential NULL dereference in unimac_mdio_probe() [ Upstream commit 297a6961ffb8ff4dc66c9fbf53b924bd1dda05d5 ] platform_get_resource() may fail and return NULL, so we should better check it's return value to avoid a NULL pointer dereference a bit later in the code. This is detected by Coccinelle semantic patch. @@ expression pdev, res, n, t, e, e1, e2; @@ res = platform_get_resource(pdev, t, n); + if (!res) + return -EINVAL; ... when != res == NULL e = devm_ioremap(e1, res->start, e2); Signed-off-by: Wei Yongjun Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- drivers/net/phy/mdio-bcm-unimac.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/phy/mdio-bcm-unimac.c b/drivers/net/phy/mdio-bcm-unimac.c index 52703bbd4d66..df75efa96a7d 100644 --- a/drivers/net/phy/mdio-bcm-unimac.c +++ b/drivers/net/phy/mdio-bcm-unimac.c @@ -237,6 +237,8 @@ static int unimac_mdio_probe(struct platform_device *pdev) return -ENOMEM; r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!r) + return -EINVAL; /* Just ioremap, as this MDIO block is usually integrated into an * Ethernet MAC controller register range From a42f149865da48f25e5a49ca344dbcad61b66ae1 Mon Sep 17 00:00:00 2001 From: Navid Emamdoost Date: Thu, 19 Sep 2019 11:04:48 -0500 Subject: [PATCH 375/592] crypto: ccp - Release all allocated memory if sha type is invalid [ Upstream commit 128c66429247add5128c03dc1e144ca56f05a4e2 ] Release all allocated memory if sha type is invalid: In ccp_run_sha_cmd, if the type of sha is invalid, the allocated hmac_buf should be released. v2: fix the goto. Signed-off-by: Navid Emamdoost Acked-by: Gary R Hook Signed-off-by: Herbert Xu Signed-off-by: Sasha Levin --- drivers/crypto/ccp/ccp-ops.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/ccp/ccp-ops.c b/drivers/crypto/ccp/ccp-ops.c index 330853a2702f..43b74cf0787e 100644 --- a/drivers/crypto/ccp/ccp-ops.c +++ b/drivers/crypto/ccp/ccp-ops.c @@ -1783,8 +1783,9 @@ ccp_run_sha_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) LSB_ITEM_SIZE); break; default: + kfree(hmac_buf); ret = -EINVAL; - goto e_ctx; + goto e_data; } memset(&hmac_cmd, 0, sizeof(hmac_cmd)); From 12273ec840cc67b2ec469ee5f5214559357436bb Mon Sep 17 00:00:00 2001 From: Navid Emamdoost Date: Wed, 25 Sep 2019 12:02:41 -0300 Subject: [PATCH 376/592] media: rc: prevent memory leak in cx23888_ir_probe [ Upstream commit a7b2df76b42bdd026e3106cf2ba97db41345a177 ] In cx23888_ir_probe if kfifo_alloc fails the allocated memory for state should be released. Signed-off-by: Navid Emamdoost Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Sasha Levin --- drivers/media/pci/cx23885/cx23888-ir.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/media/pci/cx23885/cx23888-ir.c b/drivers/media/pci/cx23885/cx23888-ir.c index 040323b0f945..f63a7e6f272c 100644 --- a/drivers/media/pci/cx23885/cx23888-ir.c +++ b/drivers/media/pci/cx23885/cx23888-ir.c @@ -1178,8 +1178,11 @@ int cx23888_ir_probe(struct cx23885_dev *dev) return -ENOMEM; spin_lock_init(&state->rx_kfifo_lock); - if (kfifo_alloc(&state->rx_kfifo, CX23888_IR_RX_KFIFO_SIZE, GFP_KERNEL)) + if (kfifo_alloc(&state->rx_kfifo, CX23888_IR_RX_KFIFO_SIZE, + GFP_KERNEL)) { + kfree(state); return -ENOMEM; + } state->dev = dev; sd = &state->sd; From 8d75cc141d702ebc280dde2b32b50cfdea3a02b3 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Thu, 30 Jul 2020 19:14:12 -0400 Subject: [PATCH 377/592] iio: imu: adis16400: fix memory leak [ Upstream commit 9c0530e898f384c5d279bfcebd8bb17af1105873 ] In adis_update_scan_mode_burst, if adis->buffer allocation fails release the adis->xfer. Signed-off-by: Navid Emamdoost Reviewed-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron Signed-off-by: Sasha Levin --- drivers/iio/imu/adis16400_buffer.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/iio/imu/adis16400_buffer.c b/drivers/iio/imu/adis16400_buffer.c index e70a5339acb1..3fc11aec98b9 100644 --- a/drivers/iio/imu/adis16400_buffer.c +++ b/drivers/iio/imu/adis16400_buffer.c @@ -38,8 +38,11 @@ int adis16400_update_scan_mode(struct iio_dev *indio_dev, return -ENOMEM; adis->buffer = kzalloc(burst_length + sizeof(u16), GFP_KERNEL); - if (!adis->buffer) + if (!adis->buffer) { + kfree(adis->xfer); + adis->xfer = NULL; return -ENOMEM; + } tx = adis->buffer + burst_length; tx[0] = ADIS_READ_REG(ADIS16400_GLOB_CMD); From 5502de13f91db625b063cb9d0793c7391f38452d Mon Sep 17 00:00:00 2001 From: Navid Emamdoost Date: Fri, 6 Sep 2019 13:26:03 -0500 Subject: [PATCH 378/592] ath9k_htc: release allocated buffer if timed out [ Upstream commit 853acf7caf10b828102d92d05b5c101666a6142b ] In htc_config_pipe_credits, htc_setup_complete, and htc_connect_service if time out happens, the allocated buffer needs to be released. Otherwise there will be memory leak. Signed-off-by: Navid Emamdoost Signed-off-by: Kalle Valo Signed-off-by: Sasha Levin --- drivers/net/wireless/ath/ath9k/htc_hst.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c index d2e062eaf561..f705f0e1cb5b 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.c +++ b/drivers/net/wireless/ath/ath9k/htc_hst.c @@ -173,6 +173,7 @@ static int htc_config_pipe_credits(struct htc_target *target) time_left = wait_for_completion_timeout(&target->cmd_wait, HZ); if (!time_left) { dev_err(target->dev, "HTC credit config timeout\n"); + kfree_skb(skb); return -ETIMEDOUT; } @@ -208,6 +209,7 @@ static int htc_setup_complete(struct htc_target *target) time_left = wait_for_completion_timeout(&target->cmd_wait, HZ); if (!time_left) { dev_err(target->dev, "HTC start timeout\n"); + kfree_skb(skb); return -ETIMEDOUT; } @@ -280,6 +282,7 @@ int htc_connect_service(struct htc_target *target, if (!time_left) { dev_err(target->dev, "Service connection timeout for: %d\n", service_connreq->service_id); + kfree_skb(skb); return -ETIMEDOUT; } From 83c212df7794563a2f45a3be8fbc097e352b2c3a Mon Sep 17 00:00:00 2001 From: Navid Emamdoost Date: Fri, 6 Sep 2019 13:59:30 -0500 Subject: [PATCH 379/592] ath9k: release allocated buffer if timed out [ Upstream commit 728c1e2a05e4b5fc52fab3421dce772a806612a2 ] In ath9k_wmi_cmd, the allocated network buffer needs to be released if timeout happens. Otherwise memory will be leaked. Signed-off-by: Navid Emamdoost Signed-off-by: Kalle Valo Signed-off-by: Sasha Levin --- drivers/net/wireless/ath/ath9k/wmi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c index f57f48e4d7a0..4b68804f3742 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ b/drivers/net/wireless/ath/ath9k/wmi.c @@ -338,6 +338,7 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id, ath_dbg(common, WMI, "Timeout waiting for WMI command: %s\n", wmi_cmd_to_name(cmd_id)); mutex_unlock(&wmi->op_mutex); + kfree_skb(skb); return -ETIMEDOUT; } From fd4a641bb5731c0ce5397698560a823602dbaac2 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Thu, 30 Jul 2020 19:33:48 -0400 Subject: [PATCH 380/592] x86/kvm: Be careful not to clear KVM_VCPU_FLUSH_TLB bit [ Upstream commit 8c6de56a42e0c657955e12b882a81ef07d1d073e ] kvm_steal_time_set_preempted() may accidentally clear KVM_VCPU_FLUSH_TLB bit if it is called more than once while VCPU is preempted. This is part of CVE-2019-3016. (This bug was also independently discovered by Jim Mattson ) Signed-off-by: Boris Ostrovsky Reviewed-by: Joao Martins Cc: stable@vger.kernel.org Signed-off-by: Paolo Bonzini Signed-off-by: Sasha Levin --- arch/x86/kvm/x86.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 09f47c837c25..3aed03942d7d 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -3075,6 +3075,9 @@ static void kvm_steal_time_set_preempted(struct kvm_vcpu *vcpu) if (!(vcpu->arch.st.msr_val & KVM_MSR_ENABLED)) return; + if (vcpu->arch.st.steal.preempted) + return; + vcpu->arch.st.steal.preempted = 1; kvm_write_guest_offset_cached(vcpu->kvm, &vcpu->arch.st.stime, From 99c0a2671044fe6c857fcbd24a595e050d98f64a Mon Sep 17 00:00:00 2001 From: Robert Hancock Date: Tue, 21 Jul 2020 20:18:03 -0600 Subject: [PATCH 381/592] PCI/ASPM: Disable ASPM on ASMedia ASM1083/1085 PCIe-to-PCI bridge commit b361663c5a40c8bc758b7f7f2239f7a192180e7c upstream. Recently ASPM handling was changed to allow ASPM on PCIe-to-PCI/PCI-X bridges. Unfortunately the ASMedia ASM1083/1085 PCIe to PCI bridge device doesn't seem to function properly with ASPM enabled. On an Asus PRIME H270-PRO motherboard, it causes errors like these: pcieport 0000:00:1c.0: AER: PCIe Bus Error: severity=Corrected, type=Data Link Layer, (Transmitter ID) pcieport 0000:00:1c.0: AER: device [8086:a292] error status/mask=00003000/00002000 pcieport 0000:00:1c.0: AER: [12] Timeout pcieport 0000:00:1c.0: AER: Corrected error received: 0000:00:1c.0 pcieport 0000:00:1c.0: AER: can't find device of ID00e0 In addition to flooding the kernel log, this also causes the machine to wake up immediately after suspend is initiated. The device advertises ASPM L0s and L1 support in the Link Capabilities register, but the ASMedia web page for ASM1083 [1] claims "No PCIe ASPM support". Windows 10 (build 2004) enables L0s, but it also logs correctable PCIe errors. Add a quirk to disable ASPM for this device. [1] https://www.asmedia.com.tw/eng/e_show_products.php?cate_index=169&item=114 [bhelgaas: commit log] Fixes: 66ff14e59e8a ("PCI/ASPM: Allow ASPM on links to PCIe-to-PCI/PCI-X Bridges") Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=208667 Link: https://lore.kernel.org/r/20200722021803.17958-1-hancockrwd@gmail.com Signed-off-by: Robert Hancock Signed-off-by: Bjorn Helgaas Signed-off-by: Greg Kroah-Hartman --- drivers/pci/quirks.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 5f26c170315c..243b16ce0c8e 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2086,6 +2086,19 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10f1, quirk_disable_aspm_l0s); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10f4, quirk_disable_aspm_l0s); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1508, quirk_disable_aspm_l0s); +static void quirk_disable_aspm_l0s_l1(struct pci_dev *dev) +{ + pci_info(dev, "Disabling ASPM L0s/L1\n"); + pci_disable_link_state(dev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1); +} + +/* + * ASM1083/1085 PCIe-PCI bridge devices cause AER timeout errors on the + * upstream PCIe root port when ASPM is enabled. At least L0s mode is affected; + * disable both L0s and L1 for now to be safe. + */ +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ASMEDIA, 0x1080, quirk_disable_aspm_l0s_l1); + /* * Some Pericom PCIe-to-PCI bridges in reverse mode need the PCIe Retrain * Link bit cleared after starting the link retrain process to allow this From f4169c4e91eb0f33a17e8c5c3bcbd6244166e697 Mon Sep 17 00:00:00 2001 From: Pi-Hsun Shih Date: Wed, 4 Dec 2019 16:13:07 +0800 Subject: [PATCH 382/592] wireless: Use offsetof instead of custom macro. commit 6989310f5d4327e8595664954edd40a7f99ddd0d upstream. Use offsetof to calculate offset of a field to take advantage of compiler built-in version when possible, and avoid UBSAN warning when compiling with Clang: ================================================================== UBSAN: Undefined behaviour in net/wireless/wext-core.c:525:14 member access within null pointer of type 'struct iw_point' CPU: 3 PID: 165 Comm: kworker/u16:3 Tainted: G S W 4.19.23 #43 Workqueue: cfg80211 __cfg80211_scan_done [cfg80211] Call trace: dump_backtrace+0x0/0x194 show_stack+0x20/0x2c __dump_stack+0x20/0x28 dump_stack+0x70/0x94 ubsan_epilogue+0x14/0x44 ubsan_type_mismatch_common+0xf4/0xfc __ubsan_handle_type_mismatch_v1+0x34/0x54 wireless_send_event+0x3cc/0x470 ___cfg80211_scan_done+0x13c/0x220 [cfg80211] __cfg80211_scan_done+0x28/0x34 [cfg80211] process_one_work+0x170/0x35c worker_thread+0x254/0x380 kthread+0x13c/0x158 ret_from_fork+0x10/0x18 =================================================================== Signed-off-by: Pi-Hsun Shih Reviewed-by: Nick Desaulniers Link: https://lore.kernel.org/r/20191204081307.138765-1-pihsun@chromium.org Signed-off-by: Johannes Berg Signed-off-by: Nick Desaulniers Signed-off-by: Greg Kroah-Hartman --- include/uapi/linux/wireless.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/uapi/linux/wireless.h b/include/uapi/linux/wireless.h index 86eca3208b6b..a2c006a364e0 100644 --- a/include/uapi/linux/wireless.h +++ b/include/uapi/linux/wireless.h @@ -74,6 +74,8 @@ #include /* for "struct sockaddr" et al */ #include /* for IFNAMSIZ and co... */ +#include /* for offsetof */ + /***************************** VERSION *****************************/ /* * This constant is used to know the availability of the wireless @@ -1090,8 +1092,7 @@ struct iw_event { /* iw_point events are special. First, the payload (extra data) come at * the end of the event, so they are bigger than IW_EV_POINT_LEN. Second, * we omit the pointer, so start at an offset. */ -#define IW_EV_POINT_OFF (((char *) &(((struct iw_point *) NULL)->length)) - \ - (char *) NULL) +#define IW_EV_POINT_OFF offsetof(struct iw_point, length) #define IW_EV_POINT_LEN (IW_EV_LCP_LEN + sizeof(struct iw_point) - \ IW_EV_POINT_OFF) From 46ee09819f35272a7107ca06a5b577ebf03f7326 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Thu, 18 Jun 2020 11:16:45 +0100 Subject: [PATCH 383/592] ARM: 8986/1: hw_breakpoint: Don't invoke overflow handler on uaccess watchpoints commit eec13b42d41b0f3339dcf0c4da43734427c68620 upstream. Unprivileged memory accesses generated by the so-called "translated" instructions (e.g. LDRT) in kernel mode can cause user watchpoints to fire unexpectedly. In such cases, the hw_breakpoint logic will invoke the user overflow handler which will typically raise a SIGTRAP back to the current task. This is futile when returning back to the kernel because (a) the signal won't have been delivered and (b) userspace can't handle the thing anyway. Avoid invoking the user overflow handler for watchpoints triggered by kernel uaccess routines, and instead single-step over the faulting instruction as we would if no overflow handler had been installed. Cc: Fixes: f81ef4a920c8 ("ARM: 6356/1: hw-breakpoint: add ARM backend for the hw-breakpoint framework") Reported-by: Luis Machado Tested-by: Luis Machado Signed-off-by: Will Deacon Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/kernel/hw_breakpoint.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c index af2a7f1e3103..a30f656f791f 100644 --- a/arch/arm/kernel/hw_breakpoint.c +++ b/arch/arm/kernel/hw_breakpoint.c @@ -688,6 +688,12 @@ static void disable_single_step(struct perf_event *bp) arch_install_hw_breakpoint(bp); } +static int watchpoint_fault_on_uaccess(struct pt_regs *regs, + struct arch_hw_breakpoint *info) +{ + return !user_mode(regs) && info->ctrl.privilege == ARM_BREAKPOINT_USER; +} + static void watchpoint_handler(unsigned long addr, unsigned int fsr, struct pt_regs *regs) { @@ -747,16 +753,27 @@ static void watchpoint_handler(unsigned long addr, unsigned int fsr, } pr_debug("watchpoint fired: address = 0x%x\n", info->trigger); + + /* + * If we triggered a user watchpoint from a uaccess routine, + * then handle the stepping ourselves since userspace really + * can't help us with this. + */ + if (watchpoint_fault_on_uaccess(regs, info)) + goto step; + perf_bp_event(wp, regs); /* - * If no overflow handler is present, insert a temporary - * mismatch breakpoint so we can single-step over the - * watchpoint trigger. + * Defer stepping to the overflow handler if one is installed. + * Otherwise, insert a temporary mismatch breakpoint so that + * we can single-step over the watchpoint trigger. */ - if (is_default_overflow_handler(wp)) - enable_single_step(wp, instruction_pointer(regs)); + if (!is_default_overflow_handler(wp)) + goto unlock; +step: + enable_single_step(wp, instruction_pointer(regs)); unlock: rcu_read_unlock(); } From 2fda665f0a26bd60e091f9162495f128896aa531 Mon Sep 17 00:00:00 2001 From: Peilin Ye Date: Tue, 28 Jul 2020 15:29:24 -0400 Subject: [PATCH 384/592] drm/amdgpu: Prevent kernel-infoleak in amdgpu_info_ioctl() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 543e8669ed9bfb30545fd52bc0e047ca4df7fb31 upstream. Compiler leaves a 4-byte hole near the end of `dev_info`, causing amdgpu_info_ioctl() to copy uninitialized kernel stack memory to userspace when `size` is greater than 356. In 2015 we tried to fix this issue by doing `= {};` on `dev_info`, which unfortunately does not initialize that 4-byte hole. Fix it by using memset() instead. Cc: stable@vger.kernel.org Fixes: c193fa91b918 ("drm/amdgpu: information leak in amdgpu_info_ioctl()") Fixes: d38ceaf99ed0 ("drm/amdgpu: add core driver (v4)") Suggested-by: Dan Carpenter Reviewed-by: Christian König Signed-off-by: Peilin Ye Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index c93e72d8ac5f..22d9ec80a2ff 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -527,8 +527,9 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file return n ? -EFAULT : 0; } case AMDGPU_INFO_DEV_INFO: { - struct drm_amdgpu_info_device dev_info = {}; + struct drm_amdgpu_info_device dev_info; + memset(&dev_info, 0, sizeof(dev_info)); dev_info.device_id = dev->pdev->device; dev_info.chip_rev = adev->rev_id; dev_info.external_rev = adev->external_rev_id; From 00cf08b009e56555e69b5d9d307577856a9a0114 Mon Sep 17 00:00:00 2001 From: Steve Cohen Date: Mon, 20 Jul 2020 18:30:50 -0400 Subject: [PATCH 385/592] drm: hold gem reference until object is no longer accessed commit 8490d6a7e0a0a6fab5c2d82d57a3937306660864 upstream. A use-after-free in drm_gem_open_ioctl can happen if the GEM object handle is closed between the idr lookup and retrieving the size from said object since a local reference is not being held at that point. Hold the local reference while the object can still be accessed to fix this and plug the potential security hole. Signed-off-by: Steve Cohen Cc: stable@vger.kernel.org Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/1595284250-31580-1-git-send-email-cohens@codeaurora.org Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/drm_gem.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index d2c042af36b8..470a79eef254 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -730,9 +730,6 @@ err: * @file_priv: drm file-private structure * * Open an object using the global name, returning a handle and the size. - * - * This handle (of course) holds a reference to the object, so the object - * will not go away until the handle is deleted. */ int drm_gem_open_ioctl(struct drm_device *dev, void *data, @@ -757,14 +754,15 @@ drm_gem_open_ioctl(struct drm_device *dev, void *data, /* drm_gem_handle_create_tail unlocks dev->object_name_lock. */ ret = drm_gem_handle_create_tail(file_priv, obj, &handle); - drm_gem_object_put_unlocked(obj); if (ret) - return ret; + goto err; args->handle = handle; args->size = obj->size; - return 0; +err: + drm_gem_object_put_unlocked(obj); + return ret; } /** From bc08d46f010ccf05817c0f53ba4226de20645a36 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Wed, 14 Nov 2018 12:40:30 -0800 Subject: [PATCH 386/592] f2fs: check memory boundary by insane namelen [ Upstream commit 4e240d1bab1ead280ddf5eb05058dba6bbd57d10 ] If namelen is corrupted to have very long value, fill_dentries can copy wrong memory area. Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim Signed-off-by: Sasha Levin --- fs/f2fs/dir.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c index 4abefd841b6c..7a177b8f227d 100644 --- a/fs/f2fs/dir.c +++ b/fs/f2fs/dir.c @@ -817,6 +817,16 @@ int f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d, de_name.name = d->filename[bit_pos]; de_name.len = le16_to_cpu(de->name_len); + /* check memory boundary before moving forward */ + bit_pos += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len)); + if (unlikely(bit_pos > d->max)) { + f2fs_msg(F2FS_I_SB(d->inode)->sb, KERN_WARNING, + "%s: corrupted namelen=%d, run fsck to fix.", + __func__, le16_to_cpu(de->name_len)); + set_sbi_flag(F2FS_I_SB(d->inode)->sb->s_fs_info, SBI_NEED_FSCK); + return -EINVAL; + } + if (f2fs_encrypted_inode(d->inode)) { int save_len = fstr->len; int err; @@ -835,7 +845,6 @@ int f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d, le32_to_cpu(de->ino), d_type)) return 1; - bit_pos += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len)); ctx->pos = start_pos + bit_pos; } return 0; From 6a27f426266ac0d29faa95bed8934afeef1f9d13 Mon Sep 17 00:00:00 2001 From: Sheng Yong Date: Mon, 7 Jan 2019 15:02:34 +0800 Subject: [PATCH 387/592] f2fs: check if file namelen exceeds max value [ Upstream commit 720db068634c91553a8e1d9a0fcd8c7050e06d2b ] Dentry bitmap is not enough to detect incorrect dentries. So this patch also checks the namelen value of a dentry. Signed-off-by: Gong Chen Signed-off-by: Sheng Yong Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim Signed-off-by: Sasha Levin --- fs/f2fs/dir.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c index 7a177b8f227d..ff519f7a8784 100644 --- a/fs/f2fs/dir.c +++ b/fs/f2fs/dir.c @@ -819,7 +819,8 @@ int f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d, /* check memory boundary before moving forward */ bit_pos += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len)); - if (unlikely(bit_pos > d->max)) { + if (unlikely(bit_pos > d->max || + le16_to_cpu(de->name_len) > F2FS_NAME_LEN)) { f2fs_msg(F2FS_I_SB(d->inode)->sb, KERN_WARNING, "%s: corrupted namelen=%d, run fsck to fix.", __func__, le16_to_cpu(de->name_len)); From d1f7217b7a75cb7f59b295d7ceab1776a0affe95 Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Tue, 9 Oct 2018 11:18:52 +0900 Subject: [PATCH 388/592] 9p/trans_fd: abort p9_read_work if req status changed [ Upstream commit e4ca13f7d075e551dc158df6af18fb412a1dba0a ] p9_read_work would try to handle an errored req even if it got put to error state by another thread between the lookup (that worked) and the time it had been fully read. The request itself is safe to use because we hold a ref to it from the lookup (for m->rreq, so it was safe to read into the request data buffer until this point), but the req_list has been deleted at the same time status changed, and client_cb already has been called as well, so we should not do either. Link: http://lkml.kernel.org/r/1539057956-23741-1-git-send-email-asmadeus@codewreck.org Signed-off-by: Dominique Martinet Reported-by: syzbot+2222c34dc40b515f30dc@syzkaller.appspotmail.com Cc: Eric Van Hensbergen Cc: Latchesar Ionkov Signed-off-by: Sasha Levin --- net/9p/trans_fd.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index a9c65f13b7f5..cbd8cfafb794 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c @@ -301,7 +301,6 @@ static void p9_read_work(struct work_struct *work) { int n, err; struct p9_conn *m; - int status = REQ_STATUS_ERROR; m = container_of(work, struct p9_conn, rq); @@ -381,11 +380,17 @@ static void p9_read_work(struct work_struct *work) if ((m->req) && (m->rc.offset == m->rc.capacity)) { p9_debug(P9_DEBUG_TRANS, "got new packet\n"); spin_lock(&m->client->lock); - if (m->req->status != REQ_STATUS_ERROR) - status = REQ_STATUS_RCVD; - list_del(&m->req->req_list); - /* update req->status while holding client->lock */ - p9_client_cb(m->client, m->req, status); + if (m->req->status == REQ_STATUS_SENT) { + list_del(&m->req->req_list); + p9_client_cb(m->client, m->req, REQ_STATUS_RCVD); + } else { + spin_unlock(&m->client->lock); + p9_debug(P9_DEBUG_ERROR, + "Request tag %d errored out while we were reading the reply\n", + m->rc.tag); + err = -EIO; + goto error; + } spin_unlock(&m->client->lock); m->rc.sdata = NULL; m->rc.offset = 0; From 019221c5e5152b6417e7cd8bb98417fe9719fc4c Mon Sep 17 00:00:00 2001 From: Wang Hai Date: Fri, 12 Jun 2020 17:08:33 +0800 Subject: [PATCH 389/592] 9p/trans_fd: Fix concurrency del of req_list in p9_fd_cancelled/p9_read_work [ Upstream commit 74d6a5d5662975aed7f25952f62efbb6f6dadd29 ] p9_read_work and p9_fd_cancelled may be called concurrently. In some cases, req->req_list may be deleted by both p9_read_work and p9_fd_cancelled. We can fix it by ignoring replies associated with a cancelled request and ignoring cancelled request if message has been received before lock. Link: http://lkml.kernel.org/r/20200612090833.36149-1-wanghai38@huawei.com Fixes: 60ff779c4abb ("9p: client: remove unused code and any reference to "cancelled" function") Cc: # v3.12+ Reported-by: syzbot+77a25acfa0382e06ab23@syzkaller.appspotmail.com Signed-off-by: Wang Hai Signed-off-by: Dominique Martinet Signed-off-by: Sasha Levin --- net/9p/trans_fd.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index cbd8cfafb794..32de8afbfbf8 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c @@ -383,6 +383,10 @@ static void p9_read_work(struct work_struct *work) if (m->req->status == REQ_STATUS_SENT) { list_del(&m->req->req_list); p9_client_cb(m->client, m->req, REQ_STATUS_RCVD); + } else if (m->req->status == REQ_STATUS_FLSHD) { + /* Ignore replies associated with a cancelled request. */ + p9_debug(P9_DEBUG_TRANS, + "Ignore replies associated with a cancelled request\n"); } else { spin_unlock(&m->client->lock); p9_debug(P9_DEBUG_ERROR, @@ -717,11 +721,20 @@ static int p9_fd_cancelled(struct p9_client *client, struct p9_req_t *req) { p9_debug(P9_DEBUG_TRANS, "client %p req %p\n", client, req); + spin_lock(&client->lock); + /* Ignore cancelled request if message has been received + * before lock. + */ + if (req->status == REQ_STATUS_RCVD) { + spin_unlock(&client->lock); + return 0; + } + /* we haven't received a response for oldreq, * remove it from the list. */ - spin_lock(&client->lock); list_del(&req->req_list); + req->status = REQ_STATUS_FLSHD; spin_unlock(&client->lock); return 0; From 53993bba307dbfaaaa04b52888081114a77e72bf Mon Sep 17 00:00:00 2001 From: Sami Tolvanen Date: Mon, 15 Apr 2019 09:49:56 -0700 Subject: [PATCH 390/592] x86/build/lto: Fix truncated .bss with -fdata-sections [ Upstream commit 6a03469a1edc94da52b65478f1e00837add869a3 ] With CONFIG_LD_DEAD_CODE_DATA_ELIMINATION=y, we compile the kernel with -fdata-sections, which also splits the .bss section. The new section, with a new .bss.* name, which pattern gets missed by the main x86 linker script which only expects the '.bss' name. This results in the discarding of the second part and a too small, truncated .bss section and an unhappy, non-working kernel. Use the common BSS_MAIN macro in the linker script to properly capture and merge all the generated BSS sections. Signed-off-by: Sami Tolvanen Reviewed-by: Nick Desaulniers Reviewed-by: Kees Cook Cc: Borislav Petkov Cc: Kees Cook Cc: Linus Torvalds Cc: Nicholas Piggin Cc: Nick Desaulniers Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/20190415164956.124067-1-samitolvanen@google.com [ Extended the changelog. ] Signed-off-by: Ingo Molnar Signed-off-by: Sasha Levin --- arch/x86/kernel/vmlinux.lds.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S index 8d8e33b720b4..f9f33a168a00 100644 --- a/arch/x86/kernel/vmlinux.lds.S +++ b/arch/x86/kernel/vmlinux.lds.S @@ -352,7 +352,7 @@ SECTIONS .bss : AT(ADDR(.bss) - LOAD_OFFSET) { __bss_start = .; *(.bss..page_aligned) - *(.bss) + *(BSS_MAIN) . = ALIGN(PAGE_SIZE); __bss_stop = .; } From 88f3814ffed51b37bda02642a3f93f8a979fb6e2 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Tue, 21 Jul 2020 11:34:48 +0200 Subject: [PATCH 391/592] x86, vmlinux.lds: Page-align end of ..page_aligned sections [ Upstream commit de2b41be8fcccb2f5b6c480d35df590476344201 ] On x86-32 the idt_table with 256 entries needs only 2048 bytes. It is page-aligned, but the end of the .bss..page_aligned section is not guaranteed to be page-aligned. As a result, objects from other .bss sections may end up on the same 4k page as the idt_table, and will accidentially get mapped read-only during boot, causing unexpected page-faults when the kernel writes to them. This could be worked around by making the objects in the page aligned sections page sized, but that's wrong. Explicit sections which store only page aligned objects have an implicit guarantee that the object is alone in the page in which it is placed. That works for all objects except the last one. That's inconsistent. Enforcing page sized objects for these sections would wreckage memory sanitizers, because the object becomes artificially larger than it should be and out of bound access becomes legit. Align the end of the .bss..page_aligned and .data..page_aligned section on page-size so all objects places in these sections are guaranteed to have their own page. [ tglx: Amended changelog ] Signed-off-by: Joerg Roedel Signed-off-by: Thomas Gleixner Reviewed-by: Kees Cook Cc: stable@vger.kernel.org Link: https://lkml.kernel.org/r/20200721093448.10417-1-joro@8bytes.org Signed-off-by: Sasha Levin --- arch/x86/kernel/vmlinux.lds.S | 1 + include/asm-generic/vmlinux.lds.h | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S index f9f33a168a00..d3dc8bc6b3ad 100644 --- a/arch/x86/kernel/vmlinux.lds.S +++ b/arch/x86/kernel/vmlinux.lds.S @@ -352,6 +352,7 @@ SECTIONS .bss : AT(ADDR(.bss) - LOAD_OFFSET) { __bss_start = .; *(.bss..page_aligned) + . = ALIGN(PAGE_SIZE); *(BSS_MAIN) . = ALIGN(PAGE_SIZE); __bss_stop = .; diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index c229ffbed6d4..48e618b20d34 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -251,7 +251,8 @@ #define PAGE_ALIGNED_DATA(page_align) \ . = ALIGN(page_align); \ - *(.data..page_aligned) + *(.data..page_aligned) \ + . = ALIGN(page_align); #define READ_MOSTLY_DATA(align) \ . = ALIGN(align); \ @@ -619,7 +620,9 @@ . = ALIGN(bss_align); \ .bss : AT(ADDR(.bss) - LOAD_OFFSET) { \ BSS_FIRST_SECTIONS \ + . = ALIGN(PAGE_SIZE); \ *(.bss..page_aligned) \ + . = ALIGN(PAGE_SIZE); \ *(.dynbss) \ *(BSS_MAIN) \ *(COMMON) \ From 4b49b16999d4f875d1ba3bdf9e8e001d64b08d5e Mon Sep 17 00:00:00 2001 From: Peilin Ye Date: Thu, 30 Jul 2020 15:20:26 -0400 Subject: [PATCH 392/592] rds: Prevent kernel-infoleak in rds_notify_queue_get() commit bbc8a99e952226c585ac17477a85ef1194501762 upstream. rds_notify_queue_get() is potentially copying uninitialized kernel stack memory to userspace since the compiler may leave a 4-byte hole at the end of `cmsg`. In 2016 we tried to fix this issue by doing `= { 0 };` on `cmsg`, which unfortunately does not always initialize that 4-byte hole. Fix it by using memset() instead. Cc: stable@vger.kernel.org Fixes: f037590fff30 ("rds: fix a leak of kernel memory") Fixes: bdbe6fbc6a2f ("RDS: recv.c") Suggested-by: Dan Carpenter Signed-off-by: Peilin Ye Acked-by: Santosh Shilimkar Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/rds/recv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/rds/recv.c b/net/rds/recv.c index c27cceae52e1..ef022d24f87a 100644 --- a/net/rds/recv.c +++ b/net/rds/recv.c @@ -453,12 +453,13 @@ static int rds_still_queued(struct rds_sock *rs, struct rds_incoming *inc, int rds_notify_queue_get(struct rds_sock *rs, struct msghdr *msghdr) { struct rds_notifier *notifier; - struct rds_rdma_notify cmsg = { 0 }; /* fill holes with zero */ + struct rds_rdma_notify cmsg; unsigned int count = 0, max_messages = ~0U; unsigned long flags; LIST_HEAD(copy); int err = 0; + memset(&cmsg, 0, sizeof(cmsg)); /* fill holes with zero */ /* put_cmsg copies to user space and thus may sleep. We can't do this * with rs_lock held, so first grab as many notifications as we can stuff From 880e98b1abec52b23e9481312596d54dfa614bcd Mon Sep 17 00:00:00 2001 From: Rik van Riel Date: Thu, 5 Sep 2019 17:32:48 -0700 Subject: [PATCH 393/592] xfs: fix missed wakeup on l_flush_wait commit cdea5459ce263fbc963657a7736762ae897a8ae6 upstream. The code in xlog_wait uses the spinlock to make adding the task to the wait queue, and setting the task state to UNINTERRUPTIBLE atomic with respect to the waker. Doing the wakeup after releasing the spinlock opens up the following race condition: Task 1 task 2 add task to wait queue wake up task set task state to UNINTERRUPTIBLE This issue was found through code inspection as a result of kworkers being observed stuck in UNINTERRUPTIBLE state with an empty wait queue. It is rare and largely unreproducable. Simply moving the spin_unlock to after the wake_up_all results in the waker not being able to see a task on the waitqueue before it has set its state to UNINTERRUPTIBLE. This bug dates back to the conversion of this code to generic waitqueue infrastructure from a counting semaphore back in 2008 which didn't place the wakeups consistently w.r.t. to the relevant spin locks. [dchinner: Also fix a similar issue in the shutdown path on xc_commit_wait. Update commit log with more details of the issue.] Fixes: d748c62367eb ("[XFS] Convert l_flushsema to a sv_t") Reported-by: Chris Mason Signed-off-by: Rik van Riel Signed-off-by: Dave Chinner Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong Cc: stable@vger.kernel.org # 4.9.x-4.19.x [modified for contextual change near xlog_state_do_callback()] Signed-off-by: Samuel Mendoza-Jonas Reviewed-by: Frank van der Linden Reviewed-by: Suraj Jitindar Singh Reviewed-by: Benjamin Herrenschmidt Reviewed-by: Anchal Agarwal Signed-off-by: Greg Kroah-Hartman --- fs/xfs/xfs_log.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 360e32220f93..0c0f70e6c7d9 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c @@ -2684,7 +2684,6 @@ xlog_state_do_callback( int funcdidcallbacks; /* flag: function did callbacks */ int repeats; /* for issuing console warnings if * looping too many times */ - int wake = 0; spin_lock(&log->l_icloglock); first_iclog = iclog = log->l_iclog; @@ -2886,11 +2885,9 @@ xlog_state_do_callback( #endif if (log->l_iclog->ic_state & (XLOG_STATE_ACTIVE|XLOG_STATE_IOERROR)) - wake = 1; - spin_unlock(&log->l_icloglock); - - if (wake) wake_up_all(&log->l_flush_wait); + + spin_unlock(&log->l_icloglock); } @@ -4052,7 +4049,9 @@ xfs_log_force_umount( * item committed callback functions will do this again under lock to * avoid races. */ + spin_lock(&log->l_cilp->xc_push_lock); wake_up_all(&log->l_cilp->xc_commit_wait); + spin_unlock(&log->l_cilp->xc_push_lock); xlog_state_do_callback(log, XFS_LI_ABORTED, NULL); #ifdef XFSERRORDEBUG From f0b6ce595c397a91d5b62c6b0b5ea93b84191795 Mon Sep 17 00:00:00 2001 From: Xiyu Yang Date: Sat, 25 Apr 2020 21:06:25 +0800 Subject: [PATCH 394/592] net/x25: Fix x25_neigh refcnt leak when x25 disconnect commit 4becb7ee5b3d2829ed7b9261a245a77d5b7de902 upstream. x25_connect() invokes x25_get_neigh(), which returns a reference of the specified x25_neigh object to "x25->neighbour" with increased refcnt. When x25 connect success and returns, the reference still be hold by "x25->neighbour", so the refcount should be decreased in x25_disconnect() to keep refcount balanced. The reference counting issue happens in x25_disconnect(), which forgets to decrease the refcnt increased by x25_get_neigh() in x25_connect(), causing a refcnt leak. Fix this issue by calling x25_neigh_put() before x25_disconnect() returns. Signed-off-by: Xiyu Yang Signed-off-by: Xin Tan Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/x25/x25_subr.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/x25/x25_subr.c b/net/x25/x25_subr.c index db0b1315d577..27c5885c14ef 100644 --- a/net/x25/x25_subr.c +++ b/net/x25/x25_subr.c @@ -363,6 +363,10 @@ void x25_disconnect(struct sock *sk, int reason, unsigned char cause, sk->sk_state_change(sk); sock_set_flag(sk, SOCK_DEAD); } + read_lock_bh(&x25_list_lock); + x25_neigh_put(x25->neighbour); + x25->neighbour = NULL; + read_unlock_bh(&x25_list_lock); } /* From f2bfdab9ae92cac7b18556bc8507c98017d6a1ad Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Tue, 28 Apr 2020 16:12:08 +0800 Subject: [PATCH 395/592] net/x25: Fix null-ptr-deref in x25_disconnect commit 8999dc89497ab1c80d0718828e838c7cd5f6bffe upstream. We should check null before do x25_neigh_put in x25_disconnect, otherwise may cause null-ptr-deref like this: #include #include int main() { int sck_x25; sck_x25 = socket(AF_X25, SOCK_SEQPACKET, 0); close(sck_x25); return 0; } BUG: kernel NULL pointer dereference, address: 00000000000000d8 CPU: 0 PID: 4817 Comm: t2 Not tainted 5.7.0-rc3+ #159 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.9.3- RIP: 0010:x25_disconnect+0x91/0xe0 Call Trace: x25_release+0x18a/0x1b0 __sock_release+0x3d/0xc0 sock_close+0x13/0x20 __fput+0x107/0x270 ____fput+0x9/0x10 task_work_run+0x6d/0xb0 exit_to_usermode_loop+0x102/0x110 do_syscall_64+0x23c/0x260 entry_SYSCALL_64_after_hwframe+0x49/0xb3 Reported-by: syzbot+6db548b615e5aeefdce2@syzkaller.appspotmail.com Fixes: 4becb7ee5b3d ("net/x25: Fix x25_neigh refcnt leak when x25 disconnect") Signed-off-by: YueHaibing Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/x25/x25_subr.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/net/x25/x25_subr.c b/net/x25/x25_subr.c index 27c5885c14ef..a946c1cfb5a2 100644 --- a/net/x25/x25_subr.c +++ b/net/x25/x25_subr.c @@ -363,10 +363,12 @@ void x25_disconnect(struct sock *sk, int reason, unsigned char cause, sk->sk_state_change(sk); sock_set_flag(sk, SOCK_DEAD); } - read_lock_bh(&x25_list_lock); - x25_neigh_put(x25->neighbour); - x25->neighbour = NULL; - read_unlock_bh(&x25_list_lock); + if (x25->neighbour) { + read_lock_bh(&x25_list_lock); + x25_neigh_put(x25->neighbour); + x25->neighbour = NULL; + read_unlock_bh(&x25_list_lock); + } } /* From f8b892f4ecf5bcc5840a28d65ae9ea3815aca2bd Mon Sep 17 00:00:00 2001 From: Tanner Love Date: Mon, 27 Jul 2020 12:25:28 -0400 Subject: [PATCH 396/592] selftests/net: rxtimestamp: fix clang issues for target arch PowerPC [ Upstream commit 955cbe91bcf782c09afe369c95a20f0a4b6dcc3c ] The signedness of char is implementation-dependent. Some systems (including PowerPC and ARM) use unsigned char. Clang 9 threw: warning: result of comparison of constant -1 with expression of type \ 'char' is always true [-Wtautological-constant-out-of-range-compare] &arg_index)) != -1) { Tested: make -C tools/testing/selftests TARGETS="net" run_tests Fixes: 16e781224198 ("selftests/net: Add a test to validate behavior of rx timestamps") Signed-off-by: Tanner Love Acked-by: Willem de Bruijn Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- tools/testing/selftests/networking/timestamping/rxtimestamp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/testing/selftests/networking/timestamping/rxtimestamp.c b/tools/testing/selftests/networking/timestamping/rxtimestamp.c index 7a573fb4c1c4..c6428f1ac22f 100644 --- a/tools/testing/selftests/networking/timestamping/rxtimestamp.c +++ b/tools/testing/selftests/networking/timestamping/rxtimestamp.c @@ -328,8 +328,7 @@ int main(int argc, char **argv) bool all_tests = true; int arg_index = 0; int failures = 0; - int s, t; - char opt; + int s, t, opt; while ((opt = getopt_long(argc, argv, "", long_options, &arg_index)) != -1) { From 0269709542e25bbc7746b5a7a53e9e16fbf10f68 Mon Sep 17 00:00:00 2001 From: Michael Karcher Date: Thu, 23 Jul 2020 01:13:19 +0200 Subject: [PATCH 397/592] sh: Fix validation of system call number [ Upstream commit 04a8a3d0a73f51c7c2da84f494db7ec1df230e69 ] The slow path for traced system call entries accessed a wrong memory location to get the number of the maximum allowed system call number. Renumber the numbered "local" label for the correct location to avoid collisions with actual local labels. Signed-off-by: Michael Karcher Tested-by: John Paul Adrian Glaubitz Fixes: f3a8308864f920d2 ("sh: Add a few missing irqflags tracing markers.") Signed-off-by: Rich Felker Signed-off-by: Sasha Levin --- arch/sh/kernel/entry-common.S | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S index 28cc61216b64..ed5b758c650d 100644 --- a/arch/sh/kernel/entry-common.S +++ b/arch/sh/kernel/entry-common.S @@ -203,7 +203,7 @@ syscall_trace_entry: mov.l @(OFF_R7,r15), r7 ! arg3 mov.l @(OFF_R3,r15), r3 ! syscall_nr ! - mov.l 2f, r10 ! Number of syscalls + mov.l 6f, r10 ! Number of syscalls cmp/hs r10, r3 bf syscall_call mov #-ENOSYS, r0 @@ -357,7 +357,7 @@ ENTRY(system_call) tst r9, r8 bf syscall_trace_entry ! - mov.l 2f, r8 ! Number of syscalls + mov.l 6f, r8 ! Number of syscalls cmp/hs r8, r3 bt syscall_badsys ! @@ -396,7 +396,7 @@ syscall_exit: #if !defined(CONFIG_CPU_SH2) 1: .long TRA #endif -2: .long NR_syscalls +6: .long NR_syscalls 3: .long sys_call_table 7: .long do_syscall_trace_enter 8: .long do_syscall_trace_leave From 399cb287e12da41ab79bdd8a2301b36c715dc7e6 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 28 Jul 2020 14:10:29 +0200 Subject: [PATCH 398/592] net: lan78xx: add missing endpoint sanity check [ Upstream commit 8d8e95fd6d69d774013f51e5f2ee10c6e6d1fc14 ] Add the missing endpoint sanity check to prevent a NULL-pointer dereference should a malicious device lack the expected endpoints. Note that the driver has a broken endpoint-lookup helper, lan78xx_get_endpoints(), which can end up accepting interfaces in an altsetting without endpoints as long as *some* altsetting has a bulk-in and a bulk-out endpoint. Fixes: 55d7de9de6c3 ("Microchip's LAN7800 family USB 2/3 to 10/100/1000 Ethernet device driver") Cc: Woojung.Huh@microchip.com Signed-off-by: Johan Hovold Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- drivers/net/usb/lan78xx.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c index b179a96ea08c..3be92fff89b1 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c @@ -3629,6 +3629,11 @@ static int lan78xx_probe(struct usb_interface *intf, netdev->max_mtu = MAX_SINGLE_PACKET_SIZE; netif_set_gso_max_size(netdev, MAX_SINGLE_PACKET_SIZE - MAX_HEADER); + if (intf->cur_altsetting->desc.bNumEndpoints < 3) { + ret = -ENODEV; + goto out3; + } + dev->ep_blkin = (intf->cur_altsetting)->endpoint + 0; dev->ep_blkout = (intf->cur_altsetting)->endpoint + 1; dev->ep_intr = (intf->cur_altsetting)->endpoint + 2; From 3c00fe927003024cf69e22d065fb095bb0bf7a0f Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 28 Jul 2020 14:10:30 +0200 Subject: [PATCH 399/592] net: lan78xx: fix transfer-buffer memory leak [ Upstream commit 63634aa679ba8b5e306ad0727120309ae6ba8a8e ] The interrupt URB transfer-buffer was never freed on disconnect or after probe errors. Fixes: 55d7de9de6c3 ("Microchip's LAN7800 family USB 2/3 to 10/100/1000 Ethernet device driver") Cc: Woojung.Huh@microchip.com Signed-off-by: Johan Hovold Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- drivers/net/usb/lan78xx.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c index 3be92fff89b1..895f307979c8 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c @@ -3658,6 +3658,7 @@ static int lan78xx_probe(struct usb_interface *intf, usb_fill_int_urb(dev->urb_intr, dev->udev, dev->pipe_intr, buf, maxp, intr_complete, dev, period); + dev->urb_intr->transfer_flags |= URB_FREE_BUFFER; } } From a4bdf2cd63b5f14e16791e69927a92232523e1a3 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Fri, 24 Jul 2020 16:15:43 -0700 Subject: [PATCH 400/592] mlx4: disable device on shutdown [ Upstream commit 3cab8c65525920f00d8f4997b3e9bb73aecb3a8e ] It appears that not disabling a PCI device on .shutdown may lead to a Hardware Error with particular (perhaps buggy) BIOS versions: mlx4_en: eth0: Close port called mlx4_en 0000:04:00.0: removed PHC reboot: Restarting system {1}[Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 1 {1}[Hardware Error]: event severity: fatal {1}[Hardware Error]: Error 0, type: fatal {1}[Hardware Error]: section_type: PCIe error {1}[Hardware Error]: port_type: 4, root port {1}[Hardware Error]: version: 1.16 {1}[Hardware Error]: command: 0x4010, status: 0x0143 {1}[Hardware Error]: device_id: 0000:00:02.2 {1}[Hardware Error]: slot: 0 {1}[Hardware Error]: secondary_bus: 0x04 {1}[Hardware Error]: vendor_id: 0x8086, device_id: 0x2f06 {1}[Hardware Error]: class_code: 000604 {1}[Hardware Error]: bridge: secondary_status: 0x2000, control: 0x0003 {1}[Hardware Error]: aer_uncor_status: 0x00100000, aer_uncor_mask: 0x00000000 {1}[Hardware Error]: aer_uncor_severity: 0x00062030 {1}[Hardware Error]: TLP Header: 40000018 040000ff 791f4080 00000000 [hw error repeats] Kernel panic - not syncing: Fatal hardware error! CPU: 0 PID: 2189 Comm: reboot Kdump: loaded Not tainted 5.6.x-blabla #1 Hardware name: HP ProLiant DL380 Gen9/ProLiant DL380 Gen9, BIOS P89 05/05/2017 Fix the mlx4 driver. This is a very similar problem to what had been fixed in: commit 0d98ba8d70b0 ("scsi: hpsa: disable device during shutdown") to address https://bugzilla.kernel.org/show_bug.cgi?id=199779. Fixes: 2ba5fbd62b25 ("net/mlx4_core: Handle AER flow properly") Reported-by: Jake Lawrence Signed-off-by: Jakub Kicinski Reviewed-by: Saeed Mahameed Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- drivers/net/ethernet/mellanox/mlx4/main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index cf9011bb6e0f..c6660b61e836 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -4190,12 +4190,14 @@ end: static void mlx4_shutdown(struct pci_dev *pdev) { struct mlx4_dev_persistent *persist = pci_get_drvdata(pdev); + struct mlx4_dev *dev = persist->dev; mlx4_info(persist->dev, "mlx4_shutdown was called\n"); mutex_lock(&persist->interface_state_mutex); if (persist->interface_state & MLX4_INTERFACE_STATE_UP) mlx4_unload_one(pdev); mutex_unlock(&persist->interface_state_mutex); + mlx4_pci_disable_device(dev); } static const struct pci_error_handlers mlx4_err_handler = { From 6e0fdf004d8539df351f3a33e45e01575352b61c Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 29 Jul 2020 12:26:45 +0300 Subject: [PATCH 401/592] mlxsw: core: Increase scope of RCU read-side critical section [ Upstream commit 7d8e8f3433dc8d1dc87c1aabe73a154978fb4c4d ] The lifetime of the Rx listener item ('rxl_item') is managed using RCU, but is dereferenced outside of RCU read-side critical section, which can lead to a use-after-free. Fix this by increasing the scope of the RCU read-side critical section. Fixes: 93c1edb27f9e ("mlxsw: Introduce Mellanox switch driver core") Signed-off-by: Ido Schimmel Reviewed-by: Jiri Pirko Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- drivers/net/ethernet/mellanox/mlxsw/core.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c index 96f9f267d16d..a2161b140904 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -1574,11 +1574,13 @@ void mlxsw_core_skb_receive(struct mlxsw_core *mlxsw_core, struct sk_buff *skb, break; } } - rcu_read_unlock(); - if (!found) + if (!found) { + rcu_read_unlock(); goto drop; + } rxl->func(skb, local_port, rxl_item->priv); + rcu_read_unlock(); return; drop: From 2d32ef087f4e30b91dd6f409853c62dbc9aa0b5e Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 29 Jul 2020 12:26:46 +0300 Subject: [PATCH 402/592] mlxsw: core: Free EMAD transactions using kfree_rcu() [ Upstream commit 3c8ce24b037648a5a15b85888b259a74b05ff97d ] The lifetime of EMAD transactions (i.e., 'struct mlxsw_reg_trans') is managed using RCU. They are freed using kfree_rcu() once the transaction ends. However, in case the transaction failed it is freed immediately after being removed from the active transactions list. This is problematic because it is still possible for a different CPU to dereference the transaction from an RCU read-side critical section while traversing the active transaction list in mlxsw_emad_rx_listener_func(). In which case, a use-after-free is triggered [1]. Fix this by freeing the transaction after a grace period by calling kfree_rcu(). [1] BUG: KASAN: use-after-free in mlxsw_emad_rx_listener_func+0x969/0xac0 drivers/net/ethernet/mellanox/mlxsw/core.c:671 Read of size 8 at addr ffff88800b7964e8 by task syz-executor.2/2881 CPU: 0 PID: 2881 Comm: syz-executor.2 Not tainted 5.8.0-rc4+ #44 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.1-0-ga5cab58e9a3f-prebuilt.qemu.org 04/01/2014 Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0xf6/0x16e lib/dump_stack.c:118 print_address_description.constprop.0+0x1c/0x250 mm/kasan/report.c:383 __kasan_report mm/kasan/report.c:513 [inline] kasan_report.cold+0x1f/0x37 mm/kasan/report.c:530 mlxsw_emad_rx_listener_func+0x969/0xac0 drivers/net/ethernet/mellanox/mlxsw/core.c:671 mlxsw_core_skb_receive+0x571/0x700 drivers/net/ethernet/mellanox/mlxsw/core.c:2061 mlxsw_pci_cqe_rdq_handle drivers/net/ethernet/mellanox/mlxsw/pci.c:595 [inline] mlxsw_pci_cq_tasklet+0x12a6/0x2520 drivers/net/ethernet/mellanox/mlxsw/pci.c:651 tasklet_action_common.isra.0+0x13f/0x3e0 kernel/softirq.c:550 __do_softirq+0x223/0x964 kernel/softirq.c:292 asm_call_on_stack+0x12/0x20 arch/x86/entry/entry_64.S:711 __run_on_irqstack arch/x86/include/asm/irq_stack.h:22 [inline] run_on_irqstack_cond arch/x86/include/asm/irq_stack.h:48 [inline] do_softirq_own_stack+0x109/0x140 arch/x86/kernel/irq_64.c:77 invoke_softirq kernel/softirq.c:387 [inline] __irq_exit_rcu kernel/softirq.c:417 [inline] irq_exit_rcu+0x16f/0x1a0 kernel/softirq.c:429 sysvec_apic_timer_interrupt+0x4e/0xd0 arch/x86/kernel/apic/apic.c:1091 asm_sysvec_apic_timer_interrupt+0x12/0x20 arch/x86/include/asm/idtentry.h:587 RIP: 0010:arch_local_irq_restore arch/x86/include/asm/irqflags.h:85 [inline] RIP: 0010:__raw_spin_unlock_irqrestore include/linux/spinlock_api_smp.h:160 [inline] RIP: 0010:_raw_spin_unlock_irqrestore+0x3b/0x40 kernel/locking/spinlock.c:191 Code: e8 2a c3 f4 fc 48 89 ef e8 12 96 f5 fc f6 c7 02 75 11 53 9d e8 d6 db 11 fd 65 ff 0d 1f 21 b3 56 5b 5d c3 e8 a7 d7 11 fd 53 9d ed 0f 1f 00 55 48 89 fd 65 ff 05 05 21 b3 56 ff 74 24 08 48 8d RSP: 0018:ffff8880446ffd80 EFLAGS: 00000286 RAX: 0000000000000006 RBX: 0000000000000286 RCX: 0000000000000006 RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffffffffa94ecea9 RBP: ffff888012934408 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000001 R11: fffffbfff57be301 R12: 1ffff110088dffc1 R13: ffff888037b817c0 R14: ffff88802442415a R15: ffff888024424000 __do_sys_perf_event_open+0x1b5d/0x2bd0 kernel/events/core.c:11874 do_syscall_64+0x56/0xa0 arch/x86/entry/common.c:384 entry_SYSCALL_64_after_hwframe+0x44/0xa9 RIP: 0033:0x473dbd Code: Bad RIP value. RSP: 002b:00007f21e5e9cc28 EFLAGS: 00000246 ORIG_RAX: 000000000000012a RAX: ffffffffffffffda RBX: 000000000057bf00 RCX: 0000000000473dbd RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000020000040 RBP: 000000000057bf00 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000003 R11: 0000000000000246 R12: 000000000057bf0c R13: 00007ffd0493503f R14: 00000000004d0f46 R15: 00007f21e5e9cd80 Allocated by task 871: save_stack+0x1b/0x40 mm/kasan/common.c:48 set_track mm/kasan/common.c:56 [inline] __kasan_kmalloc mm/kasan/common.c:494 [inline] __kasan_kmalloc.constprop.0+0xc2/0xd0 mm/kasan/common.c:467 kmalloc include/linux/slab.h:555 [inline] kzalloc include/linux/slab.h:669 [inline] mlxsw_core_reg_access_emad+0x70/0x1410 drivers/net/ethernet/mellanox/mlxsw/core.c:1812 mlxsw_core_reg_access+0xeb/0x540 drivers/net/ethernet/mellanox/mlxsw/core.c:1991 mlxsw_sp_port_get_hw_xstats+0x335/0x7e0 drivers/net/ethernet/mellanox/mlxsw/spectrum.c:1130 update_stats_cache+0xf4/0x140 drivers/net/ethernet/mellanox/mlxsw/spectrum.c:1173 process_one_work+0xa3e/0x17a0 kernel/workqueue.c:2269 worker_thread+0x9e/0x1050 kernel/workqueue.c:2415 kthread+0x355/0x470 kernel/kthread.c:291 ret_from_fork+0x22/0x30 arch/x86/entry/entry_64.S:293 Freed by task 871: save_stack+0x1b/0x40 mm/kasan/common.c:48 set_track mm/kasan/common.c:56 [inline] kasan_set_free_info mm/kasan/common.c:316 [inline] __kasan_slab_free+0x12c/0x170 mm/kasan/common.c:455 slab_free_hook mm/slub.c:1474 [inline] slab_free_freelist_hook mm/slub.c:1507 [inline] slab_free mm/slub.c:3072 [inline] kfree+0xe6/0x320 mm/slub.c:4052 mlxsw_core_reg_access_emad+0xd45/0x1410 drivers/net/ethernet/mellanox/mlxsw/core.c:1819 mlxsw_core_reg_access+0xeb/0x540 drivers/net/ethernet/mellanox/mlxsw/core.c:1991 mlxsw_sp_port_get_hw_xstats+0x335/0x7e0 drivers/net/ethernet/mellanox/mlxsw/spectrum.c:1130 update_stats_cache+0xf4/0x140 drivers/net/ethernet/mellanox/mlxsw/spectrum.c:1173 process_one_work+0xa3e/0x17a0 kernel/workqueue.c:2269 worker_thread+0x9e/0x1050 kernel/workqueue.c:2415 kthread+0x355/0x470 kernel/kthread.c:291 ret_from_fork+0x22/0x30 arch/x86/entry/entry_64.S:293 The buggy address belongs to the object at ffff88800b796400 which belongs to the cache kmalloc-512 of size 512 The buggy address is located 232 bytes inside of 512-byte region [ffff88800b796400, ffff88800b796600) The buggy address belongs to the page: page:ffffea00002de500 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 head:ffffea00002de500 order:2 compound_mapcount:0 compound_pincount:0 flags: 0x100000000010200(slab|head) raw: 0100000000010200 dead000000000100 dead000000000122 ffff88806c402500 raw: 0000000000000000 0000000000100010 00000001ffffffff 0000000000000000 page dumped because: kasan: bad access detected Memory state around the buggy address: ffff88800b796380: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc ffff88800b796400: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb >ffff88800b796480: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ^ ffff88800b796500: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ffff88800b796580: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb Fixes: caf7297e7ab5 ("mlxsw: core: Introduce support for asynchronous EMAD register access") Signed-off-by: Ido Schimmel Reviewed-by: Jiri Pirko Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- drivers/net/ethernet/mellanox/mlxsw/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c index a2161b140904..dc12ab33afff 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -1361,7 +1361,7 @@ static int mlxsw_core_reg_access_emad(struct mlxsw_core *mlxsw_core, err = mlxsw_emad_reg_access(mlxsw_core, reg, payload, type, trans, bulk_list, cb, cb_priv, tid); if (err) { - kfree(trans); + kfree_rcu(trans, rcu); return err; } return 0; From 8091ddc0695e3737530158589e109c6562c500a0 Mon Sep 17 00:00:00 2001 From: Thomas Falcon Date: Wed, 29 Jul 2020 16:36:32 -0500 Subject: [PATCH 403/592] ibmvnic: Fix IRQ mapping disposal in error path [ Upstream commit 27a2145d6f826d1fad9de06ac541b1016ced3427 ] RX queue IRQ mappings are disposed in both the TX IRQ and RX IRQ error paths. Fix this and dispose of TX IRQ mappings correctly in case of an error. Fixes: ea22d51a7831 ("ibmvnic: simplify and improve driver probe function") Signed-off-by: Thomas Falcon Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- drivers/net/ethernet/ibm/ibmvnic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index 85c11dafb4cd..8b8a0c4fbc99 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -2324,7 +2324,7 @@ req_rx_irq_failed: req_tx_irq_failed: for (j = 0; j < i; j++) { free_irq(adapter->tx_scrq[j]->irq, adapter->tx_scrq[j]); - irq_dispose_mapping(adapter->rx_scrq[j]->irq); + irq_dispose_mapping(adapter->tx_scrq[j]->irq); } release_sub_crqs(adapter); return rc; From e1aa01195b82a5a8354c9b87746097866f3693de Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Tue, 28 Jul 2020 21:09:12 -0700 Subject: [PATCH 404/592] bpf: Fix map leak in HASH_OF_MAPS map [ Upstream commit 1d4e1eab456e1ee92a94987499b211db05f900ea ] Fix HASH_OF_MAPS bug of not putting inner map pointer on bpf_map_elem_update() operation. This is due to per-cpu extra_elems optimization, which bypassed free_htab_elem() logic doing proper clean ups. Make sure that inner map is put properly in optimized case as well. Fixes: 8c290e60fa2a ("bpf: fix hashmap extra_elems logic") Signed-off-by: Andrii Nakryiko Signed-off-by: Daniel Borkmann Acked-by: Song Liu Link: https://lore.kernel.org/bpf/20200729040913.2815687-1-andriin@fb.com Signed-off-by: Sasha Levin --- kernel/bpf/hashtab.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c index 505e69854eb8..6cc090d015f6 100644 --- a/kernel/bpf/hashtab.c +++ b/kernel/bpf/hashtab.c @@ -656,15 +656,20 @@ static void htab_elem_free_rcu(struct rcu_head *head) preempt_enable(); } -static void free_htab_elem(struct bpf_htab *htab, struct htab_elem *l) +static void htab_put_fd_value(struct bpf_htab *htab, struct htab_elem *l) { struct bpf_map *map = &htab->map; + void *ptr; if (map->ops->map_fd_put_ptr) { - void *ptr = fd_htab_map_get_ptr(map, l); - + ptr = fd_htab_map_get_ptr(map, l); map->ops->map_fd_put_ptr(ptr); } +} + +static void free_htab_elem(struct bpf_htab *htab, struct htab_elem *l) +{ + htab_put_fd_value(htab, l); if (htab_is_prealloc(htab)) { __pcpu_freelist_push(&htab->freelist, &l->fnode); @@ -725,6 +730,7 @@ static struct htab_elem *alloc_htab_elem(struct bpf_htab *htab, void *key, */ pl_new = this_cpu_ptr(htab->extra_elems); l_new = *pl_new; + htab_put_fd_value(htab, old_elem); *pl_new = old_elem; } else { struct pcpu_freelist_node *l; From 86e7d4cd2ed5f4b0188afce8199faffcf1ae7c7e Mon Sep 17 00:00:00 2001 From: Remi Pommarel Date: Sat, 4 Jul 2020 15:50:07 +0200 Subject: [PATCH 405/592] mac80211: mesh: Free ie data when leaving mesh [ Upstream commit 6a01afcf8468d3ca2bd8bbb27503f60dcf643b20 ] At ieee80211_join_mesh() some ie data could have been allocated (see copy_mesh_setup()) and need to be cleaned up when leaving the mesh. This fixes the following kmemleak report: unreferenced object 0xffff0000116bc600 (size 128): comm "wpa_supplicant", pid 608, jiffies 4294898983 (age 293.484s) hex dump (first 32 bytes): 30 14 01 00 00 0f ac 04 01 00 00 0f ac 04 01 00 0............... 00 0f ac 08 00 00 00 00 c4 65 40 00 00 00 00 00 .........e@..... backtrace: [<00000000bebe439d>] __kmalloc_track_caller+0x1c0/0x330 [<00000000a349dbe1>] kmemdup+0x28/0x50 [<0000000075d69baa>] ieee80211_join_mesh+0x6c/0x3b8 [mac80211] [<00000000683bb98b>] __cfg80211_join_mesh+0x1e8/0x4f0 [cfg80211] [<0000000072cb507f>] nl80211_join_mesh+0x520/0x6b8 [cfg80211] [<0000000077e9bcf9>] genl_family_rcv_msg+0x374/0x680 [<00000000b1bd936d>] genl_rcv_msg+0x78/0x108 [<0000000022c53788>] netlink_rcv_skb+0xb0/0x1c0 [<0000000011af8ec9>] genl_rcv+0x34/0x48 [<0000000069e41f53>] netlink_unicast+0x268/0x2e8 [<00000000a7517316>] netlink_sendmsg+0x320/0x4c0 [<0000000069cba205>] ____sys_sendmsg+0x354/0x3a0 [<00000000e06bab0f>] ___sys_sendmsg+0xd8/0x120 [<0000000037340728>] __sys_sendmsg+0xa4/0xf8 [<000000004fed9776>] __arm64_sys_sendmsg+0x44/0x58 [<000000001c1e5647>] el0_svc_handler+0xd0/0x1a0 Fixes: c80d545da3f7 (mac80211: Let userspace enable and configure vendor specific path selection.) Signed-off-by: Remi Pommarel Link: https://lore.kernel.org/r/20200704135007.27292-1-repk@triplefau.lt Signed-off-by: Johannes Berg Signed-off-by: Sasha Levin --- net/mac80211/cfg.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index b1484b8316e8..c883cb67b731 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1997,6 +1997,7 @@ static int ieee80211_leave_mesh(struct wiphy *wiphy, struct net_device *dev) ieee80211_stop_mesh(sdata); mutex_lock(&sdata->local->mtx); ieee80211_vif_release_channel(sdata); + kfree(sdata->u.mesh.ie); mutex_unlock(&sdata->local->mtx); return 0; From b0cf0beeb6619a7e876e101bcb044eb803b876fa Mon Sep 17 00:00:00 2001 From: Remi Pommarel Date: Sat, 4 Jul 2020 15:54:19 +0200 Subject: [PATCH 406/592] mac80211: mesh: Free pending skb when destroying a mpath [ Upstream commit 5e43540c2af0a0c0a18e39579b1ad49541f87506 ] A mpath object can hold reference on a list of skb that are waiting for mpath resolution to be sent. When destroying a mpath this skb list should be cleaned up in order to not leak memory. Fixing that kind of leak: unreferenced object 0xffff0000181c9300 (size 1088): comm "openvpn", pid 1782, jiffies 4295071698 (age 80.416s) hex dump (first 32 bytes): 00 00 00 00 00 00 00 00 f9 80 36 00 00 00 00 00 ..........6..... 02 00 07 40 00 00 00 00 00 00 00 00 00 00 00 00 ...@............ backtrace: [<000000004bc6a443>] kmem_cache_alloc+0x1a4/0x2f0 [<000000002caaef13>] sk_prot_alloc.isra.39+0x34/0x178 [<00000000ceeaa916>] sk_alloc+0x34/0x228 [<00000000ca1f1d04>] inet_create+0x198/0x518 [<0000000035626b1c>] __sock_create+0x134/0x328 [<00000000a12b3a87>] __sys_socket+0xb0/0x158 [<00000000ff859f23>] __arm64_sys_socket+0x40/0x58 [<00000000263486ec>] el0_svc_handler+0xd0/0x1a0 [<0000000005b5157d>] el0_svc+0x8/0xc unreferenced object 0xffff000012973a40 (size 216): comm "openvpn", pid 1782, jiffies 4295082137 (age 38.660s) hex dump (first 32 bytes): 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 c0 06 16 00 00 ff ff 00 93 1c 18 00 00 ff ff ................ backtrace: [<000000004bc6a443>] kmem_cache_alloc+0x1a4/0x2f0 [<0000000023c8c8f9>] __alloc_skb+0xc0/0x2b8 [<000000007ad950bb>] alloc_skb_with_frags+0x60/0x320 [<00000000ef90023a>] sock_alloc_send_pskb+0x388/0x3c0 [<00000000104fb1a3>] sock_alloc_send_skb+0x1c/0x28 [<000000006919d2dd>] __ip_append_data+0xba4/0x11f0 [<0000000083477587>] ip_make_skb+0x14c/0x1a8 [<0000000024f3d592>] udp_sendmsg+0xaf0/0xcf0 [<000000005aabe255>] inet_sendmsg+0x5c/0x80 [<000000008651ea08>] __sys_sendto+0x15c/0x218 [<000000003505c99b>] __arm64_sys_sendto+0x74/0x90 [<00000000263486ec>] el0_svc_handler+0xd0/0x1a0 [<0000000005b5157d>] el0_svc+0x8/0xc Fixes: 2bdaf386f99c (mac80211: mesh: move path tables into if_mesh) Signed-off-by: Remi Pommarel Link: https://lore.kernel.org/r/20200704135419.27703-1-repk@triplefau.lt Signed-off-by: Johannes Berg Signed-off-by: Sasha Levin --- net/mac80211/mesh_pathtbl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 130022091205..933f26e2ff8b 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -554,6 +554,7 @@ static void mesh_path_free_rcu(struct mesh_table *tbl, del_timer_sync(&mpath->timer); atomic_dec(&sdata->u.mesh.mpaths); atomic_dec(&tbl->entries); + mesh_path_flush_pending(mpath); kfree_rcu(mpath, rcu); } From a15a67e3eb42af79d0b0470578d19462ce9c68ad Mon Sep 17 00:00:00 2001 From: Sami Tolvanen Date: Thu, 30 Jul 2020 08:37:01 -0700 Subject: [PATCH 407/592] arm64/alternatives: move length validation inside the subsection [ Upstream commit 966a0acce2fca776391823381dba95c40e03c339 ] Commit f7b93d42945c ("arm64/alternatives: use subsections for replacement sequences") breaks LLVM's integrated assembler, because due to its one-pass design, it cannot compute instruction sequence lengths before the layout for the subsection has been finalized. This change fixes the build by moving the .org directives inside the subsection, so they are processed after the subsection layout is known. Fixes: f7b93d42945c ("arm64/alternatives: use subsections for replacement sequences") Signed-off-by: Sami Tolvanen Link: https://github.com/ClangBuiltLinux/linux/issues/1078 Link: https://lore.kernel.org/r/20200730153701.3892953-1-samitolvanen@google.com Signed-off-by: Will Deacon Signed-off-by: Sasha Levin --- arch/arm64/include/asm/alternative.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/include/asm/alternative.h b/arch/arm64/include/asm/alternative.h index 1824768fb1ee..3abb2dacb43f 100644 --- a/arch/arm64/include/asm/alternative.h +++ b/arch/arm64/include/asm/alternative.h @@ -72,9 +72,9 @@ void apply_alternatives(void *start, size_t length); "663:\n\t" \ newinstr "\n" \ "664:\n\t" \ - ".previous\n\t" \ ".org . - (664b-663b) + (662b-661b)\n\t" \ - ".org . - (662b-661b) + (664b-663b)\n" \ + ".org . - (662b-661b) + (664b-663b)\n\t" \ + ".previous\n" \ ".endif\n" #define __ALTERNATIVE_CFG_CB(oldinstr, feature, cfg_enabled, cb) \ From 565089445b39c2c35f2cb977b50246291f568a78 Mon Sep 17 00:00:00 2001 From: Robin Murphy Date: Thu, 30 Jul 2020 10:56:49 +0100 Subject: [PATCH 408/592] arm64: csum: Fix handling of bad packets [ Upstream commit 05fb3dbda187bbd9cc1cd0e97e5d6595af570ac6 ] Although iph is expected to point to at least 20 bytes of valid memory, ihl may be bogus, for example on reception of a corrupt packet. If it happens to be less than 5, we really don't want to run away and dereference 16GB worth of memory until it wraps back to exactly zero... Fixes: 0e455d8e80aa ("arm64: Implement optimised IP checksum helpers") Reported-by: guodeqing Signed-off-by: Robin Murphy Signed-off-by: Will Deacon Signed-off-by: Sasha Levin --- arch/arm64/include/asm/checksum.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm64/include/asm/checksum.h b/arch/arm64/include/asm/checksum.h index 0b6f5a7d4027..fd11e0d70e44 100644 --- a/arch/arm64/include/asm/checksum.h +++ b/arch/arm64/include/asm/checksum.h @@ -30,16 +30,17 @@ static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl) { __uint128_t tmp; u64 sum; + int n = ihl; /* we want it signed */ tmp = *(const __uint128_t *)iph; iph += 16; - ihl -= 4; + n -= 4; tmp += ((tmp >> 64) | (tmp << 64)); sum = tmp >> 64; do { sum += *(const u32 *)iph; iph += 4; - } while (--ihl); + } while (--n > 0); sum += ((sum >> 32) | (sum << 32)); return csum_fold((__force u32)(sum >> 32)); From 9358267414ca4cefc73ddc29542ec5b1433cd3de Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 13 Jul 2020 13:05:13 +0200 Subject: [PATCH 409/592] usb: hso: Fix debug compile warning on sparc32 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit e0484010ec05191a8edf980413fc92f28050c1cc ] On sparc32, tcflag_t is "unsigned long", unlike on all other architectures, where it is "unsigned int": drivers/net/usb/hso.c: In function ‘hso_serial_set_termios’: include/linux/kern_levels.h:5:18: warning: format ‘%d’ expects argument of type ‘unsigned int’, but argument 4 has type ‘tcflag_t {aka long unsigned int}’ [-Wformat=] drivers/net/usb/hso.c:1393:3: note: in expansion of macro ‘hso_dbg’ hso_dbg(0x16, "Termios called with: cflags new[%d] - old[%d]\n", ^~~~~~~ include/linux/kern_levels.h:5:18: warning: format ‘%d’ expects argument of type ‘unsigned int’, but argument 5 has type ‘tcflag_t {aka long unsigned int}’ [-Wformat=] drivers/net/usb/hso.c:1393:3: note: in expansion of macro ‘hso_dbg’ hso_dbg(0x16, "Termios called with: cflags new[%d] - old[%d]\n", ^~~~~~~ As "unsigned long" is 32-bit on sparc32, fix this by casting all tcflag_t parameters to "unsigned int". While at it, use "%u" to format unsigned numbers. Signed-off-by: Geert Uytterhoeven Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- drivers/net/usb/hso.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 6597d1f8d68c..7988c41bff1d 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -1402,8 +1402,9 @@ static void hso_serial_set_termios(struct tty_struct *tty, struct ktermios *old) unsigned long flags; if (old) - hso_dbg(0x16, "Termios called with: cflags new[%d] - old[%d]\n", - tty->termios.c_cflag, old->c_cflag); + hso_dbg(0x16, "Termios called with: cflags new[%u] - old[%u]\n", + (unsigned int)tty->termios.c_cflag, + (unsigned int)old->c_cflag); /* the actual setup */ spin_lock_irqsave(&serial->serial_lock, flags); From 5727ef24ba9d51ce21f49b92669dfdf03b31de59 Mon Sep 17 00:00:00 2001 From: Laurence Oberman Date: Tue, 14 Jul 2020 18:08:05 -0400 Subject: [PATCH 410/592] qed: Disable "MFW indication via attention" SPAM every 5 minutes [ Upstream commit 1d61e21852d3161f234b9656797669fe185c251b ] This is likely firmware causing this but its starting to annoy customers. Change the message level to verbose to prevent the spam. Note that this seems to only show up with ISCSI enabled on the HBA via the qedi driver. Signed-off-by: Laurence Oberman Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- drivers/net/ethernet/qlogic/qed/qed_int.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/qlogic/qed/qed_int.c b/drivers/net/ethernet/qlogic/qed/qed_int.c index c5d9f290ec4c..f8d1d02a3cd4 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_int.c +++ b/drivers/net/ethernet/qlogic/qed/qed_int.c @@ -1015,7 +1015,8 @@ static int qed_int_attentions(struct qed_hwfn *p_hwfn) index, attn_bits, attn_acks, asserted_bits, deasserted_bits, p_sb_attn_sw->known_attn); } else if (asserted_bits == 0x100) { - DP_INFO(p_hwfn, "MFW indication via attention\n"); + DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, + "MFW indication via attention\n"); } else { DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, "MFW indication [deassertion]\n"); From b10dc328b3c7892944693db2150c0bc340743f3f Mon Sep 17 00:00:00 2001 From: Navid Emamdoost Date: Sat, 18 Jul 2020 00:31:49 -0500 Subject: [PATCH 411/592] nfc: s3fwrn5: add missing release on skb in s3fwrn5_recv_frame [ Upstream commit 1e8fd3a97f2d83a7197876ceb4f37b4c2b00a0f3 ] The implementation of s3fwrn5_recv_frame() is supposed to consume skb on all execution paths. Release skb before returning -ENODEV. Signed-off-by: Navid Emamdoost Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- drivers/nfc/s3fwrn5/core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/nfc/s3fwrn5/core.c b/drivers/nfc/s3fwrn5/core.c index 9d9c8d57a042..64b58455e620 100644 --- a/drivers/nfc/s3fwrn5/core.c +++ b/drivers/nfc/s3fwrn5/core.c @@ -209,6 +209,7 @@ int s3fwrn5_recv_frame(struct nci_dev *ndev, struct sk_buff *skb, case S3FWRN5_MODE_FW: return s3fwrn5_fw_recv_frame(ndev, skb); default: + kfree_skb(skb); return -ENODEV; } } From 9e3f4267f73ee3f747ae4826f7bdb171dbab2303 Mon Sep 17 00:00:00 2001 From: Liam Beguin Date: Sat, 18 Jul 2020 16:10:21 -0400 Subject: [PATCH 412/592] parisc: add support for cmpxchg on u8 pointers [ Upstream commit b344d6a83d01c52fddbefa6b3b4764da5b1022a0 ] The kernel test bot reported[1] that using set_mask_bits on a u8 causes the following issue on parisc: hppa-linux-ld: drivers/phy/ti/phy-tusb1210.o: in function `tusb1210_probe': >> (.text+0x2f4): undefined reference to `__cmpxchg_called_with_bad_pointer' >> hppa-linux-ld: (.text+0x324): undefined reference to `__cmpxchg_called_with_bad_pointer' hppa-linux-ld: (.text+0x354): undefined reference to `__cmpxchg_called_with_bad_pointer' Add support for cmpxchg on u8 pointers. [1] https://lore.kernel.org/patchwork/patch/1272617/#1468946 Reported-by: kernel test robot Signed-off-by: Liam Beguin Tested-by: Dave Anglin Signed-off-by: Helge Deller Signed-off-by: Sasha Levin --- arch/parisc/include/asm/cmpxchg.h | 2 ++ arch/parisc/lib/bitops.c | 12 ++++++++++++ 2 files changed, 14 insertions(+) diff --git a/arch/parisc/include/asm/cmpxchg.h b/arch/parisc/include/asm/cmpxchg.h index ab5c215cf46c..068958575871 100644 --- a/arch/parisc/include/asm/cmpxchg.h +++ b/arch/parisc/include/asm/cmpxchg.h @@ -60,6 +60,7 @@ extern void __cmpxchg_called_with_bad_pointer(void); extern unsigned long __cmpxchg_u32(volatile unsigned int *m, unsigned int old, unsigned int new_); extern u64 __cmpxchg_u64(volatile u64 *ptr, u64 old, u64 new_); +extern u8 __cmpxchg_u8(volatile u8 *ptr, u8 old, u8 new_); /* don't worry...optimizer will get rid of most of this */ static inline unsigned long @@ -71,6 +72,7 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new_, int size) #endif case 4: return __cmpxchg_u32((unsigned int *)ptr, (unsigned int)old, (unsigned int)new_); + case 1: return __cmpxchg_u8((u8 *)ptr, (u8)old, (u8)new_); } __cmpxchg_called_with_bad_pointer(); return old; diff --git a/arch/parisc/lib/bitops.c b/arch/parisc/lib/bitops.c index 70ffbcf889b8..2e4d1f05a926 100644 --- a/arch/parisc/lib/bitops.c +++ b/arch/parisc/lib/bitops.c @@ -79,3 +79,15 @@ unsigned long __cmpxchg_u32(volatile unsigned int *ptr, unsigned int old, unsign _atomic_spin_unlock_irqrestore(ptr, flags); return (unsigned long)prev; } + +u8 __cmpxchg_u8(volatile u8 *ptr, u8 old, u8 new) +{ + unsigned long flags; + u8 prev; + + _atomic_spin_lock_irqsave(ptr, flags); + if ((prev = *ptr) == old) + *ptr = new; + _atomic_spin_unlock_irqrestore(ptr, flags); + return prev; +} From 850a971a4e2955b966eead9910e375233b15e935 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Tue, 21 Jul 2020 15:23:12 +0900 Subject: [PATCH 413/592] net: ethernet: ravb: exit if re-initialization fails in tx timeout [ Upstream commit 015c5d5e6aa3523c758a70eb87b291cece2dbbb4 ] According to the report of [1], this driver is possible to cause the following error in ravb_tx_timeout_work(). ravb e6800000.ethernet ethernet: failed to switch device to config mode This error means that the hardware could not change the state from "Operation" to "Configuration" while some tx and/or rx queue are operating. After that, ravb_config() in ravb_dmac_init() will fail, and then any descriptors will be not allocaled anymore so that NULL pointer dereference happens after that on ravb_start_xmit(). To fix the issue, the ravb_tx_timeout_work() should check the return values of ravb_stop_dma() and ravb_dmac_init(). If ravb_stop_dma() fails, ravb_tx_timeout_work() re-enables TX and RX and just exits. If ravb_dmac_init() fails, just exits. [1] https://lore.kernel.org/linux-renesas-soc/20200518045452.2390-1-dirk.behme@de.bosch.com/ Reported-by: Dirk Behme Signed-off-by: Yoshihiro Shimoda Reviewed-by: Sergei Shtylyov Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- drivers/net/ethernet/renesas/ravb_main.c | 26 ++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c index d73617cc3b15..9f4d93a16b7e 100644 --- a/drivers/net/ethernet/renesas/ravb_main.c +++ b/drivers/net/ethernet/renesas/ravb_main.c @@ -1482,6 +1482,7 @@ static void ravb_tx_timeout_work(struct work_struct *work) struct ravb_private *priv = container_of(work, struct ravb_private, work); struct net_device *ndev = priv->ndev; + int error; netif_tx_stop_all_queues(ndev); @@ -1490,15 +1491,36 @@ static void ravb_tx_timeout_work(struct work_struct *work) ravb_ptp_stop(ndev); /* Wait for DMA stopping */ - ravb_stop_dma(ndev); + if (ravb_stop_dma(ndev)) { + /* If ravb_stop_dma() fails, the hardware is still operating + * for TX and/or RX. So, this should not call the following + * functions because ravb_dmac_init() is possible to fail too. + * Also, this should not retry ravb_stop_dma() again and again + * here because it's possible to wait forever. So, this just + * re-enables the TX and RX and skip the following + * re-initialization procedure. + */ + ravb_rcv_snd_enable(ndev); + goto out; + } ravb_ring_free(ndev, RAVB_BE); ravb_ring_free(ndev, RAVB_NC); /* Device init */ - ravb_dmac_init(ndev); + error = ravb_dmac_init(ndev); + if (error) { + /* If ravb_dmac_init() fails, descriptors are freed. So, this + * should return here to avoid re-enabling the TX and RX in + * ravb_emac_init(). + */ + netdev_err(ndev, "%s: ravb_dmac_init() failed, error %d\n", + __func__, error); + return; + } ravb_emac_init(ndev); +out: /* Initialise PTP Clock driver */ if (priv->chip_id == RCAR_GEN2) ravb_ptp_init(ndev, priv->pdev); From 24bc07356c49789937026632363efbd83a3e368d Mon Sep 17 00:00:00 2001 From: Raviteja Narayanam Date: Fri, 3 Jul 2020 19:25:49 +0530 Subject: [PATCH 414/592] Revert "i2c: cadence: Fix the hold bit setting" [ Upstream commit 0db9254d6b896b587759e2c844c277fb1a6da5b9 ] This reverts commit d358def706880defa4c9e87381c5bf086a97d5f9. There are two issues with "i2c: cadence: Fix the hold bit setting" commit. 1. In case of combined message request from user space, when the HOLD bit is cleared in cdns_i2c_mrecv function, a STOP condition is sent on the bus even before the last message is started. This is because when the HOLD bit is cleared, the FIFOS are empty and there is no pending transfer. The STOP condition should occur only after the last message is completed. 2. The code added by the commit is redundant. Driver is handling the setting/clearing of HOLD bit in right way before the commit. The setting of HOLD bit based on 'bus_hold_flag' is taken care in cdns_i2c_master_xfer function even before cdns_i2c_msend/cdns_i2c_recv functions. The clearing of HOLD bit is taken care at the end of cdns_i2c_msend and cdns_i2c_recv functions based on bus_hold_flag and byte count. Since clearing of HOLD bit is done after the slave address is written to the register (writing to address register triggers the message transfer), it is ensured that STOP condition occurs at the right time after completion of the pending transfer (last message). Signed-off-by: Raviteja Narayanam Acked-by: Michal Simek Signed-off-by: Wolfram Sang Signed-off-by: Sasha Levin --- drivers/i2c/busses/i2c-cadence.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/i2c/busses/i2c-cadence.c b/drivers/i2c/busses/i2c-cadence.c index d917cefc5a19..b13605718291 100644 --- a/drivers/i2c/busses/i2c-cadence.c +++ b/drivers/i2c/busses/i2c-cadence.c @@ -382,10 +382,8 @@ static void cdns_i2c_mrecv(struct cdns_i2c *id) * Check for the message size against FIFO depth and set the * 'hold bus' bit if it is greater than FIFO depth. */ - if ((id->recv_count > CDNS_I2C_FIFO_DEPTH) || id->bus_hold_flag) + if (id->recv_count > CDNS_I2C_FIFO_DEPTH) ctrl_reg |= CDNS_I2C_CR_HOLD; - else - ctrl_reg = ctrl_reg & ~CDNS_I2C_CR_HOLD; cdns_i2c_writereg(ctrl_reg, CDNS_I2C_CR_OFFSET); @@ -442,11 +440,8 @@ static void cdns_i2c_msend(struct cdns_i2c *id) * Check for the message size against FIFO depth and set the * 'hold bus' bit if it is greater than FIFO depth. */ - if ((id->send_count > CDNS_I2C_FIFO_DEPTH) || id->bus_hold_flag) + if (id->send_count > CDNS_I2C_FIFO_DEPTH) ctrl_reg |= CDNS_I2C_CR_HOLD; - else - ctrl_reg = ctrl_reg & ~CDNS_I2C_CR_HOLD; - cdns_i2c_writereg(ctrl_reg, CDNS_I2C_CR_OFFSET); /* Clear the interrupts in interrupt status register. */ From cc5324cc0cae449e232931623cb0436f1acbb3e6 Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Fri, 17 Jul 2020 09:04:25 -0500 Subject: [PATCH 415/592] x86/unwind/orc: Fix ORC for newly forked tasks [ Upstream commit 372a8eaa05998cd45b3417d0e0ffd3a70978211a ] The ORC unwinder fails to unwind newly forked tasks which haven't yet run on the CPU. It correctly reads the 'ret_from_fork' instruction pointer from the stack, but it incorrectly interprets that value as a call stack address rather than a "signal" one, so the address gets incorrectly decremented in the call to orc_find(), resulting in bad ORC data. Fix it by forcing 'ret_from_fork' frames to be signal frames. Reported-by: Wang ShaoBo Signed-off-by: Josh Poimboeuf Signed-off-by: Thomas Gleixner Tested-by: Wang ShaoBo Link: https://lkml.kernel.org/r/f91a8778dde8aae7f71884b5df2b16d552040441.1594994374.git.jpoimboe@redhat.com Signed-off-by: Sasha Levin --- arch/x86/kernel/unwind_orc.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/unwind_orc.c b/arch/x86/kernel/unwind_orc.c index a9a55e76a43f..a5e2ce931f69 100644 --- a/arch/x86/kernel/unwind_orc.c +++ b/arch/x86/kernel/unwind_orc.c @@ -346,8 +346,11 @@ bool unwind_next_frame(struct unwind_state *state) /* * Find the orc_entry associated with the text address. * - * Decrement call return addresses by one so they work for sibling - * calls and calls to noreturn functions. + * For a call frame (as opposed to a signal frame), state->ip points to + * the instruction after the call. That instruction's stack layout + * could be different from the call instruction's layout, for example + * if the call was to a noreturn function. So get the ORC data for the + * call instruction itself. */ orc = orc_find(state->signal ? state->ip : state->ip - 1); if (!orc || orc->sp_reg == ORC_REG_UNDEFINED) @@ -550,6 +553,7 @@ void __unwind_start(struct unwind_state *state, struct task_struct *task, state->sp = task->thread.sp; state->bp = READ_ONCE_NOCHECK(frame->bp); state->ip = READ_ONCE_NOCHECK(frame->ret_addr); + state->signal = (void *)state->ip == ret_from_fork; } if (get_stack_info((unsigned long *)state->sp, state->task, From 11e2db546c1bf909a0381415590c45bb5fb88d12 Mon Sep 17 00:00:00 2001 From: Navid Emamdoost Date: Wed, 22 Jul 2020 21:58:39 -0500 Subject: [PATCH 416/592] cxgb4: add missing release on skb in uld_send() [ Upstream commit e6827d1abdc9b061a57d7b7d3019c4e99fabea2f ] In the implementation of uld_send(), the skb is consumed on all execution paths except one. Release skb when returning NET_XMIT_DROP. Signed-off-by: Navid Emamdoost Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- drivers/net/ethernet/chelsio/cxgb4/sge.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c index 0a5c4c7da505..006f8b8aaa7d 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c @@ -1812,6 +1812,7 @@ static inline int uld_send(struct adapter *adap, struct sk_buff *skb, txq_info = adap->sge.uld_txq_info[tx_uld_type]; if (unlikely(!txq_info)) { WARN_ON(true); + kfree_skb(skb); return NET_XMIT_DROP; } From d1245833e0d7652ed5e2a3545f976cf086ee87e0 Mon Sep 17 00:00:00 2001 From: Andrea Righi Date: Fri, 24 Jul 2020 10:59:10 +0200 Subject: [PATCH 417/592] xen-netfront: fix potential deadlock in xennet_remove() [ Upstream commit c2c633106453611be07821f53dff9e93a9d1c3f0 ] There's a potential race in xennet_remove(); this is what the driver is doing upon unregistering a network device: 1. state = read bus state 2. if state is not "Closed": 3. request to set state to "Closing" 4. wait for state to be set to "Closing" 5. request to set state to "Closed" 6. wait for state to be set to "Closed" If the state changes to "Closed" immediately after step 1 we are stuck forever in step 4, because the state will never go back from "Closed" to "Closing". Make sure to check also for state == "Closed" in step 4 to prevent the deadlock. Also add a 5 sec timeout any time we wait for the bus state to change, to avoid getting stuck forever in wait_event(). Signed-off-by: Andrea Righi Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- drivers/net/xen-netfront.c | 68 ++++++++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 24 deletions(-) diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index 91bf86cee273..1131397454bd 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -63,6 +63,8 @@ module_param_named(max_queues, xennet_max_queues, uint, 0644); MODULE_PARM_DESC(max_queues, "Maximum number of queues per virtual interface"); +#define XENNET_TIMEOUT (5 * HZ) + static const struct ethtool_ops xennet_ethtool_ops; struct netfront_cb { @@ -1336,12 +1338,15 @@ static struct net_device *xennet_create_dev(struct xenbus_device *dev) netif_carrier_off(netdev); - xenbus_switch_state(dev, XenbusStateInitialising); - wait_event(module_wq, - xenbus_read_driver_state(dev->otherend) != - XenbusStateClosed && - xenbus_read_driver_state(dev->otherend) != - XenbusStateUnknown); + do { + xenbus_switch_state(dev, XenbusStateInitialising); + err = wait_event_timeout(module_wq, + xenbus_read_driver_state(dev->otherend) != + XenbusStateClosed && + xenbus_read_driver_state(dev->otherend) != + XenbusStateUnknown, XENNET_TIMEOUT); + } while (!err); + return netdev; exit: @@ -2142,28 +2147,43 @@ static const struct attribute_group xennet_dev_group = { }; #endif /* CONFIG_SYSFS */ +static void xennet_bus_close(struct xenbus_device *dev) +{ + int ret; + + if (xenbus_read_driver_state(dev->otherend) == XenbusStateClosed) + return; + do { + xenbus_switch_state(dev, XenbusStateClosing); + ret = wait_event_timeout(module_wq, + xenbus_read_driver_state(dev->otherend) == + XenbusStateClosing || + xenbus_read_driver_state(dev->otherend) == + XenbusStateClosed || + xenbus_read_driver_state(dev->otherend) == + XenbusStateUnknown, + XENNET_TIMEOUT); + } while (!ret); + + if (xenbus_read_driver_state(dev->otherend) == XenbusStateClosed) + return; + + do { + xenbus_switch_state(dev, XenbusStateClosed); + ret = wait_event_timeout(module_wq, + xenbus_read_driver_state(dev->otherend) == + XenbusStateClosed || + xenbus_read_driver_state(dev->otherend) == + XenbusStateUnknown, + XENNET_TIMEOUT); + } while (!ret); +} + static int xennet_remove(struct xenbus_device *dev) { struct netfront_info *info = dev_get_drvdata(&dev->dev); - dev_dbg(&dev->dev, "%s\n", dev->nodename); - - if (xenbus_read_driver_state(dev->otherend) != XenbusStateClosed) { - xenbus_switch_state(dev, XenbusStateClosing); - wait_event(module_wq, - xenbus_read_driver_state(dev->otherend) == - XenbusStateClosing || - xenbus_read_driver_state(dev->otherend) == - XenbusStateUnknown); - - xenbus_switch_state(dev, XenbusStateClosed); - wait_event(module_wq, - xenbus_read_driver_state(dev->otherend) == - XenbusStateClosed || - xenbus_read_driver_state(dev->otherend) == - XenbusStateUnknown); - } - + xennet_bus_close(dev); xennet_disconnect_backend(info); if (info->netdev->reg_state == NETREG_REGISTERED) From ba53d9deccbac6e0670bd9b1849663ecda54d648 Mon Sep 17 00:00:00 2001 From: Wanpeng Li Date: Fri, 31 Jul 2020 11:12:19 +0800 Subject: [PATCH 418/592] KVM: LAPIC: Prevent setting the tscdeadline timer if the lapic is hw disabled commit d2286ba7d574ba3103a421a2f9ec17cb5b0d87a1 upstream. Prevent setting the tscdeadline timer if the lapic is hw disabled. Fixes: bce87cce88 (KVM: x86: consolidate different ways to test for in-kernel LAPIC) Cc: Signed-off-by: Wanpeng Li Message-Id: <1596165141-28874-1-git-send-email-wanpengli@tencent.com> Signed-off-by: Paolo Bonzini Signed-off-by: Greg Kroah-Hartman --- arch/x86/kvm/lapic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 537c36b55b5d..d4fdf0e52144 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -1918,7 +1918,7 @@ void kvm_set_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu, u64 data) { struct kvm_lapic *apic = vcpu->arch.apic; - if (!lapic_in_kernel(vcpu) || apic_lvtt_oneshot(apic) || + if (!kvm_apic_present(vcpu) || apic_lvtt_oneshot(apic) || apic_lvtt_period(apic)) return; From ba6e4d6a92c9d02153861e5693665d4a89caf5d0 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 29 Jul 2020 10:53:28 +0200 Subject: [PATCH 419/592] x86/i8259: Use printk_deferred() to prevent deadlock commit bdd65589593edd79b6a12ce86b3b7a7c6dae5208 upstream. 0day reported a possible circular locking dependency: Chain exists of: &irq_desc_lock_class --> console_owner --> &port_lock_key Possible unsafe locking scenario: CPU0 CPU1 ---- ---- lock(&port_lock_key); lock(console_owner); lock(&port_lock_key); lock(&irq_desc_lock_class); The reason for this is a printk() in the i8259 interrupt chip driver which is invoked with the irq descriptor lock held, which reverses the lock operations vs. printk() from arbitrary contexts. Switch the printk() to printk_deferred() to avoid that. Reported-by: kernel test robot Signed-off-by: Thomas Gleixner Signed-off-by: Ingo Molnar Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/87365abt2v.fsf@nanos.tec.linutronix.de Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/i8259.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/i8259.c b/arch/x86/kernel/i8259.c index 02abc134367f..f7833ae4e3f1 100644 --- a/arch/x86/kernel/i8259.c +++ b/arch/x86/kernel/i8259.c @@ -206,7 +206,7 @@ spurious_8259A_irq: * lets ACK and report it. [once per IRQ] */ if (!(spurious_irq_mask & irqmask)) { - printk(KERN_DEBUG + printk_deferred(KERN_DEBUG "spurious 8259A interrupt: IRQ%d.\n", irq); spurious_irq_mask |= irqmask; } From ca4f2c56d4162a4a5236f2099b55453fb98296f9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 5 Aug 2020 10:06:53 +0200 Subject: [PATCH 420/592] Linux 4.14.192 Tested-by: Shuah Khan Signed-off-by: Greg Kroah-Hartman --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index e31c1ce12895..60570fad811e 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 VERSION = 4 PATCHLEVEL = 14 -SUBLEVEL = 191 +SUBLEVEL = 192 EXTRAVERSION = NAME = Petit Gorille From cb5f044f808d04436f87263aa33fae96def862d4 Mon Sep 17 00:00:00 2001 From: UtsavBalar1231 Date: Mon, 3 Aug 2020 12:27:29 +0530 Subject: [PATCH 421/592] cpufreq: squash revert cpu_input_boost support Revert "cpu_input_boost: add prime core support" Revert "cpu_input_boost: rewrite update_online_cpu_policy function" Revert "cpu_input_boost: disable input boost of duration==0" Revert "cpu_input_boost: add sm8150 support" Revert "cpu_input_boost: add support for boost freqs lower than min freq" Revert "cpu_input_boost: Mark boost kthread as performance critical" Revert "cpu_input_boost: Introduce driver for event-based CPU boosting" Revert "kernel: Boost to the max for a short amount of time when zygote forks" Revert "kernel: Boost whenever a zygote-forked process becomes a top app" Signed-off-by: UtsavBalar1231 --- drivers/cpufreq/Kconfig | 61 ----- drivers/cpufreq/Makefile | 3 - drivers/cpufreq/cpu_input_boost.c | 375 ------------------------------ include/linux/cpu_input_boost.h | 20 -- kernel/cgroup/cgroup-v1.c | 9 - kernel/fork.c | 9 - mm/page_alloc.c | 2 - 7 files changed, 479 deletions(-) delete mode 100644 drivers/cpufreq/cpu_input_boost.c delete mode 100644 include/linux/cpu_input_boost.h diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index 4597d3232709..6cfaaeb2e79a 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -250,67 +250,6 @@ config CPU_FREQ_GOV_INTERACTIVE If in doubt, say N. -config CPU_INPUT_BOOST - bool "CPU Input Boost" - help - Boosts the CPU on touchscreen and touchpad input, and allows for - boosting on other custom events, mainly which is intended to be for - boosting when there is a new frame ready to be rendered to the - display. The boost frequencies for this driver should be set so that - frame drops are near-zero at the boosted frequencies and power - consumption is minimized at said frequency combination. - -if CPU_INPUT_BOOST - -config INPUT_BOOST_DURATION_MS - int "Input boost duration" - default "100" - help - Input boost duration in milliseconds. - -config WAKE_BOOST_DURATION_MS - int "Wake boost duration" - default "1000" - help - Wake boost duration in milliseconds. - -config INPUT_BOOST_FREQ_LP - int "Low-power cluster boost freq" - default "0" - help - Input boost frequency for the low-power CPU cluster. - -config INPUT_BOOST_FREQ_PERF - int "Performance cluster boost freq" - default "0" - help - Input boost frequency for the performance CPU cluster. - -config MAX_BOOST_FREQ_LP - int "Low-power cluster max-boost freq" - default "0" - help - Max-boost frequency for the low-power CPU cluster. - -config MAX_BOOST_FREQ_PERF - int "Performance cluster max-boost freq" - default "0" - help - Max-boost frequency for the performance CPU cluster. - -config MIN_FREQ_LP - int "LP cluster min boost to set after boost" - default "0" - help - Min freq to set for lp cluster when boost is over. - -config MIN_FREQ_PERF - int "HP cluster min boost to set after boost" - default "0" - help - Min freq to set for hp cluster when boost is over. -endif - comment "CPU frequency scaling drivers" config CPUFREQ_DT diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index c5abbf7aa58a..6d92de038fdc 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -19,9 +19,6 @@ obj-$(CONFIG_CPU_FREQ_GOV_COMMON) += cpufreq_governor.o obj-$(CONFIG_CPU_FREQ_GOV_ATTR_SET) += cpufreq_governor_attr_set.o obj-$(CONFIG_CPU_BOOST) += cpu-boost.o -# CPU Input Boost -obj-$(CONFIG_CPU_INPUT_BOOST) += cpu_input_boost.o - obj-$(CONFIG_CPUFREQ_DT) += cpufreq-dt.o obj-$(CONFIG_CPUFREQ_DT_PLATDEV) += cpufreq-dt-platdev.o diff --git a/drivers/cpufreq/cpu_input_boost.c b/drivers/cpufreq/cpu_input_boost.c deleted file mode 100644 index bf158fb06951..000000000000 --- a/drivers/cpufreq/cpu_input_boost.c +++ /dev/null @@ -1,375 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) 2018-2019 Sultan Alsawaf . - */ - -#define pr_fmt(fmt) "cpu_input_boost: " fmt - -#include -#include -#include -#include -#include -#include -#include - -/* The sched_param struct is located elsewhere in newer kernels */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0) -#include -#endif - -enum { - SCREEN_OFF, - INPUT_BOOST, - MAX_BOOST -}; - -struct boost_drv { - struct delayed_work input_unboost; - struct delayed_work max_unboost; - struct notifier_block cpu_notif; - struct notifier_block msm_drm_notif; - wait_queue_head_t boost_waitq; - atomic_long_t max_boost_expires; - unsigned long state; -}; - -static void input_unboost_worker(struct work_struct *work); -static void max_unboost_worker(struct work_struct *work); - -static struct boost_drv boost_drv_g __read_mostly = { - .input_unboost = __DELAYED_WORK_INITIALIZER(boost_drv_g.input_unboost, - input_unboost_worker, 0), - .max_unboost = __DELAYED_WORK_INITIALIZER(boost_drv_g.max_unboost, - max_unboost_worker, 0), - .boost_waitq = __WAIT_QUEUE_HEAD_INITIALIZER(boost_drv_g.boost_waitq) -}; - -static unsigned int get_input_boost_freq(struct cpufreq_policy *policy) -{ - unsigned int freq; - - if (cpumask_test_cpu(policy->cpu, cpu_lp_mask)) - freq = max(CONFIG_INPUT_BOOST_FREQ_LP, CONFIG_MIN_FREQ_LP); - else if (cpumask_test_cpu(policy->cpu, cpu_perf_mask)) - freq = max(CONFIG_INPUT_BOOST_FREQ_PERF, CONFIG_MIN_FREQ_PERF); - else - freq = policy->min; - - return min(freq, policy->max); -} - -static unsigned int get_max_boost_freq(struct cpufreq_policy *policy) -{ - unsigned int freq; - - if (cpumask_test_cpu(policy->cpu, cpu_lp_mask)) - freq = CONFIG_MAX_BOOST_FREQ_LP; - else - freq = CONFIG_MAX_BOOST_FREQ_PERF; - - return min(freq, policy->max); -} - -static void update_online_cpu_policy(void) -{ - unsigned int cpu; - - get_online_cpus(); - for_each_possible_cpu(cpu) { - if (cpu_online(cpu)) { - if (cpumask_intersects(cpumask_of(cpu), cpu_lp_mask)) - cpufreq_update_policy(cpu); - if (cpumask_intersects(cpumask_of(cpu), cpu_perf_mask)) - cpufreq_update_policy(cpu); - if (cpumask_intersects(cpumask_of(cpu), cpu_perfp_mask)) - cpufreq_update_policy(cpu); - } - } - put_online_cpus(); -} - -static void __cpu_input_boost_kick(struct boost_drv *b) -{ - if (test_bit(SCREEN_OFF, &b->state) || (CONFIG_INPUT_BOOST_DURATION_MS == 0)) - return; - - set_bit(INPUT_BOOST, &b->state); - if (!mod_delayed_work(system_unbound_wq, &b->input_unboost, - msecs_to_jiffies(CONFIG_INPUT_BOOST_DURATION_MS))) - wake_up(&b->boost_waitq); -} - -void cpu_input_boost_kick(void) -{ - struct boost_drv *b = &boost_drv_g; - - __cpu_input_boost_kick(b); -} - -static void __cpu_input_boost_kick_max(struct boost_drv *b, - unsigned int duration_ms) -{ - unsigned long boost_jiffies = msecs_to_jiffies(duration_ms); - unsigned long curr_expires, new_expires; - - if (test_bit(SCREEN_OFF, &b->state)) - return; - - do { - curr_expires = atomic_long_read(&b->max_boost_expires); - new_expires = jiffies + boost_jiffies; - - /* Skip this boost if there's a longer boost in effect */ - if (time_after(curr_expires, new_expires)) - return; - } while (atomic_long_cmpxchg(&b->max_boost_expires, curr_expires, - new_expires) != curr_expires); - - set_bit(MAX_BOOST, &b->state); - if (!mod_delayed_work(system_unbound_wq, &b->max_unboost, - boost_jiffies)) - wake_up(&b->boost_waitq); -} - -void cpu_input_boost_kick_max(unsigned int duration_ms) -{ - struct boost_drv *b = &boost_drv_g; - - __cpu_input_boost_kick_max(b, duration_ms); -} - -static void input_unboost_worker(struct work_struct *work) -{ - struct boost_drv *b = container_of(to_delayed_work(work), - typeof(*b), input_unboost); - - clear_bit(INPUT_BOOST, &b->state); - wake_up(&b->boost_waitq); -} - -static void max_unboost_worker(struct work_struct *work) -{ - struct boost_drv *b = container_of(to_delayed_work(work), - typeof(*b), max_unboost); - - clear_bit(MAX_BOOST, &b->state); - wake_up(&b->boost_waitq); -} - -static int cpu_boost_thread(void *data) -{ - static const struct sched_param sched_max_rt_prio = { - .sched_priority = MAX_RT_PRIO - 1 - }; - struct boost_drv *b = data; - unsigned long old_state = 0; - - sched_setscheduler_nocheck(current, SCHED_FIFO, &sched_max_rt_prio); - - while (1) { - bool should_stop = false; - unsigned long curr_state; - - wait_event(b->boost_waitq, - (curr_state = READ_ONCE(b->state)) != old_state || - (should_stop = kthread_should_stop())); - - if (should_stop) - break; - - old_state = curr_state; - update_online_cpu_policy(); - } - - return 0; -} - -static int cpu_notifier_cb(struct notifier_block *nb, unsigned long action, - void *data) -{ - struct boost_drv *b = container_of(nb, typeof(*b), cpu_notif); - struct cpufreq_policy *policy = data; - - if (action != CPUFREQ_ADJUST) - return NOTIFY_OK; - - /* Unboost when the screen is off */ - if (test_bit(SCREEN_OFF, &b->state)) { - policy->min = policy->cpuinfo.min_freq; - return NOTIFY_OK; - } - - /* Boost CPU to max frequency for max boost */ - if (test_bit(MAX_BOOST, &b->state)) { - policy->min = get_max_boost_freq(policy); - return NOTIFY_OK; - } - - /* - * Boost to policy->max if the boost frequency is higher. When - * unboosting, set policy->min to the absolute min freq for the CPU. - */ - if (test_bit(INPUT_BOOST, &b->state)) - policy->min = get_input_boost_freq(policy); - else if (cpumask_test_cpu(policy->cpu, cpu_lp_mask)) - policy->min = CONFIG_MIN_FREQ_LP; - else if (cpumask_test_cpu(policy->cpu, cpu_perf_mask)) - policy->min = CONFIG_MIN_FREQ_PERF; - else - policy->min = policy->cpuinfo.min_freq; - - return NOTIFY_OK; -} - -static int msm_drm_notifier_cb(struct notifier_block *nb, unsigned long action, - void *data) -{ - struct boost_drv *b = container_of(nb, typeof(*b), msm_drm_notif); - struct msm_drm_notifier *evdata = data; - int *blank = evdata->data; - - /* Parse framebuffer blank events as soon as they occur */ - if (action != MSM_DRM_EARLY_EVENT_BLANK) - return NOTIFY_OK; - - /* Boost when the screen turns on and unboost when it turns off */ - if (*blank == MSM_DRM_BLANK_UNBLANK) { - clear_bit(SCREEN_OFF, &b->state); - __cpu_input_boost_kick_max(b, CONFIG_WAKE_BOOST_DURATION_MS); - } else { - set_bit(SCREEN_OFF, &b->state); - wake_up(&b->boost_waitq); - } - - return NOTIFY_OK; -} - -static void cpu_input_boost_input_event(struct input_handle *handle, - unsigned int type, unsigned int code, - int value) -{ - struct boost_drv *b = handle->handler->private; - - __cpu_input_boost_kick(b); -} - -static int cpu_input_boost_input_connect(struct input_handler *handler, - struct input_dev *dev, - const struct input_device_id *id) -{ - struct input_handle *handle; - int ret; - - handle = kzalloc(sizeof(*handle), GFP_KERNEL); - if (!handle) - return -ENOMEM; - - handle->dev = dev; - handle->handler = handler; - handle->name = "cpu_input_boost_handle"; - - ret = input_register_handle(handle); - if (ret) - goto free_handle; - - ret = input_open_device(handle); - if (ret) - goto unregister_handle; - - return 0; - -unregister_handle: - input_unregister_handle(handle); -free_handle: - kfree(handle); - return ret; -} - -static void cpu_input_boost_input_disconnect(struct input_handle *handle) -{ - input_close_device(handle); - input_unregister_handle(handle); - kfree(handle); -} - -static const struct input_device_id cpu_input_boost_ids[] = { - /* Multi-touch touchscreen */ - { - .flags = INPUT_DEVICE_ID_MATCH_EVBIT | - INPUT_DEVICE_ID_MATCH_ABSBIT, - .evbit = { BIT_MASK(EV_ABS) }, - .absbit = { [BIT_WORD(ABS_MT_POSITION_X)] = - BIT_MASK(ABS_MT_POSITION_X) | - BIT_MASK(ABS_MT_POSITION_Y) } - }, - /* Touchpad */ - { - .flags = INPUT_DEVICE_ID_MATCH_KEYBIT | - INPUT_DEVICE_ID_MATCH_ABSBIT, - .keybit = { [BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH) }, - .absbit = { [BIT_WORD(ABS_X)] = - BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) } - }, - /* Keypad */ - { - .flags = INPUT_DEVICE_ID_MATCH_EVBIT, - .evbit = { BIT_MASK(EV_KEY) } - }, - { } -}; - -static struct input_handler cpu_input_boost_input_handler = { - .event = cpu_input_boost_input_event, - .connect = cpu_input_boost_input_connect, - .disconnect = cpu_input_boost_input_disconnect, - .name = "cpu_input_boost_handler", - .id_table = cpu_input_boost_ids -}; - -static int __init cpu_input_boost_init(void) -{ - struct boost_drv *b = &boost_drv_g; - struct task_struct *thread; - int ret; - - b->cpu_notif.notifier_call = cpu_notifier_cb; - ret = cpufreq_register_notifier(&b->cpu_notif, CPUFREQ_POLICY_NOTIFIER); - if (ret) { - pr_err("Failed to register cpufreq notifier, err: %d\n", ret); - return ret; - } - - cpu_input_boost_input_handler.private = b; - ret = input_register_handler(&cpu_input_boost_input_handler); - if (ret) { - pr_err("Failed to register input handler, err: %d\n", ret); - goto unregister_cpu_notif; - } - - b->msm_drm_notif.notifier_call = msm_drm_notifier_cb; - b->msm_drm_notif.priority = INT_MAX; - ret = msm_drm_register_client(&b->msm_drm_notif); - if (ret) { - pr_err("Failed to register msm_drm notifier, err: %d\n", ret); - goto unregister_handler; - } - - thread = kthread_run_perf_critical(cpu_boost_thread, b, "cpu_boostd"); - if (IS_ERR(thread)) { - ret = PTR_ERR(thread); - pr_err("Failed to start CPU boost thread, err: %d\n", ret); - goto unregister_fb_notif; - } - - return 0; - -unregister_fb_notif: - msm_drm_unregister_client(&b->msm_drm_notif); -unregister_handler: - input_unregister_handler(&cpu_input_boost_input_handler); -unregister_cpu_notif: - cpufreq_unregister_notifier(&b->cpu_notif, CPUFREQ_POLICY_NOTIFIER); - return ret; -} -subsys_initcall(cpu_input_boost_init); diff --git a/include/linux/cpu_input_boost.h b/include/linux/cpu_input_boost.h deleted file mode 100644 index a988039ffd7d..000000000000 --- a/include/linux/cpu_input_boost.h +++ /dev/null @@ -1,20 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (C) 2018-2019 Sultan Alsawaf . - */ -#ifndef _CPU_INPUT_BOOST_H_ -#define _CPU_INPUT_BOOST_H_ - -#ifdef CONFIG_CPU_INPUT_BOOST -void cpu_input_boost_kick(void); -void cpu_input_boost_kick_max(unsigned int duration_ms); -#else -static inline void cpu_input_boost_kick(void) -{ -} -static inline void cpu_input_boost_kick_max(unsigned int duration_ms) -{ -} -#endif - -#endif /* _CPU_INPUT_BOOST_H_ */ diff --git a/kernel/cgroup/cgroup-v1.c b/kernel/cgroup/cgroup-v1.c index 226d0d47e13f..1d166be184f7 100644 --- a/kernel/cgroup/cgroup-v1.c +++ b/kernel/cgroup/cgroup-v1.c @@ -13,8 +13,6 @@ #include #include #include -#include -#include #include @@ -553,13 +551,6 @@ static ssize_t __cgroup1_procs_write(struct kernfs_open_file *of, ret = cgroup_attach_task(cgrp, task, threadgroup); - /* This covers boosting for app launches and app transitions */ - if (!ret && !threadgroup && - !memcmp(of->kn->parent->name, "top-app", sizeof("top-app")) && - is_zygote_pid(task->parent->pid)) { - cpu_input_boost_kick_max(1000); - } - out_finish: cgroup_procs_write_finish(task); out_unlock: diff --git a/kernel/fork.c b/kernel/fork.c index 2e3225a6d286..17a5cc8e7880 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -94,8 +94,6 @@ #include #include #include -#include -#include #include #include @@ -2208,13 +2206,6 @@ long _do_fork(unsigned long clone_flags, int trace = 0; long nr; - /* Boost CPU to the max for 150 ms when userspace launches an app */ - if (is_zygote_pid(current->pid)) { - cpu_input_boost_kick_max(150); - devfreq_boost_kick_max(DEVFREQ_MSM_CPUBW, 150); - devfreq_boost_kick_max(DEVFREQ_MSM_LLCCBW, 150); - } - /* * Determine whether and which event to report to ptracer. When * called from kernel_thread or CLONE_UNTRACED is explicitly diff --git a/mm/page_alloc.c b/mm/page_alloc.c index a187d347eeb5..18e2e8a0ad49 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -69,7 +69,6 @@ #include #include #include -#include #include #include @@ -4224,7 +4223,6 @@ retry: goto nopage; /* Boost when memory is low so allocation latency doesn't get too bad */ - cpu_input_boost_kick_max(100); devfreq_boost_kick_max(DEVFREQ_MSM_LLCCBW, 100); devfreq_boost_kick_max(DEVFREQ_MSM_CPUBW, 100); From 3588cb8f72a4ea39417dc2b0d7a1807d442f43e5 Mon Sep 17 00:00:00 2001 From: Danny Lin Date: Mon, 5 Aug 2019 05:52:04 +0000 Subject: [PATCH 422/592] cpufreq: Kill userspace CPU boosting entirely Kernel-based CPU boosting is used now, so stop userspace from messing with it by turning scaling_min_freq into a no-op. Note that this is done instead of making scaling_min_freq read-only so that userspace doesn't spit out error messages when it can't do its boosting. Signed-off-by: Sultan Alsawaf Signed-off-by: Danny Lin Signed-off-by: UtsavBalar1231 --- drivers/cpufreq/cpufreq.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index a9c484519369..db33268b47fa 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -727,6 +727,9 @@ static ssize_t store_##file_name \ int ret, temp; \ struct cpufreq_policy new_policy; \ \ + if (&policy->object == &policy->min) \ + return count; \ + \ memcpy(&new_policy, policy, sizeof(*policy)); \ new_policy.min = policy->user_policy.min; \ new_policy.max = policy->user_policy.max; \ From f67dd314b6db4b63eb169a588793225ad6573f1b Mon Sep 17 00:00:00 2001 From: Danny Lin Date: Sun, 4 Aug 2019 07:39:15 +0000 Subject: [PATCH 423/592] cpufreq: Only block min freq setting for booster processes Signed-off-by: Danny Lin Signed-off-by: UtsavBalar1231 --- drivers/cpufreq/cpufreq.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index db33268b47fa..6bcbf1d36475 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -18,6 +18,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include #include #include #include @@ -727,7 +728,8 @@ static ssize_t store_##file_name \ int ret, temp; \ struct cpufreq_policy new_policy; \ \ - if (&policy->object == &policy->min) \ + if (&policy->object == &policy->min && \ + task_is_booster(current)) \ return count; \ \ memcpy(&new_policy, policy, sizeof(*policy)); \ From c52d0b68a4c1bf1a40694c323c514bf9af3c63c4 Mon Sep 17 00:00:00 2001 From: Danny Lin Date: Mon, 2 Sep 2019 21:32:56 -0700 Subject: [PATCH 424/592] cpufreq: Allow configuring default minimum frequencies in Kconfig This adds config options that set the default minimum frequency for the little, big, and prime CPU clusters. Signed-off-by: Danny Lin Signed-off-by: UtsavBalar1231 --- drivers/cpufreq/Kconfig | 27 +++++++++++++++++++++++++++ drivers/cpufreq/freq_table.c | 13 +++++++++++++ 2 files changed, 40 insertions(+) diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index 6cfaaeb2e79a..ed23aacc7258 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -250,6 +250,33 @@ config CPU_FREQ_GOV_INTERACTIVE If in doubt, say N. +config CPU_FREQ_DEFAULT_LITTLE_MIN + int "Default minimum frequency for the little cluster" + default 0 + help + This sets the default minimum frequency (in kHz) for the little CPU + cluster. + + If in doubt, say 0 to use the hardware's minimum frequency. + +config CPU_FREQ_DEFAULT_BIG_MIN + int "Default minimum frequency for the big cluster" + default 0 + help + This sets the default minimum frequency (in kHz) for the big CPU + cluster. + + If in doubt, say 0 to use the hardware's minimum frequency. + +config CPU_FREQ_DEFAULT_PRIME_MIN + int "Default minimum frequency for the prime cluster" + default 0 + help + This sets the default minimum frequency (in kHz) for the prime CPU + cluster. + + If in doubt, say 0 to use the hardware's minimum frequency. + comment "CPU frequency scaling drivers" config CPUFREQ_DT diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c index 7f205ec61244..060b5c03ea9c 100644 --- a/drivers/cpufreq/freq_table.c +++ b/drivers/cpufreq/freq_table.c @@ -61,6 +61,19 @@ int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy, if (max_freq > cpuinfo_max_freq_cached) cpuinfo_max_freq_cached = max_freq; +#if CONFIG_CPU_FREQ_DEFAULT_LITTLE_MIN + if (cpumask_test_cpu(policy->cpu, cpu_lp_mask)) + policy->min = CONFIG_CPU_FREQ_DEFAULT_LITTLE_MIN; +#endif +#if CONFIG_CPU_FREQ_DEFAULT_BIG_MIN + if (cpumask_test_cpu(policy->cpu, cpu_perf_mask)) + policy->min = CONFIG_CPU_FREQ_DEFAULT_BIG_MIN; +#endif +#if CONFIG_CPU_FREQ_DEFAULT_PRIME_MIN + if (cpumask_test_cpu(policy->cpu, cpu_perfp_mask)) + policy->min = CONFIG_CPU_FREQ_DEFAULT_PRIME_MIN; +#endif + if (policy->min == ~0) return -EINVAL; else From 363f5923d54f94c4f548af7f36f6692c15211ba2 Mon Sep 17 00:00:00 2001 From: Danny Lin Date: Mon, 2 Sep 2019 21:33:39 -0700 Subject: [PATCH 425/592] ARM64: configs: raphael: Configure optimal minimum CPU frequencies for sm8150 These frequencies have been selected by weighing absolute power usage vs. efficiency (mW/perf -- the lower the better) for all the frequencies available on each cluster. Performance was measured by running an in-kernel RC4 benchmark simultaneously on all the cores in a cluster (minus one for housekeeping, except Prime where the first core of the little cluster was used for housekeeping). Power usage was measured while the benchmark was running using the integrated PMIC (PM8150B v2.0). 768000 kHz, 1056000 kHz, and 1171200 kHz have each been selected by looking for the most efficient frequency with a relatively low power usage. That is, when mW/perf and power usage (mW) are graphed together, the ideal frequency is one with very low mW/perf and mW, such that the lines are intersecting. Since this is obviously not possible in practice, we look for the frequency closest to matching this description. We aren't using the *most* efficient freqs because PM QoS abuse and high overall CPU usage causes higher drain on them by reducing deep idle time and utilizing the CPU more, which makes the frequency's high absolute power usage show. As a result of this careful selection, the new frequencies should benefit both performance *and* battery endurance in real-world scenarios. Full data with graphs: https://docs.google.com/spreadsheets/d/1gOG4MVDzOvfAtXzifL0EQm-BPHdGkZ9SHThybRpm6R8/edit Thanks to Sultan Alsawaf (kerneltoast) for creating the benchmark used in this test. Signed-off-by: Danny Lin Signed-off-by: UtsavBalar1231 --- arch/arm64/configs/raphael_defconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/configs/raphael_defconfig b/arch/arm64/configs/raphael_defconfig index 5548e5273587..b1dd6d16205a 100644 --- a/arch/arm64/configs/raphael_defconfig +++ b/arch/arm64/configs/raphael_defconfig @@ -737,6 +737,9 @@ CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y CONFIG_SCHEDUTIL_UP_RATE_LIMIT=500 CONFIG_SCHEDUTIL_DOWN_RATE_LIMIT=20000 # CONFIG_CPU_FREQ_GOV_INTERACTIVE is not set +CONFIG_CPU_FREQ_DEFAULT_LITTLE_MIN=768000 +CONFIG_CPU_FREQ_DEFAULT_BIG_MIN=1056000 +CONFIG_CPU_FREQ_DEFAULT_PRIME_MIN=1171200 # # CPU frequency scaling drivers From 8e639c1f3ff7ec34d127b4c060be6d6916e1acd4 Mon Sep 17 00:00:00 2001 From: Danny Lin Date: Mon, 5 Aug 2019 06:45:05 +0000 Subject: [PATCH 426/592] cpufreq: schedutil: Expose default rate-limits as config options This allows us to tune the default rate-limits without constantly changing schedutil's code. Signed-off-by: Danny Lin Signed-off-by: UtsavBalar1231 --- drivers/cpufreq/Kconfig | 18 ++++++++++++++++++ kernel/sched/cpufreq_schedutil.c | 4 ++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index ed23aacc7258..db8c2890accd 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -230,6 +230,24 @@ config CPU_FREQ_GOV_SCHEDUTIL If in doubt, say N. +if CPU_FREQ_GOV_SCHEDUTIL + +config SCHEDUTIL_UP_RATE_LIMIT + int "Default up rate-limit for schedutil" + default 1000 + help + This sets schedutil's default frequency up rate-limit in + microseconds. + +config SCHEDUTIL_DOWN_RATE_LIMIT + int "Default down rate-limit for schedutil" + default 1000 + help + This sets schedutil's default frequency down rate-limit in + microseconds. + +endif + config CPU_FREQ_GOV_INTERACTIVE tristate "'interactive' cpufreq policy governor" depends on CPU_FREQ diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c index be341e726c4f..156d87de575e 100644 --- a/kernel/sched/cpufreq_schedutil.c +++ b/kernel/sched/cpufreq_schedutil.c @@ -1048,9 +1048,9 @@ static int sugov_init(struct cpufreq_policy *policy) } tunables->up_rate_limit_us = - cpufreq_policy_transition_delay_us(policy); + CONFIG_SCHEDUTIL_UP_RATE_LIMIT; tunables->down_rate_limit_us = - cpufreq_policy_transition_delay_us(policy); + CONFIG_SCHEDUTIL_DOWN_RATE_LIMIT; tunables->hispeed_load = DEFAULT_HISPEED_LOAD; tunables->hispeed_freq = 0; tunables->iowait_boost_enable = false; From 1c7f27c51e40702525c28db42395600e342e985a Mon Sep 17 00:00:00 2001 From: Danny Lin Date: Sun, 4 Aug 2019 04:50:50 +0000 Subject: [PATCH 427/592] ARM64: configs: raphael: Enable and configure cpuset assist These cpusets are derived from the Pixel 3's stock cpusets and tuned to accomodate the new Prime cluster on sm8150. Signed-off-by: Danny Lin Signed-off-by: UtsavBalar1231 --- arch/arm64/configs/raphael_defconfig | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/arm64/configs/raphael_defconfig b/arch/arm64/configs/raphael_defconfig index b1dd6d16205a..a8fc34e2ad5d 100644 --- a/arch/arm64/configs/raphael_defconfig +++ b/arch/arm64/configs/raphael_defconfig @@ -167,7 +167,14 @@ CONFIG_PID_NS=y CONFIG_NET_NS=y # CONFIG_SCHED_AUTOGROUP is not set CONFIG_SCHED_TUNE=y -# CONFIG_CPUSETS_ASSIST is not set +CONFIG_CPUSETS_ASSIST=y +CONFIG_CPUSET_AUDIO_APP="0-3,5-6" +CONFIG_CPUSET_BG="0-1" +CONFIG_CPUSET_CAMERA="0-3,6-7" +CONFIG_CPUSET_FG="0-3,5-6" +CONFIG_CPUSET_RESTRICTED="0-3" +CONFIG_CPUSET_SYSTEM_BG="0-3" +CONFIG_CPUSET_TOP_APP="0-7" CONFIG_DEFAULT_USE_ENERGY_AWARE=y # CONFIG_SYSFS_DEPRECATED is not set # CONFIG_RELAY is not set From 6c2870d2511b81cafdbf8a7d84a4fd315029e38a Mon Sep 17 00:00:00 2001 From: UtsavBalar1231 Date: Wed, 5 Aug 2020 20:14:18 +0530 Subject: [PATCH 428/592] ARM64: configs: raphael: adjust cpusets Signed-off-by: UtsavBalar1231 --- arch/arm64/configs/raphael_defconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/configs/raphael_defconfig b/arch/arm64/configs/raphael_defconfig index a8fc34e2ad5d..46180b50011b 100644 --- a/arch/arm64/configs/raphael_defconfig +++ b/arch/arm64/configs/raphael_defconfig @@ -170,10 +170,10 @@ CONFIG_SCHED_TUNE=y CONFIG_CPUSETS_ASSIST=y CONFIG_CPUSET_AUDIO_APP="0-3,5-6" CONFIG_CPUSET_BG="0-1" -CONFIG_CPUSET_CAMERA="0-3,6-7" +CONFIG_CPUSET_CAMERA="0-7" CONFIG_CPUSET_FG="0-3,5-6" CONFIG_CPUSET_RESTRICTED="0-3" -CONFIG_CPUSET_SYSTEM_BG="0-3" +CONFIG_CPUSET_SYSTEM_BG="0-3,5-6" CONFIG_CPUSET_TOP_APP="0-7" CONFIG_DEFAULT_USE_ENERGY_AWARE=y # CONFIG_SYSFS_DEPRECATED is not set From 60ad3f6f00d7e41323e8f3013f565487431cd1a5 Mon Sep 17 00:00:00 2001 From: Danny Lin Date: Sun, 2 Aug 2020 01:30:58 -0700 Subject: [PATCH 429/592] Revert "kbuild: Add support for LLVM's Polly optimizer" This reverts commit 00f711eead4238d13ccf0affe01f08616f707881. This is completely useless (no measurable performance gain when accounting for noise) and likely to introduce silent breakage in some places. Signed-off-by: Danny Lin Signed-off-by: UtsavBalar1231 --- Makefile | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/Makefile b/Makefile index fc0517d2c4bf..ab8e85b973c8 100644 --- a/Makefile +++ b/Makefile @@ -737,17 +737,6 @@ endif ifeq ($(cc-name),clang) KBUILD_CFLAGS += -O3 KBUILD_CFLAGS += $(call cc-option, -mcpu=cortex-a55 -mtune=cortex-a55) - -ifdef CONFIG_LLVM_POLLY -KBUILD_CFLAGS += -mllvm -polly \ - -mllvm -polly-run-dce \ - -mllvm -polly-run-inliner \ - -mllvm -polly-opt-fusion=max \ - -mllvm -polly-ast-use-context \ - -mllvm -polly-detect-keep-going \ - -mllvm -polly-vectorizer=stripmine \ - -mllvm -polly-invariant-load-hoisting -endif endif endif From e510960c4ccdb2a46246daacb42b5ece35da89b9 Mon Sep 17 00:00:00 2001 From: Danny Lin Date: Thu, 30 Jul 2020 15:55:53 -0700 Subject: [PATCH 430/592] arm64: dts: sm8150: Don't ratelimit userspace kmsg logging Ratelimiting messages from init and fsck.f2fs make early userspace boot debugging much more difficult for no good reason. Signed-off-by: Danny Lin Signed-off-by: UtsavBalar1231 --- arch/arm64/boot/dts/qcom/sm8150.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/sm8150.dtsi b/arch/arm64/boot/dts/qcom/sm8150.dtsi index e1b09781d813..800f8a26abb7 100644 --- a/arch/arm64/boot/dts/qcom/sm8150.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150.dtsi @@ -550,7 +550,7 @@ }; chosen { - bootargs = "rcu_nocbs=0-7 cgroup.memory=nokmem,nosocket noirqdebug"; + bootargs = "rcu_nocbs=0-7 cgroup.memory=nokmem,nosocket noirqdebug printk.devkmsg=on"; }; soc: soc { }; From e727c45645e06c7e631e851db2d8f972ece2569c Mon Sep 17 00:00:00 2001 From: Danny Lin Date: Sat, 1 Aug 2020 23:32:57 -0700 Subject: [PATCH 431/592] input: qpnp-power-on: Adapt software debounce to work for all keys In some cases, it can be beneficial to use software debouncing for all keys rather than just the power key to work around poorly implemented hardware debouncing in the PMIC. Signed-off-by: Danny Lin Signed-off-by: UtsavBalar1231 --- .../bindings/input/qpnp-power-on.txt | 4 ++-- drivers/input/misc/qpnp-power-on.c | 19 +++++++++---------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/Documentation/devicetree/bindings/input/qpnp-power-on.txt b/Documentation/devicetree/bindings/input/qpnp-power-on.txt index e13669a6acbd..f3b822ae58de 100644 --- a/Documentation/devicetree/bindings/input/qpnp-power-on.txt +++ b/Documentation/devicetree/bindings/input/qpnp-power-on.txt @@ -80,8 +80,8 @@ Optional properties: - qcom,shutdown-poweroff-type: Same description as qcom,warm-reset-poweroff- type but this applies for the system shutdown case. -- qcom,kpdpwr-sw-debounce: Boolean property to enable the debounce logic - on the KPDPWR_N rising edge. +- qcom,pon-sw-debounce Boolean property to enable software debouncing + logic for pon input keys. - qcom,resin-pon-reset: Boolean property which indicates that resin needs to be configured during reset in addition to the primary PON device that is configured diff --git a/drivers/input/misc/qpnp-power-on.c b/drivers/input/misc/qpnp-power-on.c index e4025a6bbac8..14326303830b 100644 --- a/drivers/input/misc/qpnp-power-on.c +++ b/drivers/input/misc/qpnp-power-on.c @@ -167,6 +167,7 @@ enum pon_type { PON_RESIN = PON_POWER_ON_TYPE_RESIN, PON_CBLPWR = PON_POWER_ON_TYPE_CBLPWR, PON_KPDPWR_RESIN = PON_POWER_ON_TYPE_KPDPWR_RESIN, + PON_KEY_MAX }; struct pon_reg { @@ -237,12 +238,12 @@ struct qpnp_pon { bool resin_shutdown_disable; bool ps_hold_hard_reset_disable; bool ps_hold_shutdown_disable; - bool kpdpwr_dbc_enable; bool support_twm_config; bool resin_pon_reset; - ktime_t kpdpwr_last_release_time; struct notifier_block pon_nb; bool legacy_hard_reset_offset; + bool sw_dbc_enable; + ktime_t sw_dbc_last_release_time[PON_KEY_MAX]; }; static int pon_ship_mode_en; @@ -960,9 +961,9 @@ static int qpnp_pon_input_dispatch(struct qpnp_pon *pon, u32 pon_type) if (!cfg->key_code) return 0; - if (pon->kpdpwr_dbc_enable && cfg->pon_type == PON_KPDPWR) { + if (pon->sw_dbc_enable) { elapsed_us = ktime_us_delta(ktime_get(), - pon->kpdpwr_last_release_time); + pon->sw_dbc_last_release_time[cfg->pon_type]); if (elapsed_us < pon->dbc_time_us) { pr_debug("Ignoring kpdpwr event; within debounce time\n"); return 0; @@ -995,10 +996,8 @@ static int qpnp_pon_input_dispatch(struct qpnp_pon *pon, u32 pon_type) pon_rt_sts); key_status = pon_rt_sts & pon_rt_bit; - if (pon->kpdpwr_dbc_enable && cfg->pon_type == PON_KPDPWR) { - if (!key_status) - pon->kpdpwr_last_release_time = ktime_get(); - } + if (pon->sw_dbc_enable && !key_status) + pon->sw_dbc_last_release_time[cfg->pon_type] = ktime_get(); /* * Simulate a press event in case release event occurred without a press @@ -2425,8 +2424,8 @@ static int qpnp_pon_probe(struct platform_device *pdev) if (rc) return rc; - pon->kpdpwr_dbc_enable = of_property_read_bool(dev->of_node, - "qcom,kpdpwr-sw-debounce"); + pon->sw_dbc_enable = of_property_read_bool(dev->of_node, + "qcom,pon-sw-debounce"); pon->store_hard_reset_reason = of_property_read_bool(dev->of_node, "qcom,store-hard-reset-reason"); From 227442c214e1737d4bddb5c28c21f35cddc5dfbf Mon Sep 17 00:00:00 2001 From: Danny Lin Date: Sun, 2 Aug 2020 00:03:51 -0700 Subject: [PATCH 432/592] input: qpnp-power-on: Separate software debounce delay from hardware Sometimes we may want to set a software debounce delay different from the PMIC hardware debounce delay, e.g. for bypassing a faulty hardware debounce implementation and handling as much as possible in software instead. Signed-off-by: Danny Lin Signed-off-by: UtsavBalar1231 --- .../devicetree/bindings/input/qpnp-power-on.txt | 6 ++++++ drivers/input/misc/qpnp-power-on.c | 17 ++++++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/input/qpnp-power-on.txt b/Documentation/devicetree/bindings/input/qpnp-power-on.txt index f3b822ae58de..e52ecc639bce 100644 --- a/Documentation/devicetree/bindings/input/qpnp-power-on.txt +++ b/Documentation/devicetree/bindings/input/qpnp-power-on.txt @@ -82,6 +82,12 @@ Optional properties: case. - qcom,pon-sw-debounce Boolean property to enable software debouncing logic for pon input keys. +- qcom,pon-sw-dbc-delay The debounce delay for the power-key interrupt + specified in us. This can be set to any value + as it is handled in software rather than by the + PMIC hardware. Only used if qcom,pon-sw-debounce + is enabled. Defaults to the value of + qcom,pon-dbc-delay if not specified. - qcom,resin-pon-reset: Boolean property which indicates that resin needs to be configured during reset in addition to the primary PON device that is configured diff --git a/drivers/input/misc/qpnp-power-on.c b/drivers/input/misc/qpnp-power-on.c index 14326303830b..164193af8103 100644 --- a/drivers/input/misc/qpnp-power-on.c +++ b/drivers/input/misc/qpnp-power-on.c @@ -225,6 +225,7 @@ struct qpnp_pon { int pon_trigger_reason; int pon_power_off_reason; u32 dbc_time_us; + u32 sw_dbc_time_us; u32 uvlo; int warm_reset_poff_type; int hard_reset_poff_type; @@ -964,7 +965,7 @@ static int qpnp_pon_input_dispatch(struct qpnp_pon *pon, u32 pon_type) if (pon->sw_dbc_enable) { elapsed_us = ktime_us_delta(ktime_get(), pon->sw_dbc_last_release_time[cfg->pon_type]); - if (elapsed_us < pon->dbc_time_us) { + if (elapsed_us < pon->sw_dbc_time_us) { pr_debug("Ignoring kpdpwr event; within debounce time\n"); return 0; } @@ -2426,6 +2427,20 @@ static int qpnp_pon_probe(struct platform_device *pdev) pon->sw_dbc_enable = of_property_read_bool(dev->of_node, "qcom,pon-sw-debounce"); + if (pon->sw_dbc_enable) { + rc = of_property_read_u32(dev->of_node, + "qcom,pon-sw-dbc-delay", + &pon->sw_dbc_time_us); + if (rc) { + if (rc == -EINVAL) { + pon->sw_dbc_time_us = pon->dbc_time_us; + } else { + dev_err(dev, "Unable to read software debounce delay rc: %d\n", + rc); + return rc; + } + } + } pon->store_hard_reset_reason = of_property_read_bool(dev->of_node, "qcom,store-hard-reset-reason"); From bfdaaf00721e8f947218bbf1f884f920963b42be Mon Sep 17 00:00:00 2001 From: Danny Lin Date: Sun, 2 Aug 2020 03:27:53 -0700 Subject: [PATCH 433/592] arm64: dts: pm8150: Switch to software debouncing for pon keys MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The hardware debouncing implementation in PM8150 is poorly implemented and delays *all* key presses by the debounce delay, even when no bouncing occurs. Let's switch to the kernel's software debouncing implementation instead to reduce unnecessary kpdpwr and resin key press delays, since it doesn't have this issue. Note that we still have a 62 µs debounce delay added by the PMIC, since it's not possible to fully disable hardware debouncing, but at least the delay is much shorter than what it used to be. This reduces the total wakeup latency (excluding deep sleep) from ~175 ms to ~160 ms, or about 9%, on a Pixel 2 XL with MSM8998 + PM8998. Signed-off-by: Danny Lin Signed-off-by: UtsavBalar1231 --- arch/arm64/boot/dts/qcom/pm8150.dtsi | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/pm8150.dtsi b/arch/arm64/boot/dts/qcom/pm8150.dtsi index d6b8eb94dd94..e6e5f4bacd44 100644 --- a/arch/arm64/boot/dts/qcom/pm8150.dtsi +++ b/arch/arm64/boot/dts/qcom/pm8150.dtsi @@ -47,8 +47,9 @@ <0x0 0x8 0x5 IRQ_TYPE_NONE>; interrupt-names = "kpdpwr", "resin", "resin-bark", "kpdpwr-resin-bark"; - qcom,pon-dbc-delay = <62500>; - qcom,kpdpwr-sw-debounce; + qcom,pon-dbc-delay = <62>; + qcom,pon-sw-dbc-delay = <15500>; + qcom,pon-sw-debounce; qcom,system-reset; qcom,store-hard-reset-reason; From cb9d18402b40e4678b30c8c45aea239b2e6d7751 Mon Sep 17 00:00:00 2001 From: Danny Lin Date: Sun, 2 Aug 2020 03:31:41 -0700 Subject: [PATCH 434/592] Revert "FROMLIST: cpu: fix cache warnings when resuming from deep suspend" This reverts commit 92765d3b38de8789ade8bcff01e57ab84875f637. There's a better fix for this issue now, backported from mainline. Signed-off-by: Danny Lin Signed-off-by: UtsavBalar1231 --- drivers/base/cpu.c | 14 +------------- include/linux/cpuhotplug.h | 1 - 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index 5a537093b9a6..11027b2146bc 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -435,16 +435,6 @@ static int cpu_uevent(struct device *dev, struct kobj_uevent_env *env) } #endif -static int cpu_dev_pm_unset_is_prepared(unsigned int cpu) -{ - struct device *cpu_dev = get_cpu_device(cpu); - - if (cpu_dev) - cpu_dev->power.is_prepared = false; - - return 0; -} - /* * register_cpu - Setup a sysfs device for a CPU. * @cpu - cpu->hotpluggable field set to 1 will generate a control file in @@ -479,9 +469,7 @@ int register_cpu(struct cpu *cpu, int num) register_cpu_under_node(num, cpu_to_node(num)); dev_pm_qos_expose_latency_limit(&cpu->dev, 0); - return cpuhp_setup_state_nocalls(CPUHP_CPUDEV_PM_PREPARE, - "base/cpu/dev_pm:prepare", - cpu_dev_pm_unset_is_prepared, NULL); + return 0; } struct device *get_cpu_device(unsigned cpu) diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h index 63fbc5f2adfa..c1bd9854ed30 100644 --- a/include/linux/cpuhotplug.h +++ b/include/linux/cpuhotplug.h @@ -69,7 +69,6 @@ enum cpuhp_state { CPUHP_SLAB_PREPARE, CPUHP_MD_RAID5_PREPARE, CPUHP_RCUTREE_PREP, - CPUHP_CPUDEV_PM_PREPARE, CPUHP_HYP_CORE_CTL_ISOLATION_DEAD, CPUHP_CORE_CTL_ISOLATION_DEAD, CPUHP_CPUIDLE_COUPLED_PREPARE, From b1f3174df00badcc8457bc9e93cb7475de5bbb25 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 30 Jun 2020 10:19:21 +0200 Subject: [PATCH 435/592] arm64/alternatives: use subsections for replacement sequences [ Upstream commit f7b93d42945cc71e1346dd5ae07c59061d56745e ] When building very large kernels, the logic that emits replacement sequences for alternatives fails when relative branches are present in the code that is emitted into the .altinstr_replacement section and patched in at the original site and fixed up. The reason is that the linker will insert veneers if relative branches go out of range, and due to the relative distance of the .altinstr_replacement from the .text section where its branch targets usually live, veneers may be emitted at the end of the .altinstr_replacement section, with the relative branches in the sequence pointed at the veneers instead of the actual target. The alternatives patching logic will attempt to fix up the branch to point to its original target, which will be the veneer in this case, but given that the patch site is likely to be far away as well, it will be out of range and so patching will fail. There are other cases where these veneers are problematic, e.g., when the target of the branch is in .text while the patch site is in .init.text, in which case putting the replacement sequence inside .text may not help either. So let's use subsections to emit the replacement code as closely as possible to the patch site, to ensure that veneers are only likely to be emitted if they are required at the patch site as well, in which case they will be in range for the replacement sequence both before and after it is transported to the patch site. This will prevent alternative sequences in non-init code from being released from memory after boot, but this is tolerable given that the entire section is only 512 KB on an allyesconfig build (which weighs in at 500+ MB for the entire Image). Also, note that modules today carry the replacement sequences in non-init sections as well, and any of those that target init code will be emitted into init sections after this change. This fixes an early crash when booting an allyesconfig kernel on a system where any of the alternatives sequences containing relative branches are activated at boot (e.g., ARM64_HAS_PAN on TX2) Signed-off-by: Ard Biesheuvel Cc: Suzuki K Poulose Cc: James Morse Cc: Andre Przywara Cc: Dave P Martin Link: https://lore.kernel.org/r/20200630081921.13443-1-ardb@kernel.org Signed-off-by: Will Deacon Signed-off-by: Sasha Levin Signed-off-by: UtsavBalar1231 --- arch/arm64/include/asm/alternative.h | 16 ++++++++-------- arch/arm64/kernel/vmlinux.lds.S | 3 --- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/arch/arm64/include/asm/alternative.h b/arch/arm64/include/asm/alternative.h index 4ed869845a23..1824768fb1ee 100644 --- a/arch/arm64/include/asm/alternative.h +++ b/arch/arm64/include/asm/alternative.h @@ -68,11 +68,11 @@ void apply_alternatives(void *start, size_t length); ".pushsection .altinstructions,\"a\"\n" \ ALTINSTR_ENTRY(feature) \ ".popsection\n" \ - ".pushsection .altinstr_replacement, \"a\"\n" \ + ".subsection 1\n" \ "663:\n\t" \ newinstr "\n" \ "664:\n\t" \ - ".popsection\n\t" \ + ".previous\n\t" \ ".org . - (664b-663b) + (662b-661b)\n\t" \ ".org . - (662b-661b) + (664b-663b)\n" \ ".endif\n" @@ -112,9 +112,9 @@ void apply_alternatives(void *start, size_t length); 662: .pushsection .altinstructions, "a" altinstruction_entry 661b, 663f, \cap, 662b-661b, 664f-663f .popsection - .pushsection .altinstr_replacement, "ax" + .subsection 1 663: \insn2 -664: .popsection +664: .previous .org . - (664b-663b) + (662b-661b) .org . - (662b-661b) + (664b-663b) .endif @@ -155,7 +155,7 @@ void apply_alternatives(void *start, size_t length); .pushsection .altinstructions, "a" altinstruction_entry 663f, 661f, \cap, 664f-663f, 662f-661f .popsection - .pushsection .altinstr_replacement, "ax" + .subsection 1 .align 2 /* So GAS knows label 661 is suitably aligned */ 661: .endm @@ -174,9 +174,9 @@ void apply_alternatives(void *start, size_t length); .macro alternative_else 662: .if .Lasm_alt_mode==0 - .pushsection .altinstr_replacement, "ax" + .subsection 1 .else - .popsection + .previous .endif 663: .endm @@ -187,7 +187,7 @@ void apply_alternatives(void *start, size_t length); .macro alternative_endif 664: .if .Lasm_alt_mode==0 - .popsection + .previous .endif .org . - (664b-663b) + (662b-661b) .org . - (662b-661b) + (664b-663b) diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S index 9844a4ae6196..7babca96fbb2 100644 --- a/arch/arm64/kernel/vmlinux.lds.S +++ b/arch/arm64/kernel/vmlinux.lds.S @@ -162,9 +162,6 @@ SECTIONS KEEP(*(.altinstructions)) __alt_instructions_end = .; } - .altinstr_replacement : { - *(.altinstr_replacement) - } . = ALIGN(PAGE_SIZE); __inittext_end = .; From 3e879750543b575402ceca76bbeee745a5c88c83 Mon Sep 17 00:00:00 2001 From: Sami Tolvanen Date: Thu, 30 Jul 2020 08:37:01 -0700 Subject: [PATCH 436/592] arm64/alternatives: move length validation inside the subsection Commit f7b93d42945c ("arm64/alternatives: use subsections for replacement sequences") breaks LLVM's integrated assembler, because due to its one-pass design, it cannot compute instruction sequence lengths before the layout for the subsection has been finalized. This change fixes the build by moving the .org directives inside the subsection, so they are processed after the subsection layout is known. Fixes: f7b93d42945c ("arm64/alternatives: use subsections for replacement sequences") Signed-off-by: Sami Tolvanen Link: https://github.com/ClangBuiltLinux/linux/issues/1078 Link: https://lore.kernel.org/r/20200730153701.3892953-1-samitolvanen@google.com Signed-off-by: Will Deacon Signed-off-by: Danny Lin Signed-off-by: UtsavBalar1231 --- arch/arm64/include/asm/alternative.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/include/asm/alternative.h b/arch/arm64/include/asm/alternative.h index 1824768fb1ee..3abb2dacb43f 100644 --- a/arch/arm64/include/asm/alternative.h +++ b/arch/arm64/include/asm/alternative.h @@ -72,9 +72,9 @@ void apply_alternatives(void *start, size_t length); "663:\n\t" \ newinstr "\n" \ "664:\n\t" \ - ".previous\n\t" \ ".org . - (664b-663b) + (662b-661b)\n\t" \ - ".org . - (662b-661b) + (664b-663b)\n" \ + ".org . - (662b-661b) + (664b-663b)\n\t" \ + ".previous\n" \ ".endif\n" #define __ALTERNATIVE_CFG_CB(oldinstr, feature, cfg_enabled, cb) \ From e55fb9d2dfd08732aa1e40afa1f264bf2bab9bf4 Mon Sep 17 00:00:00 2001 From: Park Ju Hyung Date: Sun, 21 Jul 2019 01:30:10 +0900 Subject: [PATCH 437/592] Kconfig: omit sublevel patch version These are getting annoying in defconfig diffs Signed-off-by: Park Ju Hyung Signed-off-by: Danny Lin Signed-off-by: UtsavBalar1231 --- Kconfig | 2 +- init/Kconfig | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Kconfig b/Kconfig index 8c4c1cb0f9cd..af31bb3d62da 100644 --- a/Kconfig +++ b/Kconfig @@ -3,7 +3,7 @@ # For a description of the syntax of this configuration file, # see Documentation/kbuild/kconfig-language.txt. # -mainmenu "Linux/$ARCH $KERNELVERSION Kernel Configuration" +mainmenu "Linux/$ARCH $VERSION.$PATCHLEVEL Kernel Configuration" config SRCARCH string diff --git a/init/Kconfig b/init/Kconfig index 6c14e5499fb9..16ccb418ca32 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -2,6 +2,14 @@ config ARCH string option env="ARCH" +config VERSION + string + option env="VERSION" + +config PATCHLEVEL + string + option env="PATCHLEVEL" + config KERNELVERSION string option env="KERNELVERSION" From b8616e47db8b58c7ac70de60d41169b94c3df8a1 Mon Sep 17 00:00:00 2001 From: UtsavBalar1231 Date: Mon, 3 Aug 2020 12:38:00 +0530 Subject: [PATCH 438/592] ARM64: configs: raphael: sync for omit sublevel patch version Signed-off-by: UtsavBalar1231 --- arch/arm64/configs/raphael_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/configs/raphael_defconfig b/arch/arm64/configs/raphael_defconfig index 46180b50011b..9ce6bb1cbdee 100644 --- a/arch/arm64/configs/raphael_defconfig +++ b/arch/arm64/configs/raphael_defconfig @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm64 4.14.189 Kernel Configuration +# Linux/arm64 4.14 Kernel Configuration # CONFIG_ARM64=y CONFIG_64BIT=y From da10ec15d9bd3608a4295412779531698884a117 Mon Sep 17 00:00:00 2001 From: UtsavBalar1231 Date: Mon, 3 Aug 2020 14:10:26 +0530 Subject: [PATCH 439/592] dsi_panel: Do not explicitly enable ULPS mode during suspend This reverts commit 36f66843835d5992c4b87efa76ce8320505d6402. Signed-off-by: UtsavBalar1231 --- drivers/gpu/drm/msm/dsi-staging/dsi_panel.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c index 5a8e94efce2e..387c5b37dc59 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c @@ -2296,7 +2296,8 @@ static int dsi_panel_parse_misc_features(struct dsi_panel *panel) pr_info("%s: ulps feature %s\n", __func__, (panel->ulps_feature_enabled ? "enabled" : "disabled")); - panel->ulps_suspend_enabled = true; + panel->ulps_suspend_enabled = + utils->read_bool(utils->data, "qcom,suspend-ulps-enabled"); pr_info("%s: ulps during suspend feature %s", __func__, (panel->ulps_suspend_enabled ? "enabled" : "disabled")); From 34a20308c34c8b5af4372d8f10a3e27993a12017 Mon Sep 17 00:00:00 2001 From: Danny Lin Date: Sun, 2 Aug 2020 02:35:30 -0700 Subject: [PATCH 440/592] f2fs: Add support for reporting a fake kernel version to fsck fsck.f2fs forces a filesystem fix on boot if it detects that the current kernel version differs from the one saved in the superblock, which results in fsck blocking boot for a long time (~35 seconds). This commit provides a way to report a constant fake kernel version to fsck to avoid triggering the version check, which is useful if you boot new kernel builds frequently. Signed-off-by: Danny Lin Signed-off-by: UtsavBalar1231 --- fs/f2fs/Kconfig | 19 +++++++++++++++++++ kernel/sys.c | 24 ++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/fs/f2fs/Kconfig b/fs/f2fs/Kconfig index cb3a0e0652c5..3c5c9ef573df 100644 --- a/fs/f2fs/Kconfig +++ b/fs/f2fs/Kconfig @@ -148,3 +148,22 @@ config F2FS_FS_LZORLE default y help Support LZO-RLE compress algorithm, if unsure, say Y. + +config F2FS_REPORT_FAKE_KERNEL_VERSION + bool "Report fake kernel version to fsck.f2fs" + depends on F2FS_FS + help + fsck.f2fs forces a filesystem fix on boot if it detects that the current + kernel version differs from the one saved in the superblock, which results in + fsck taking a long time to run. This option provides a way to report a + constant fake kernel version to fsck to avoid triggering the version check. + + If unsure, say N. + +config F2FS_FAKE_KERNEL_RELEASE + string "Kernel release for fsck.f2fs" + depends on F2FS_REPORT_FAKE_KERNEL_VERSION + +config F2FS_FAKE_KERNEL_VERSION + string "Kernel version for fsck.f2fs" + depends on F2FS_REPORT_FAKE_KERNEL_VERSION diff --git a/kernel/sys.c b/kernel/sys.c index a08073ebf19a..60d18b36c6d6 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -1182,6 +1182,28 @@ static int override_release(char __user *release, size_t len) return ret; } +static int override_version(struct new_utsname __user *name) +{ +#ifdef CONFIG_F2FS_REPORT_FAKE_KERNEL_VERSION + int ret; + + if (strcmp(current->comm, "fsck.f2fs")) + return 0; + + ret = copy_to_user(name->release, CONFIG_F2FS_FAKE_KERNEL_RELEASE, + strlen(CONFIG_F2FS_FAKE_KERNEL_RELEASE) + 1); + if (ret) + return ret; + + ret = copy_to_user(name->version, CONFIG_F2FS_FAKE_KERNEL_VERSION, + strlen(CONFIG_F2FS_FAKE_KERNEL_VERSION) + 1); + + return ret; +#else + return 0; +#endif +} + SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name) { struct new_utsname tmp; @@ -1196,6 +1218,8 @@ SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name) return -EFAULT; if (override_architecture(name)) return -EFAULT; + if (override_version(name)) + return -EFAULT; return 0; } From 9312e8c88bfa8352b3047482a53e403160fd18df Mon Sep 17 00:00:00 2001 From: UtsavBalar1231 Date: Mon, 3 Aug 2020 20:05:26 +0530 Subject: [PATCH 441/592] ARM64: configs: raphael: Always report stock kernel version to fsck.f2fs This is the prebuilt kernel used in los tree Signed-off-by: UtsavBalar1231 --- arch/arm64/configs/raphael_defconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/configs/raphael_defconfig b/arch/arm64/configs/raphael_defconfig index 9ce6bb1cbdee..419132be52c0 100644 --- a/arch/arm64/configs/raphael_defconfig +++ b/arch/arm64/configs/raphael_defconfig @@ -4673,6 +4673,9 @@ CONFIG_F2FS_FS_SECURITY=y CONFIG_F2FS_FS_ENCRYPTION=y # CONFIG_F2FS_FAULT_INJECTION is not set # CONFIG_F2FS_FS_COMPRESSION is not set +CONFIG_F2FS_REPORT_FAKE_KERNEL_VERSION=y +CONFIG_F2FS_FAKE_KERNEL_RELEASE="4.14.117-perf-g2146d60" +CONFIG_F2FS_FAKE_KERNEL_VERSION="#1 SMP PREEMPT Mon Apr 27 03:21:17 CST 2020" # CONFIG_FS_DAX is not set CONFIG_FS_POSIX_ACL=y CONFIG_EXPORTFS=y From 0399eaa0cc141e626cce9319092056aec461dc5a Mon Sep 17 00:00:00 2001 From: UtsavBalar1231 Date: Mon, 3 Aug 2020 16:28:29 +0530 Subject: [PATCH 442/592] ARM64: configs: raphael: switch back to 100hz timer frequency Signed-off-by: UtsavBalar1231 --- arch/arm64/configs/raphael_defconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm64/configs/raphael_defconfig b/arch/arm64/configs/raphael_defconfig index 419132be52c0..1ed3b4c5a07a 100644 --- a/arch/arm64/configs/raphael_defconfig +++ b/arch/arm64/configs/raphael_defconfig @@ -549,11 +549,11 @@ CONFIG_HOLES_IN_ZONE=y # CONFIG_PREEMPT_VOLUNTARY is not set CONFIG_PREEMPT=y CONFIG_PREEMPT_COUNT=y -# CONFIG_HZ_100 is not set -CONFIG_HZ_250=y +CONFIG_HZ_100=y +# CONFIG_HZ_250 is not set # CONFIG_HZ_300 is not set # CONFIG_HZ_1000 is not set -CONFIG_HZ=250 +CONFIG_HZ=100 CONFIG_SCHED_HRTICK=y CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y From 6e4af6f1f457b015bca9ef91783cf0c303d26e67 Mon Sep 17 00:00:00 2001 From: UtsavBalar1231 Date: Mon, 3 Aug 2020 16:22:05 +0530 Subject: [PATCH 443/592] ARM64: configs: raphael: debloat and optimize - previous Image size : 11619.75Kib - new Image size : 11367.14Kib Signed-off-by: UtsavBalar1231 --- arch/arm64/configs/raphael_defconfig | 247 ++++++++++++++++++--------- 1 file changed, 168 insertions(+), 79 deletions(-) diff --git a/arch/arm64/configs/raphael_defconfig b/arch/arm64/configs/raphael_defconfig index 1ed3b4c5a07a..17f8b9590fb1 100644 --- a/arch/arm64/configs/raphael_defconfig +++ b/arch/arm64/configs/raphael_defconfig @@ -48,7 +48,7 @@ CONFIG_THREAD_INFO_IN_TASK=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_CROSS_COMPILE="" # CONFIG_COMPILE_TEST is not set -CONFIG_LOCALVERSION="-iMMENSITY" +CONFIG_LOCALVERSION="-IMMENSiTY" CONFIG_LOCALVERSION_AUTO=y CONFIG_LOCALVERSION_COMMIT_SHA=y CONFIG_DEFAULT_HOSTNAME="(none)" @@ -126,7 +126,7 @@ CONFIG_RCU_NOCB_CPU=y CONFIG_BUILD_BIN2C=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y -# CONFIG_IKHEADERS is not set +CONFIG_IKHEADERS=y CONFIG_LOG_BUF_SHIFT=17 # CONFIG_CONSOLE_FLUSH_ON_HOTPLUG is not set CONFIG_LOG_CPU_MAX_BUF_SHIFT=17 @@ -185,7 +185,7 @@ CONFIG_RD_GZIP=y # CONFIG_RD_LZMA is not set # CONFIG_RD_XZ is not set # CONFIG_RD_LZO is not set -# CONFIG_RD_LZ4 is not set +CONFIG_RD_LZ4=y CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # CONFIG_GCC_LTO is not set @@ -283,9 +283,10 @@ CONFIG_ARCH_SUPPORTS_THINLTO=y CONFIG_LTO_NONE=y # CONFIG_LTO_CLANG is not set CONFIG_ARCH_SUPPORTS_SHADOW_CALL_STACK=y -CONFIG_ROP_PROTECTION_NONE=y -# CONFIG_SHADOW_CALL_STACK is not set +# CONFIG_ROP_PROTECTION_NONE is not set +CONFIG_SHADOW_CALL_STACK=y # CONFIG_LLVM_POLLY is not set +CONFIG_SHADOW_CALL_STACK_VMAP=y CONFIG_HAVE_CONTEXT_TRACKING=y CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y @@ -370,8 +371,8 @@ CONFIG_CFQ_GROUP_IOSCHED=y CONFIG_DEFAULT_CFQ=y # CONFIG_DEFAULT_NOOP is not set CONFIG_DEFAULT_IOSCHED="cfq" -CONFIG_MQ_IOSCHED_DEADLINE=y -CONFIG_MQ_IOSCHED_KYBER=y +# CONFIG_MQ_IOSCHED_DEADLINE is not set +# CONFIG_MQ_IOSCHED_KYBER is not set # CONFIG_IOSCHED_BFQ is not set CONFIG_ASN1=y CONFIG_ARCH_INLINE_SPIN_TRYLOCK=y @@ -588,7 +589,7 @@ CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y # CONFIG_MEMORY_FAILURE is not set # CONFIG_TRANSPARENT_HUGEPAGE is not set # CONFIG_ARCH_WANTS_THP_SWAP is not set -CONFIG_CLEANCACHE=y +# CONFIG_CLEANCACHE is not set # CONFIG_FRONTSWAP is not set CONFIG_CMA=y CONFIG_CMA_AREAS=7 @@ -604,7 +605,7 @@ CONFIG_BALANCE_ANON_FILE_RECLAIM=y CONFIG_ARCH_SUPPORTS_SPECULATIVE_PAGE_FAULT=y CONFIG_SPECULATIVE_PAGE_FAULT=y # CONFIG_HAVE_LOW_MEMORY_KILLER is not set -CONFIG_PROCESS_RECLAIM=y +# CONFIG_PROCESS_RECLAIM is not set # CONFIG_FORCE_ALLOC_FROM_DMA_ZONE is not set CONFIG_ARM64_DMA_USE_IOMMU=y CONFIG_ARM64_DMA_IOMMU_ALIGNMENT=9 @@ -620,13 +621,13 @@ CONFIG_FORCE_MAX_ZONEORDER=11 # CONFIG_HARDEN_BRANCH_PREDICTOR is not set # CONFIG_PRINT_VMEMLAYOUT is not set # CONFIG_ARM64_SSBD is not set -CONFIG_ARM64_TAGGED_ADDR_ABI=y +# CONFIG_ARM64_TAGGED_ADDR_ABI is not set # CONFIG_RODATA_FULL_DEFAULT_ENABLED is not set CONFIG_ARMV8_DEPRECATED=y CONFIG_SWP_EMULATION=y CONFIG_CP15_BARRIER_EMULATION=y CONFIG_SETEND_EMULATION=y -# CONFIG_ARM64_SW_TTBR0_PAN is not set +CONFIG_ARM64_SW_TTBR0_PAN=y # # ARMv8.1 architectural features @@ -694,7 +695,7 @@ CONFIG_PM=y CONFIG_PM_OPP=y CONFIG_PM_CLK=y CONFIG_PM_GENERIC_DOMAINS=y -CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y +# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set CONFIG_PM_GENERIC_DOMAINS_SLEEP=y CONFIG_PM_GENERIC_DOMAINS_OF=y CONFIG_CPU_PM=y @@ -712,12 +713,11 @@ CONFIG_CPU_IDLE=y CONFIG_CPU_IDLE_MULTIPLE_DRIVERS=y # CONFIG_CPU_IDLE_GOV_LADDER is not set # CONFIG_CPU_IDLE_GOV_MENU is not set -CONFIG_DT_IDLE_STATES=y # # ARM CPU Idle Drivers # -CONFIG_ARM_CPUIDLE=y +# CONFIG_ARM_CPUIDLE is not set # CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set # @@ -939,7 +939,7 @@ CONFIG_NETFILTER_XT_TARGET_CONNMARK=y CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y CONFIG_NETFILTER_XT_TARGET_CT=y CONFIG_NETFILTER_XT_TARGET_DSCP=y -# CONFIG_NETFILTER_XT_TARGET_HL is not set +CONFIG_NETFILTER_XT_TARGET_HL=y # CONFIG_NETFILTER_XT_TARGET_HMARK is not set CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y CONFIG_NETFILTER_XT_TARGET_HARDIDLETIMER=y @@ -1065,7 +1065,7 @@ CONFIG_IP6_NF_IPTABLES=y # CONFIG_IP6_NF_MATCH_EUI64 is not set # CONFIG_IP6_NF_MATCH_FRAG is not set # CONFIG_IP6_NF_MATCH_OPTS is not set -# CONFIG_IP6_NF_MATCH_HL is not set +CONFIG_IP6_NF_MATCH_HL=y # CONFIG_IP6_NF_MATCH_IPV6HEADER is not set # CONFIG_IP6_NF_MATCH_MH is not set CONFIG_IP6_NF_MATCH_RPFILTER=y @@ -1157,7 +1157,7 @@ CONFIG_NET_SCH_NETEM=y CONFIG_NET_SCH_FQ_CODEL=y # CONFIG_NET_SCH_FQ is not set # CONFIG_NET_SCH_HHF is not set -CONFIG_NET_SCH_PIE=y +# CONFIG_NET_SCH_PIE is not set CONFIG_NET_SCH_INGRESS=y # CONFIG_NET_SCH_PLUG is not set CONFIG_NET_SCH_DEFAULT=y @@ -1225,7 +1225,7 @@ CONFIG_QRTR=y CONFIG_QRTR_NODE_ID=1 CONFIG_QRTR_SMD=y # CONFIG_QRTR_USB is not set -# CONFIG_QRTR_FIFO is not set +CONFIG_QRTR_FIFO=y # CONFIG_NET_NCSI is not set # CONFIG_RMNET_DATA is not set # CONFIG_RMNET_USB is not set @@ -1526,7 +1526,7 @@ CONFIG_SCSI=y CONFIG_SCSI_DMA=y # CONFIG_SCSI_NETLINK is not set # CONFIG_SCSI_MQ_DEFAULT is not set -CONFIG_SCSI_PROC_FS=y +# CONFIG_SCSI_PROC_FS is not set # # SCSI support type (disk, tape, CD-ROM) @@ -1593,13 +1593,13 @@ CONFIG_DM_VERITY_FEC=y # CONFIG_DM_LOG_WRITES is not set # CONFIG_DM_INTEGRITY is not set # CONFIG_DM_VERITY_AVB is not set -# CONFIG_DM_ANDROID_VERITY_AT_MOST_ONCE_DEFAULT_ENABLED is not set -CONFIG_DM_BOW=y +CONFIG_DM_ANDROID_VERITY_AT_MOST_ONCE_DEFAULT_ENABLED=y +# CONFIG_DM_BOW is not set # CONFIG_TARGET_CORE is not set CONFIG_NETDEVICES=y CONFIG_MII=y CONFIG_NET_CORE=y -CONFIG_BONDING=y +# CONFIG_BONDING is not set CONFIG_DUMMY=y # CONFIG_EQUALIZER is not set # CONFIG_IFB is not set @@ -1712,14 +1712,14 @@ CONFIG_PPP_BSDCOMP=y CONFIG_PPP_DEFLATE=y CONFIG_PPP_FILTER=y CONFIG_PPP_MPPE=y -CONFIG_PPP_MULTILINK=y -CONFIG_PPPOE=y +# CONFIG_PPP_MULTILINK is not set +# CONFIG_PPPOE is not set CONFIG_PPTP=y CONFIG_PPPOL2TP=y CONFIG_PPPOLAC=y CONFIG_PPPOPNS=y -CONFIG_PPP_ASYNC=y -CONFIG_PPP_SYNC_TTY=y +# CONFIG_PPP_ASYNC is not set +# CONFIG_PPP_SYNC_TTY is not set # CONFIG_SLIP is not set CONFIG_SLHC=y CONFIG_USB_NET_DRIVERS=y @@ -1761,10 +1761,7 @@ CONFIG_USB_NET_CDC_NCM=y CONFIG_WLAN=y # CONFIG_WIRELESS_WDS is not set # CONFIG_WLAN_VENDOR_ADMTEK is not set -CONFIG_WLAN_VENDOR_ATH=y -# CONFIG_ATH_DEBUG is not set -# CONFIG_ATH_REG_DYNAMIC_USER_REG_HINTS is not set -# CONFIG_ATH6KL is not set +# CONFIG_WLAN_VENDOR_ATH is not set # CONFIG_WLAN_VENDOR_ATMEL is not set # CONFIG_WLAN_VENDOR_BROADCOM is not set # CONFIG_WLAN_VENDOR_CISCO is not set @@ -1816,7 +1813,7 @@ CONFIG_INPUT_POLLDEV=y # Userland interfaces # # CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_JOYDEV=y CONFIG_INPUT_EVDEV=y # CONFIG_INPUT_EVBUG is not set # CONFIG_INPUT_KEYRESET is not set @@ -2016,7 +2013,7 @@ CONFIG_UNIX98_PTYS=y # CONFIG_SERIAL_NONSTANDARD is not set # CONFIG_N_GSM is not set # CONFIG_TRACE_SINK is not set -CONFIG_LDISC_AUTOLOAD=y +# CONFIG_LDISC_AUTOLOAD is not set # CONFIG_DEVMEM is not set # @@ -2067,8 +2064,6 @@ CONFIG_HW_RANDOM_MSM_LEGACY=y # # Diag Support # -CONFIG_DIAG_CHAR=y -CONFIG_DIAG_OVER_USB=y CONFIG_MSM_FASTCVPD=y CONFIG_MSM_ADSPRPC=y # CONFIG_MSM_RDBG is not set @@ -2287,8 +2282,8 @@ CONFIG_POWER_RESET=y CONFIG_POWER_RESET_QCOM=y # CONFIG_QCOM_DLOAD_MODE is not set # CONFIG_POWER_RESET_RESTART is not set -CONFIG_POWER_RESET_XGENE=y -CONFIG_POWER_RESET_SYSCON=y +# CONFIG_POWER_RESET_XGENE is not set +# CONFIG_POWER_RESET_SYSCON is not set # CONFIG_POWER_RESET_SYSCON_POWEROFF is not set # CONFIG_SYSCON_REBOOT_MODE is not set CONFIG_POWER_SUPPLY=y @@ -2648,7 +2643,7 @@ CONFIG_REGULATOR_PROXY_CONSUMER=y # CONFIG_REGULATOR_PV88090 is not set # CONFIG_REGULATOR_PWM is not set # CONFIG_REGULATOR_QCOM_SPMI is not set -CONFIG_REGULATOR_QPNP_AMOLED=y +# CONFIG_REGULATOR_QPNP_AMOLED is not set # CONFIG_REGULATOR_QPNP_LABIBB is not set CONFIG_REGULATOR_QPNP_LCDB=y # CONFIG_REGULATOR_QPNP_OLEDB is not set @@ -2748,43 +2743,132 @@ CONFIG_MSM_NPU=y # # Media ancillary drivers (tuners, sensors, i2c, spi, frontends) # -CONFIG_MEDIA_SUBDRV_AUTOSELECT=y +# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set + +# +# I2C Encoders, decoders, sensors and other helper chips +# # # Audio decoders, processors and mixers # +# CONFIG_VIDEO_TVAUDIO is not set +# CONFIG_VIDEO_TDA7432 is not set +# CONFIG_VIDEO_TDA9840 is not set +# CONFIG_VIDEO_TEA6415C is not set +# CONFIG_VIDEO_TEA6420 is not set +# CONFIG_VIDEO_MSP3400 is not set +# CONFIG_VIDEO_CS3308 is not set +# CONFIG_VIDEO_CS5345 is not set +# CONFIG_VIDEO_CS53L32A is not set +# CONFIG_VIDEO_TLV320AIC23B is not set +# CONFIG_VIDEO_UDA1342 is not set +# CONFIG_VIDEO_WM8775 is not set +# CONFIG_VIDEO_WM8739 is not set +# CONFIG_VIDEO_VP27SMPX is not set +# CONFIG_VIDEO_SONY_BTF_MPX is not set # # RDS decoders # +# CONFIG_VIDEO_SAA6588 is not set # # Video decoders # +# CONFIG_VIDEO_ADV7180 is not set +# CONFIG_VIDEO_ADV7183 is not set +# CONFIG_VIDEO_ADV748X is not set +# CONFIG_VIDEO_ADV7604 is not set +# CONFIG_VIDEO_ADV7842 is not set +# CONFIG_VIDEO_BT819 is not set +# CONFIG_VIDEO_BT856 is not set +# CONFIG_VIDEO_BT866 is not set +# CONFIG_VIDEO_KS0127 is not set +# CONFIG_VIDEO_ML86V7667 is not set +# CONFIG_VIDEO_AD5820 is not set +# CONFIG_VIDEO_DW9714 is not set +# CONFIG_VIDEO_SAA7110 is not set +# CONFIG_VIDEO_SAA711X is not set +# CONFIG_VIDEO_TC358743 is not set +# CONFIG_VIDEO_TVP514X is not set +# CONFIG_VIDEO_TVP5150 is not set +# CONFIG_VIDEO_TVP7002 is not set +# CONFIG_VIDEO_TW2804 is not set +# CONFIG_VIDEO_TW9903 is not set +# CONFIG_VIDEO_TW9906 is not set +# CONFIG_VIDEO_VPX3220 is not set # # Video and audio decoders # +# CONFIG_VIDEO_SAA717X is not set +# CONFIG_VIDEO_CX25840 is not set # # Video encoders # +# CONFIG_VIDEO_SAA7127 is not set +# CONFIG_VIDEO_SAA7185 is not set +# CONFIG_VIDEO_ADV7170 is not set +# CONFIG_VIDEO_ADV7175 is not set +# CONFIG_VIDEO_ADV7343 is not set +# CONFIG_VIDEO_ADV7393 is not set +# CONFIG_VIDEO_ADV7511 is not set +# CONFIG_VIDEO_AD9389B is not set +# CONFIG_VIDEO_AK881X is not set +# CONFIG_VIDEO_THS8200 is not set # # Camera sensor devices # +# CONFIG_VIDEO_OV2640 is not set +# CONFIG_VIDEO_OV2659 is not set +# CONFIG_VIDEO_OV5640 is not set +# CONFIG_VIDEO_OV5645 is not set +# CONFIG_VIDEO_OV5647 is not set +# CONFIG_VIDEO_OV6650 is not set +# CONFIG_VIDEO_OV5670 is not set +# CONFIG_VIDEO_OV7640 is not set +# CONFIG_VIDEO_OV7670 is not set +# CONFIG_VIDEO_OV9650 is not set +# CONFIG_VIDEO_OV13858 is not set +# CONFIG_VIDEO_VS6624 is not set +# CONFIG_VIDEO_MT9M032 is not set +# CONFIG_VIDEO_MT9M111 is not set +# CONFIG_VIDEO_MT9P031 is not set +# CONFIG_VIDEO_MT9T001 is not set +# CONFIG_VIDEO_MT9V011 is not set +# CONFIG_VIDEO_MT9V032 is not set +# CONFIG_VIDEO_SR030PC30 is not set +# CONFIG_VIDEO_NOON010PC30 is not set +# CONFIG_VIDEO_M5MOLS is not set +# CONFIG_VIDEO_S5K6AA is not set +# CONFIG_VIDEO_S5K6A3 is not set +# CONFIG_VIDEO_S5K4ECGX is not set +# CONFIG_VIDEO_S5K5BAF is not set +# CONFIG_VIDEO_SMIAPP is not set +# CONFIG_VIDEO_ET8EK8 is not set +# CONFIG_VIDEO_S5C73M3 is not set # # Flash devices # +# CONFIG_VIDEO_ADP1653 is not set +# CONFIG_VIDEO_AS3645A is not set +# CONFIG_VIDEO_LM3560 is not set +# CONFIG_VIDEO_LM3646 is not set # # Video improvement chips # +# CONFIG_VIDEO_UPD64031A is not set +# CONFIG_VIDEO_UPD64083 is not set # # Audio/Video compression chips # +# CONFIG_VIDEO_SAA6752HS is not set # # SDR tuner chips @@ -2793,11 +2877,22 @@ CONFIG_MEDIA_SUBDRV_AUTOSELECT=y # # Miscellaneous helper chips # +# CONFIG_VIDEO_THS7303 is not set +# CONFIG_VIDEO_M52790 is not set # # Sensors used on soc_camera driver # +# +# SPI helper chips +# +# CONFIG_VIDEO_GS1662 is not set + +# +# Customise DVB Frontends +# + # # Tools to develop new frontends # @@ -2834,7 +2929,7 @@ CONFIG_DRM_MSM=y # CONFIG_DRM_MSM_HDMI is not set # CONFIG_DRM_MSM_DSI is not set CONFIG_DRM_MSM_DSI_STAGING=y -# CONFIG_DSI_PARSER is not set +CONFIG_DSI_PARSER=y # CONFIG_DRM_MSM_MDP5 is not set # CONFIG_DRM_MSM_MDP4 is not set # CONFIG_DRM_MSM_HDCP is not set @@ -2935,7 +3030,7 @@ CONFIG_FB_NOTIFY=y CONFIG_BACKLIGHT_LCD_SUPPORT=y # CONFIG_LCD_CLASS_DEVICE is not set CONFIG_BACKLIGHT_CLASS_DEVICE=y -CONFIG_BACKLIGHT_GENERIC=y +# CONFIG_BACKLIGHT_GENERIC is not set # CONFIG_BACKLIGHT_PWM is not set # CONFIG_BACKLIGHT_PM8941_WLED is not set CONFIG_BACKLIGHT_QCOM_SPMI_WLED=y @@ -2968,9 +3063,9 @@ CONFIG_SND_PCM_TIMER=y # CONFIG_SND_HRTIMER is not set CONFIG_SND_DYNAMIC_MINORS=y CONFIG_SND_MAX_CARDS=32 -CONFIG_SND_SUPPORT_OLD_API=y +# CONFIG_SND_SUPPORT_OLD_API is not set CONFIG_SND_PROC_FS=y -CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PROCFS is not set # CONFIG_SND_VERBOSE_PRINTK is not set # CONFIG_SND_DEBUG is not set # CONFIG_SND_SEQUENCER is not set @@ -3146,7 +3241,7 @@ CONFIG_HID_GENERIC=y # CONFIG_HID_A4TECH is not set # CONFIG_HID_ACCUTOUCH is not set # CONFIG_HID_ACRUX is not set -CONFIG_HID_APPLE=y +# CONFIG_HID_APPLE is not set # CONFIG_HID_APPLEIR is not set # CONFIG_HID_ASUS is not set # CONFIG_HID_AUREAL is not set @@ -3158,10 +3253,9 @@ CONFIG_HID_APPLE=y # CONFIG_HID_PRODIKEYS is not set # CONFIG_HID_CMEDIA is not set # CONFIG_HID_CYPRESS is not set -CONFIG_HID_DRAGONRISE=y -# CONFIG_DRAGONRISE_FF is not set +# CONFIG_HID_DRAGONRISE is not set # CONFIG_HID_EMS_FF is not set -CONFIG_HID_ELECOM=y +# CONFIG_HID_ELECOM is not set # CONFIG_HID_ELO is not set # CONFIG_HID_EZKEY is not set # CONFIG_HID_GEMBIRD is not set @@ -3181,21 +3275,20 @@ CONFIG_HID_ELECOM=y # CONFIG_HID_LED is not set # CONFIG_HID_LENOVO is not set # CONFIG_HID_LOGITECH is not set -CONFIG_HID_MAGICMOUSE=y +# CONFIG_HID_MAGICMOUSE is not set # CONFIG_HID_MAYFLASH is not set -CONFIG_HID_MICROSOFT=y +# CONFIG_HID_MICROSOFT is not set # CONFIG_HID_MONTEREY is not set -CONFIG_HID_MULTITOUCH=y +# CONFIG_HID_MULTITOUCH is not set # CONFIG_HID_NINTENDO is not set # CONFIG_HID_NTI is not set # CONFIG_HID_NTRIG is not set # CONFIG_HID_ORTEK is not set -CONFIG_HID_PANTHERLORD=y -# CONFIG_PANTHERLORD_FF is not set +# CONFIG_HID_PANTHERLORD is not set # CONFIG_HID_PENMOUNT is not set # CONFIG_HID_PETALYNX is not set # CONFIG_HID_PICOLCD is not set -CONFIG_HID_PLANTRONICS=y +# CONFIG_HID_PLANTRONICS is not set # CONFIG_HID_PRIMAX is not set # CONFIG_HID_RETRODE is not set # CONFIG_HID_ROCCAT is not set @@ -3222,7 +3315,7 @@ CONFIG_HID_STEAM=y # CONFIG_HID_ZYDACRON is not set # CONFIG_HID_SENSOR_HUB is not set # CONFIG_HID_ALPS is not set -CONFIG_HID_QVR=y +# CONFIG_HID_QVR is not set # # USB HID support @@ -3347,14 +3440,14 @@ CONFIG_USB_DWC3_MSM=y # CONFIG_USB_TRANCEVIBRATOR is not set # CONFIG_USB_IOWARRIOR is not set # CONFIG_USB_TEST is not set -CONFIG_USB_EHSET_TEST_FIXTURE=y +# CONFIG_USB_EHSET_TEST_FIXTURE is not set # CONFIG_USB_ISIGHTFW is not set # CONFIG_USB_YUREX is not set # CONFIG_USB_EZUSB_FX2 is not set # CONFIG_USB_HUB_USB251XB is not set # CONFIG_USB_HSIC_USB3503 is not set # CONFIG_USB_HSIC_USB4604 is not set -CONFIG_USB_LINK_LAYER_TEST=y +# CONFIG_USB_LINK_LAYER_TEST is not set # CONFIG_USB_CHAOSKEY is not set # CONFIG_USB_REDRIVER_NB7VPQ904M is not set # CONFIG_USB_TYPEC_MUX_NXP5150A is not set @@ -3374,7 +3467,7 @@ CONFIG_NOP_USB_XCEIV=y # CONFIG_USB_MSM_OTG is not set # CONFIG_USB_MSM_SSPHY is not set # CONFIG_USB_QCOM_8X16_PHY is not set -CONFIG_USB_QCOM_EMU_PHY=y +# CONFIG_USB_QCOM_EMU_PHY is not set CONFIG_USB_MSM_SSPHY_QMP=y # CONFIG_MSM_QUSB_PHY is not set CONFIG_MSM_HSUSB_PHY=y @@ -3407,16 +3500,15 @@ CONFIG_USB_U_ETHER=y CONFIG_USB_U_AUDIO=y CONFIG_USB_F_NCM=y CONFIG_USB_RNDIS=y +CONFIG_USB_F_RNDIS=y CONFIG_USB_F_MASS_STORAGE=y CONFIG_USB_F_FS=y CONFIG_USB_F_UAC2=y CONFIG_USB_F_MIDI=y -CONFIG_USB_F_HID=y CONFIG_USB_F_MTP=y CONFIG_USB_F_PTP=y CONFIG_USB_F_AUDIO_SRC=y CONFIG_USB_F_ACC=y -CONFIG_USB_F_DIAG=y CONFIG_USB_F_CDEV=y CONFIG_USB_F_CCID=y CONFIG_USB_F_GSI=y @@ -3429,7 +3521,7 @@ CONFIG_USB_CONFIGFS_NCM=y # CONFIG_USB_CONFIGFS_ECM is not set # CONFIG_USB_CONFIGFS_ECM_SUBSET is not set # CONFIG_USB_CONFIGFS_QCRNDIS is not set -# CONFIG_USB_CONFIGFS_RNDIS is not set +CONFIG_USB_CONFIGFS_RNDIS=y # CONFIG_USB_CONFIGFS_RMNET_BAM is not set # CONFIG_USB_CONFIGFS_MBIM_BAM is not set # CONFIG_USB_CONFIGFS_EEM is not set @@ -3445,10 +3537,10 @@ CONFIG_USB_CONFIGFS_UEVENT=y # CONFIG_USB_CONFIGFS_F_UAC1_LEGACY is not set CONFIG_USB_CONFIGFS_F_UAC2=y CONFIG_USB_CONFIGFS_F_MIDI=y -CONFIG_USB_CONFIGFS_F_HID=y +# CONFIG_USB_CONFIGFS_F_HID is not set # CONFIG_USB_CONFIGFS_F_UVC is not set # CONFIG_USB_CONFIGFS_F_PRINTER is not set -CONFIG_USB_CONFIGFS_F_DIAG=y +# CONFIG_USB_CONFIGFS_F_DIAG is not set CONFIG_USB_CONFIGFS_F_CDEV=y CONFIG_USB_CONFIGFS_F_CCID=y CONFIG_USB_CONFIGFS_F_GSI=y @@ -3791,7 +3883,7 @@ CONFIG_STAGING=y CONFIG_ASHMEM=y # CONFIG_ANDROID_LOW_MEMORY_KILLER is not set CONFIG_ION=y -CONFIG_ION_SYSTEM_HEAP=y +# CONFIG_ION_SYSTEM_HEAP is not set # CONFIG_ION_CARVEOUT_HEAP is not set # CONFIG_ION_CHUNK_HEAP is not set # CONFIG_ION_CMA_HEAP is not set @@ -3842,6 +3934,7 @@ CONFIG_USB_BAM=y # CONFIG_VETH_IPA is not set CONFIG_GSI=y # CONFIG_GSI_REGISTER_VERSION_2 is not set +# CONFIG_GSI_DEBUG is not set CONFIG_IPA3=y # CONFIG_IPA is not set # CONFIG_IPA_DEBUG is not set @@ -3870,7 +3963,7 @@ CONFIG_COMMON_CLK=y # CONFIG_COMMON_CLK_CDCE925 is not set # CONFIG_COMMON_CLK_CS2000_CP is not set # CONFIG_CLK_QORIQ is not set -CONFIG_COMMON_CLK_XGENE=y +# CONFIG_COMMON_CLK_XGENE is not set # CONFIG_COMMON_CLK_NXP is not set # CONFIG_COMMON_CLK_PWM is not set # CONFIG_COMMON_CLK_PXA is not set @@ -4087,10 +4180,7 @@ CONFIG_MSM_PIL=y CONFIG_MSM_SYSMON_QMI_COMM=y CONFIG_MSM_PIL_SSR_GENERIC=y # CONFIG_MSM_PIL_MSS_QDSP6V5 is not set -CONFIG_SETUP_SSR_NOTIF_TIMEOUTS=y -CONFIG_SSR_SYSMON_NOTIF_TIMEOUT=20000 -CONFIG_SSR_SUBSYS_NOTIF_TIMEOUT=20000 -CONFIG_PANIC_ON_SSR_NOTIF_TIMEOUT=y +# CONFIG_SETUP_SSR_NOTIF_TIMEOUTS is not set CONFIG_MSM_BOOT_STATS=y # CONFIG_MSM_BOOT_TIME_MARKER is not set # CONFIG_MSM_CORE_HANG_DETECT is not set @@ -4119,9 +4209,9 @@ CONFIG_QSEE_IPC_IRQ_BRIDGE=y CONFIG_QCOM_GLINK=y CONFIG_QCOM_GLINK_PKT=y # CONFIG_MSM_JTAGV8 is not set -CONFIG_QTI_RPM_STATS_LOG=y +# CONFIG_QTI_RPM_STATS_LOG is not set CONFIG_MSM_CDSP_LOADER=y -CONFIG_QCOM_SMCINVOKE=y +# CONFIG_QCOM_SMCINVOKE is not set CONFIG_MSM_EVENT_TIMER=y # CONFIG_MSM_AVTIMER is not set CONFIG_MSM_PM=y @@ -4138,8 +4228,8 @@ CONFIG_MEM_SHARE_QMI_SERVICE=y # CONFIG_MSM_HAB is not set # CONFIG_MSM_AGL is not set # CONFIG_QCOM_HGSL_TCSR_SIGNAL is not set -CONFIG_MSM_PERFORMANCE=y -CONFIG_QCOM_QHEE_ENABLE_MEM_PROTECTION=y +# CONFIG_MSM_PERFORMANCE is not set +# CONFIG_QCOM_QHEE_ENABLE_MEM_PROTECTION is not set CONFIG_QCOM_SMP2P_SLEEPSTATE=y CONFIG_QCOM_CDSP_RM=y # CONFIG_QCOM_CX_IPEAK is not set @@ -4833,8 +4923,7 @@ CONFIG_NLS_ISO8859_1=y # CONFIG_NLS_MAC_TURKISH is not set CONFIG_NLS_UTF8=y # CONFIG_DLM is not set -CONFIG_UNICODE=y -# CONFIG_UNICODE_NORMALIZATION_SELFTEST is not set +# CONFIG_UNICODE is not set # CONFIG_FILE_TABLE_DEBUG is not set # CONFIG_VIRTUALIZATION is not set @@ -4898,7 +4987,7 @@ CONFIG_CC_HAS_SANCOV_TRACE_PC=y # CONFIG_PANIC_ON_OOPS is not set CONFIG_PANIC_ON_OOPS_VALUE=0 CONFIG_PANIC_TIMEOUT=-1 -CONFIG_SCHED_DEBUG=y +# CONFIG_SCHED_DEBUG is not set # CONFIG_SCHED_INFO is not set # CONFIG_PANIC_ON_SCHED_BUG is not set # CONFIG_PANIC_ON_RT_THROTTLING is not set @@ -4923,7 +5012,6 @@ CONFIG_DEBUG_BUGVERBOSE=y CONFIG_RCU_CPU_STALL_TIMEOUT=21 CONFIG_RCU_PANIC_ON_STALL=0 CONFIG_HAVE_FUNCTION_TRACER=y -CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y CONFIG_HAVE_DYNAMIC_FTRACE=y CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y CONFIG_HAVE_SYSCALL_TRACEPOINTS=y @@ -4983,7 +5071,7 @@ CONFIG_KEYS_COMPAT=y # CONFIG_PFT is not set CONFIG_PFK=y CONFIG_PFK_WRAPPED_KEY_SUPPORTED=y -# CONFIG_SECURITY_DMESG_RESTRICT is not set +CONFIG_SECURITY_DMESG_RESTRICT=y CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y CONFIG_SECURITY=y # CONFIG_SECURITY_WRITABLE_HOOKS is not set @@ -5001,7 +5089,7 @@ CONFIG_SECURITY_SELINUX=y # CONFIG_SECURITY_SELINUX_BOOTPARAM is not set # CONFIG_SECURITY_SELINUX_DISABLE is not set CONFIG_SECURITY_SELINUX_DEVELOP=y -CONFIG_SECURITY_SELINUX_AVC_STATS=y +# CONFIG_SECURITY_SELINUX_AVC_STATS is not set CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=0 CONFIG_SECURITY_SELINUX_SIDTAB_HASH_BITS=9 # CONFIG_SECURITY_SMACK is not set @@ -5153,8 +5241,8 @@ CONFIG_CRYPTO_ZSTD=y CONFIG_CRYPTO_ANSI_CPRNG=y CONFIG_CRYPTO_DRBG_MENU=y CONFIG_CRYPTO_DRBG_HMAC=y -CONFIG_CRYPTO_DRBG_HASH=y -CONFIG_CRYPTO_DRBG_CTR=y +# CONFIG_CRYPTO_DRBG_HASH is not set +# CONFIG_CRYPTO_DRBG_CTR is not set CONFIG_CRYPTO_DRBG=y CONFIG_CRYPTO_JITTERENTROPY=y # CONFIG_CRYPTO_USER_API_HASH is not set @@ -5232,6 +5320,7 @@ CONFIG_ZSTD_DECOMPRESS=y # CONFIG_XZ_DEC is not set # CONFIG_XZ_DEC_BCJ is not set CONFIG_DECOMPRESS_GZIP=y +CONFIG_DECOMPRESS_LZ4=y CONFIG_GENERIC_ALLOCATOR=y CONFIG_REED_SOLOMON=y CONFIG_REED_SOLOMON_ENC8=y From c4b7c845a085addbb4c53293f9fe1896bb9f8fa1 Mon Sep 17 00:00:00 2001 From: UtsavBalar1231 Date: Mon, 3 Aug 2020 19:34:04 +0530 Subject: [PATCH 444/592] sm8150: squash remove place_marker usage sed -i -e '/place_marker/d' $(git grep -l place_marker | tr '\n' ' ') and manually remove snprintf() usage for boot marker Signed-off-by: UtsavBalar1231 --- arch/arm64/kernel/hibernate.c | 2 -- drivers/gnsssirf/gnss_sirf.c | 4 ---- drivers/gpu/drm/msm/msm_drv.c | 1 - drivers/gpu/msm/adreno.c | 4 ---- drivers/gpu/msm/kgsl.c | 2 -- drivers/i2c/busses/i2c-qcom-geni.c | 6 ------ drivers/media/platform/msm/vidc/msm_v4l2_vidc.c | 5 ----- drivers/platform/msm/ep_pcie/ep_pcie_core.c | 2 -- .../platform/msm/ipa/ipa_v3/ipa_qmi_service.c | 1 - drivers/platform/msm/mhi_dev/mhi.c | 1 - drivers/soc/qcom/peripheral-loader.c | 6 ------ drivers/spi/spi-geni-qcom.c | 8 -------- drivers/tty/serial/msm_geni_serial.c | 17 ----------------- drivers/usb/dwc3/dwc3-msm.c | 2 -- drivers/usb/gadget/composite.c | 2 -- init/do_mounts.c | 2 -- init/main.c | 1 - kernel/power/hibernate.c | 6 ------ 18 files changed, 72 deletions(-) diff --git a/arch/arm64/kernel/hibernate.c b/arch/arm64/kernel/hibernate.c index 95b5f7679e39..90f980bedb20 100644 --- a/arch/arm64/kernel/hibernate.c +++ b/arch/arm64/kernel/hibernate.c @@ -303,7 +303,6 @@ int swsusp_arch_suspend(void) sleep_cpu = smp_processor_id(); ret = swsusp_save(); } else { - place_marker("M - Image Kernel Start"); /* Clean kernel core startup/idle code to PoC*/ dcache_clean_range(__mmuoff_data_start, __mmuoff_data_end); dcache_clean_range(__idmap_text_start, __idmap_text_end); @@ -339,7 +338,6 @@ int swsusp_arch_suspend(void) } local_dbg_restore(flags); - place_marker("PM: Kernel restore start!"); return ret; } diff --git a/drivers/gnsssirf/gnss_sirf.c b/drivers/gnsssirf/gnss_sirf.c index d10749166767..91d6198eaa7c 100644 --- a/drivers/gnsssirf/gnss_sirf.c +++ b/drivers/gnsssirf/gnss_sirf.c @@ -238,10 +238,6 @@ static int gnss_sirf_probe(struct platform_device *pdev) onOffPin = of_get_named_gpio(pdev->dev.of_node, "ssVonoff-gpio", 0); ret = configurePins(pdev); - if (ret == 0) { - snprintf(boot_marker, sizeof(boot_marker), - "M - DRIVER GNSS Ready"); - place_marker(boot_marker); } } } diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 423d225dedc7..a2973c859d79 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -948,7 +948,6 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv) } drm_kms_helper_poll_init(ddev); - place_marker("M - DISPLAY Driver Ready"); return 0; diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index 0e364772706e..1ae774892ecd 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -1190,7 +1190,6 @@ static int adreno_probe(struct platform_device *pdev) struct adreno_device *adreno_dev; int status; - place_marker("M - DRIVER GPU Init"); adreno_dev = adreno_get_dev(pdev); @@ -1319,7 +1318,6 @@ static int adreno_probe(struct platform_device *pdev) "Failed to get gpuhtw LLC slice descriptor %ld\n", PTR_ERR(adreno_dev->gpuhtw_llc_slice)); - place_marker("M - DRIVER GPU Ready"); out: if (status) { adreno_ringbuffer_close(adreno_dev); @@ -1528,7 +1526,6 @@ static int adreno_init(struct kgsl_device *device) if (test_bit(ADRENO_DEVICE_INITIALIZED, &adreno_dev->priv)) return 0; - place_marker("M - DRIVER ADRENO Init"); /* * Either the microcode read failed because the usermodehelper isn't @@ -1603,7 +1600,6 @@ static int adreno_init(struct kgsl_device *device) } - place_marker("M - DRIVER ADRENO Ready"); return 0; } diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index f75e68e86d73..c346f4174e41 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -5116,7 +5116,6 @@ static int __init kgsl_core_init(void) int result = 0; struct sched_param param = { .sched_priority = 2 }; - place_marker("M - DRIVER KGSL Init"); /* alloc major and minor device numbers */ result = alloc_chrdev_region(&kgsl_driver.major, 0, KGSL_DEVICE_MAX, @@ -5203,7 +5202,6 @@ static int __init kgsl_core_init(void) kgsl_memfree_init(); - place_marker("M - DRIVER KGSL Ready"); return 0; diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c index 3b07969a48c0..dd7ee148b780 100644 --- a/drivers/i2c/busses/i2c-qcom-geni.c +++ b/drivers/i2c/busses/i2c-qcom-geni.c @@ -811,9 +811,6 @@ static int geni_i2c_probe(struct platform_device *pdev) return -ENOMEM; gi2c->dev = &pdev->dev; - snprintf(boot_marker, sizeof(boot_marker), - "M - DRIVER GENI_I2C Init"); - place_marker(boot_marker); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) @@ -954,9 +951,6 @@ static int geni_i2c_probe(struct platform_device *pdev) pm_runtime_enable(gi2c->dev); i2c_add_adapter(&gi2c->adap); - snprintf(boot_marker, sizeof(boot_marker), - "M - DRIVER GENI_I2C_%d Ready", gi2c->adap.nr); - place_marker(boot_marker); dev_dbg(gi2c->dev, "I2C probed\n"); return 0; } diff --git a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c index c8306b70ddf4..8c601e3d8779 100644 --- a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c +++ b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c @@ -534,7 +534,6 @@ static int msm_vidc_probe_vidc_device(struct platform_device *pdev) struct device *dev; int nr = BASE_DEVICE_NUMBER; - place_marker("M - DRIVER Video Start"); if (!vidc_driver) { dprintk(VIDC_ERR, "Invalid vidc driver\n"); @@ -642,7 +641,6 @@ static int msm_vidc_probe_vidc_device(struct platform_device *pdev) goto err_fail_sub_device_probe; } - place_marker("M - DRIVER Video Ready"); return rc; err_fail_sub_device_probe: @@ -785,7 +783,6 @@ static int msm_vidc_pm_suspend(struct device *dev) static int msm_vidc_pm_resume(struct device *dev) { - place_marker("vidc resumed"); dprintk(VIDC_INFO, "%s\n", __func__); return 0; } @@ -855,11 +852,9 @@ static int msm_vidc_pm_freeze(struct device *dev) return 0; if (of_device_is_compatible(dev->of_node, "qcom,msm-vidc")) { - place_marker("vidc hibernation start"); rc = msm_vidc_freeze_core(core); - place_marker("vidc hibernation end"); } dprintk(VIDC_INFO, "%s: done\n", __func__); diff --git a/drivers/platform/msm/ep_pcie/ep_pcie_core.c b/drivers/platform/msm/ep_pcie/ep_pcie_core.c index bd1cfcb3dc13..61c6e12c99e0 100644 --- a/drivers/platform/msm/ep_pcie/ep_pcie_core.c +++ b/drivers/platform/msm/ep_pcie/ep_pcie_core.c @@ -1895,8 +1895,6 @@ int ep_pcie_core_enable_endpoint(enum ep_pcie_options opt) "PCIe V%d: link initialized for LE PCIe endpoint\n", dev->rev); pr_crit("PCIe - link initialized for LE PCIe endpoint\n"); - place_marker( - "PCIe - link initialized for LE PCIe endpoint\n"); } checkbme: diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c index 266734f4ba9f..af148df76365 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c @@ -685,7 +685,6 @@ static int ipa3_qmi_init_modem_send_sync_msg(void) pr_info("QMI_IPA_INIT_MODEM_DRIVER_REQ_V01 response received\n"); - place_marker("M - QMI ready for commands"); return ipa3_check_qmi_response(rc, QMI_IPA_INIT_MODEM_DRIVER_REQ_V01, resp.resp.result, diff --git a/drivers/platform/msm/mhi_dev/mhi.c b/drivers/platform/msm/mhi_dev/mhi.c index f2336be13d8d..e49cd9e07441 100644 --- a/drivers/platform/msm/mhi_dev/mhi.c +++ b/drivers/platform/msm/mhi_dev/mhi.c @@ -1276,7 +1276,6 @@ static void mhi_hwc_cb(void *priv, enum ipa_mhi_event_type event, } mhi_log(MHI_MSG_CRITICAL, "Device in M0 State\n"); - place_marker("MHI - Device in M0 State\n"); break; case IPA_MHI_EVENT_DATA_AVAILABLE: rc = mhi_dev_notify_sm_event(MHI_DEV_EVENT_HW_ACC_WAKEUP); diff --git a/drivers/soc/qcom/peripheral-loader.c b/drivers/soc/qcom/peripheral-loader.c index be9d092727d6..b51e434c2a64 100644 --- a/drivers/soc/qcom/peripheral-loader.c +++ b/drivers/soc/qcom/peripheral-loader.c @@ -945,9 +945,6 @@ static int pil_init_mmap(struct pil_desc *desc, const struct pil_mdt *mdt) if (ret) return ret; - if (!strcmp(desc->name, "modem")) - place_marker("M - Modem Image Start Loading"); - pil_info(desc, "loading from %pa to %pa\n", &priv->region_start, &priv->region_end); @@ -1408,9 +1405,6 @@ int pil_boot(struct pil_desc *desc) } pil_log("reset_done", desc); - if (!strcmp(desc->name, "modem")) - place_marker("M - Modem out of reset"); - pil_info(desc, "Brought out of reset\n"); desc->modem_ssr = false; err_auth_and_reset: diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c index 5661f12b2737..2d5ca183da3a 100644 --- a/drivers/spi/spi-geni-qcom.c +++ b/drivers/spi/spi-geni-qcom.c @@ -1586,10 +1586,6 @@ static int spi_geni_probe(struct platform_device *pdev) goto spi_geni_probe_err; } - snprintf(boot_marker, sizeof(boot_marker), - "M - DRIVER GENI_SPI Init"); - place_marker(boot_marker); - platform_set_drvdata(pdev, spi); geni_mas = spi_master_get_devdata(spi); rsc = &geni_mas->spi_rsc; @@ -1769,10 +1765,6 @@ static int spi_geni_probe(struct platform_device *pdev) } sysfs_create_file(&(geni_mas->dev->kobj), &dev_attr_spi_slave_state.attr); - snprintf(boot_marker, sizeof(boot_marker), - "M - DRIVER GENI_SPI_%d Ready", spi->bus_num); - place_marker(boot_marker); - return ret; spi_geni_probe_unmap: devm_iounmap(&pdev->dev, geni_mas->base); diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c index bff6aaf346ae..9e4dd9e68e93 100644 --- a/drivers/tty/serial/msm_geni_serial.c +++ b/drivers/tty/serial/msm_geni_serial.c @@ -2441,14 +2441,6 @@ static int msm_geni_serial_probe(struct platform_device *pdev) line = pdev->id; } - if (strcmp(id->compatible, "qcom,msm-geni-console") == 0) - snprintf(boot_marker, sizeof(boot_marker), - "M - DRIVER GENI_UART_%d Init", line); - else - snprintf(boot_marker, sizeof(boot_marker), - "M - DRIVER GENI_HS_UART_%d Init", line); - place_marker(boot_marker); - #ifdef SERIAL_CONSOLE is_console = (drv->cons ? true : false); dev_port = get_port_from_line(line, is_console); @@ -2638,15 +2630,6 @@ static int msm_geni_serial_probe(struct platform_device *pdev) goto exit_geni_serial_probe; ret = uart_add_one_port(drv, uport); - if (!ret) { - if (strcmp(id->compatible, "qcom,msm-geni-console") == 0) - snprintf(boot_marker, sizeof(boot_marker), - "M - DRIVER GENI_UART_%d Ready", line); - else - snprintf(boot_marker, sizeof(boot_marker), - "M - DRIVER GENI_HS_UART_%d Ready", line); - place_marker(boot_marker); - } exit_geni_serial_probe: return ret; } diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index fdd51b3a9913..b3366c67dcd2 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -3298,7 +3298,6 @@ static irqreturn_t msm_dwc3_pwr_irq(int irq, void *data) if (mdwc->drd_state == DRD_STATE_PERIPHERAL_SUSPEND) { dev_info(mdwc->dev, "USB Resume start\n"); - place_marker("M - USB device resume started"); } /* @@ -5173,7 +5172,6 @@ static int dwc3_msm_pm_resume(struct device *dev) if (atomic_read(&dwc->in_lpm) && mdwc->drd_state == DRD_STATE_PERIPHERAL_SUSPEND) { dev_info(mdwc->dev, "USB Resume start\n"); - place_marker("M - USB device resume started"); } if (!dwc->ignore_wakeup_src_in_hostmode || !mdwc->in_host_mode) { diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 6e5a9ce5ff7f..c8b2e08512ff 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -965,7 +965,6 @@ static int set_config(struct usb_composite_dev *cdev, if (!c) goto done; - place_marker("M - USB Device is enumerated"); usb_gadget_set_state(gadget, USB_STATE_CONFIGURED); cdev->config = c; @@ -2482,7 +2481,6 @@ void composite_resume(struct usb_gadget *gadget) * suspend/resume callbacks? */ INFO(cdev, "USB Resume end\n"); - place_marker("M - USB device is resumed"); if (cdev->driver->resume) cdev->driver->resume(cdev); diff --git a/init/do_mounts.c b/init/do_mounts.c index 26f2d53876ea..63c3591937cc 100644 --- a/init/do_mounts.c +++ b/init/do_mounts.c @@ -450,7 +450,6 @@ static int __init do_mount_root(char *name, char *fs, int flags, void *data) struct super_block *s; int err; - place_marker("M - DRIVER F/S Init"); err = sys_mount((char __user *)name, (char __user *)"/root", (char __user *)fs, (unsigned long)flags, @@ -467,7 +466,6 @@ static int __init do_mount_root(char *name, char *fs, int flags, void *data) sb_rdonly(s) ? " readonly" : "", MAJOR(ROOT_DEV), MINOR(ROOT_DEV)); - place_marker("M - DRIVER F/S Ready"); return 0; } diff --git a/init/main.c b/init/main.c index 805853c2fb63..8ff9f47c2a6a 100644 --- a/init/main.c +++ b/init/main.c @@ -1040,7 +1040,6 @@ static int __ref kernel_init(void *unused) numa_default_policy(); rcu_end_inkernel_boot(); - place_marker("M - DRIVER Kernel Boot Done"); if (ramdisk_execute_command) { ret = run_init_process(ramdisk_execute_command); diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index 4b007fd99af2..9be5dfdf5b4e 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c @@ -335,7 +335,6 @@ static int create_image(int platform_mode) Platform_finish: platform_finish(platform_mode); - place_marker("M - Hibernation: start device resume"); dpm_resume_start(in_suspend ? (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE); @@ -411,7 +410,6 @@ int hibernation_snapshot(int platform_mode) resume_console(); dpm_complete(msg); - place_marker("M - Hibernation: end device resume"); Close: platform_end(platform_mode); return error; @@ -751,7 +749,6 @@ int hibernate(void) in_suspend = 0; pm_restore_gfp_mask(); } else { - place_marker("M - PM: Image restored!"); pm_pr_dbg("Image restored successfully.\n"); } @@ -766,7 +763,6 @@ int hibernate(void) error = load_image_and_restore(); } thaw_processes(); - place_marker("M - Hibernation: processes thaw done"); /* Don't bother checking whether freezer_test_done is true */ freezer_test_done = false; @@ -776,7 +772,6 @@ int hibernate(void) atomic_inc(&snapshot_device_available); Unlock: unlock_system_sleep(); - place_marker("M - PM: Hibernation Exit!"); pr_info("hibernation exit\n"); return error; @@ -906,7 +901,6 @@ static int software_resume(void) error = load_image_and_restore(); thaw_processes(); - place_marker("M - PM: Thaw processes completed!"); Finish: __pm_notifier_call_chain(PM_POST_RESTORE, nr_calls, NULL); pm_restore_console(); From fe47fd9ee20555fad5b2063607f3dea68802fe31 Mon Sep 17 00:00:00 2001 From: UtsavBalar1231 Date: Thu, 6 Aug 2020 12:10:54 +0530 Subject: [PATCH 445/592] goodix_driver_gt9886: use async probing and suspend/resume asynchronous probing can help in booting this drivers faster and can help in avoiding suspended/resumed delays Signed-off-by: UtsavBalar1231 --- drivers/input/touchscreen/goodix_driver_gt9886/goodix_ts_core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/input/touchscreen/goodix_driver_gt9886/goodix_ts_core.c b/drivers/input/touchscreen/goodix_driver_gt9886/goodix_ts_core.c index 58fb3231e367..0f6cc980d75a 100644 --- a/drivers/input/touchscreen/goodix_driver_gt9886/goodix_ts_core.c +++ b/drivers/input/touchscreen/goodix_driver_gt9886/goodix_ts_core.c @@ -2190,6 +2190,7 @@ static int goodix_ts_probe(struct platform_device *pdev) } #endif + device_enable_async_suspend(&pdev->dev); out: backlight_unregister_notifier(&core_data->bl_notifier); ts_info("goodix_ts_probe OUT, r:%d", r); @@ -2230,6 +2231,7 @@ static struct platform_driver goodix_ts_driver = { #ifdef CONFIG_PM .pm = &dev_pm_ops, #endif + .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, .probe = goodix_ts_probe, .remove = goodix_ts_remove, From 427dcc5f2e0f967314142e3debdf71a545a863c9 Mon Sep 17 00:00:00 2001 From: UtsavBalar1231 Date: Mon, 3 Aug 2020 20:18:52 +0530 Subject: [PATCH 446/592] kernel: update build tools Signed-off-by: UtsavBalar1231 --- README.md | 7 +++---- build-lto.sh | 15 +++++++++------ build.sh | 12 ++++++------ update | 10 ++++++++++ updatedefconfig | 5 +++-- 5 files changed, 31 insertions(+), 18 deletions(-) create mode 100644 update diff --git a/README.md b/README.md index 5ef116b07359..d8ba802aed14 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,7 @@ -# iMMENSITY KERNAL for RedmiK20pro / Mi9Tpro +# IMMENSiTY KERNAL for Redmi K20pro / Mi9Tpro ![logo](https://github.com/UtsavBalar1231/xda-stuff/raw/master/immensity-new.png "logo here") -> Based on the Qualcomm AUTO tag **LE.UM.4.2.1.r1-02600-QCS404.0** -> Merged AOSP kernel_common/android-4.14-stable [4.14.185] -> Current CAF tag: **LE.UM.4.1.1.r1-00300-sa515m** +> Merged AOSP android-4.14-stable [4.14.192] +> Latest CAF tag: **LE.UM.3.2.3-45100-SA2150p** diff --git a/build-lto.sh b/build-lto.sh index a4276c643f81..2b4268b4de10 100644 --- a/build-lto.sh +++ b/build-lto.sh @@ -6,14 +6,14 @@ export KBUILD_BUILD_HOST=CuntsSpace make ARCH=arm64 \ O=${OUT_DIR} \ raphael_defconfig \ - -j4 + -j8 scripts/config --file ${OUT_DIR}/.config \ -e LTO \ -e LTO_CLANG \ + -e SHADOW_CALL_STACK \ -e TOOLS_SUPPORT_RELR \ - -e LD_LLD \ - -e LLVM_POLLY + -e LD_LLD cd ${OUT_DIR} make O=${OUT_DIR} \ @@ -24,17 +24,20 @@ cd ../ PATH=/home/utsavthecunt/proton-clang/bin/:$PATH make ARCH=arm64 \ - O=out \ + O=${OUT_DIR} \ CC="ccache clang" \ + LLVM_IAS=1 \ LD="ld.lld" \ AR="llvm-ar" \ NM="llvm-nm" \ OBJCOPY="llvm-objcopy" \ OBJDUMP="llvm-objdump" \ + OBJSIZE="llvm-size" \ + READELF="llvm-readelf" \ STRIP="llvm-strip" \ CLANG_TRIPLE="aarch64-linux-gnu-" \ CROSS_COMPILE="aarch64-linux-gnu-" \ CROSS_COMPILE_ARM32="arm-linux-gnueabi-" \ - -j4 + -j8 -rm out/.version +rm ${OUT_DIR}/.version diff --git a/build.sh b/build.sh index 89d689de1e03..0ddef5fe0729 100644 --- a/build.sh +++ b/build.sh @@ -6,14 +6,14 @@ export KBUILD_BUILD_HOST=CuntsSpace make ARCH=arm64 \ O=${OUT_DIR} \ raphael_defconfig \ - -j4 + -j8 scripts/config --file ${OUT_DIR}/.config \ -d LTO \ -d LTO_CLANG \ + -e SHADOW_CALL_STACK \ -e TOOLS_SUPPORT_RELR \ - -e LD_LLD \ - -e LLVM_POLLY + -e LD_LLD cd ${OUT_DIR} make O=${OUT_DIR} \ @@ -24,7 +24,7 @@ cd ../ PATH=/home/utsavthecunt/proton-clang/bin/:$PATH make ARCH=arm64 \ - O=out \ + O=${OUT_DIR} \ CC="ccache clang" \ LD="ld.lld" \ AR="llvm-ar" \ @@ -35,6 +35,6 @@ make ARCH=arm64 \ CLANG_TRIPLE="aarch64-linux-gnu-" \ CROSS_COMPILE="aarch64-linux-gnu-" \ CROSS_COMPILE_ARM32="arm-linux-gnueabi-" \ - -j4 + -j8 -rm out/.version +rm ${OUT_DIR}/.version diff --git a/update b/update new file mode 100644 index 000000000000..9f478d970f58 --- /dev/null +++ b/update @@ -0,0 +1,10 @@ +#!/bin/bash +OUT_DIR=out/ + +make ARCH=arm64 \ + O=${OUT_DIR} \ + raphael_defconfig \ + -j$(nproc --all) + +mv out/.config arch/arm64/configs/raphael_defconfig +git diff diff --git a/updatedefconfig b/updatedefconfig index 95b6ff52c022..b24306bf40ba 100644 --- a/updatedefconfig +++ b/updatedefconfig @@ -4,9 +4,10 @@ OUT_DIR=out/ make ARCH=arm64 \ O=${OUT_DIR} \ raphael_defconfig \ - -j4 + -j8 cp ${OUT_DIR}/.config arch/arm64/configs/raphael_defconfig -git add arch/ +git add arch/arm64/configs/raphael_defconfig + git commit -s -m "ARM64: configs: raphael: Update defconfig" From 2b76578ef118a6f3671647d68c017c7d13a4fd99 Mon Sep 17 00:00:00 2001 From: UtsavBalar1231 Date: Thu, 6 Aug 2020 13:58:29 +0530 Subject: [PATCH 447/592] techpack: silence some logging - yeah yeah i know its working dont spam me you fuck Signed-off-by: UtsavBalar1231 --- techpack/audio/asoc/codecs/tfa98xx/src/tfa98xx.c | 4 ++-- techpack/audio/dsp/msm-cirrus-playback.c | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/techpack/audio/asoc/codecs/tfa98xx/src/tfa98xx.c b/techpack/audio/asoc/codecs/tfa98xx/src/tfa98xx.c index 836ce927c2f4..ebd43dbaa9a5 100644 --- a/techpack/audio/asoc/codecs/tfa98xx/src/tfa98xx.c +++ b/techpack/audio/asoc/codecs/tfa98xx/src/tfa98xx.c @@ -2874,7 +2874,7 @@ enum Tfa98xx_Error tfa98xx_adsp_send_calib_values(void) if (tfa98xx_device_count == 1) { memcpy(&bytes[7], &bytes[4], sizeof(char)*3); } - pr_info("tfa98xx_device_count=%d bytes[0]=%d\n", tfa98xx_device_count, bytes[0]); + pr_debug("tfa98xx_device_count=%d bytes[0]=%d\n", tfa98xx_device_count, bytes[0]); /* we will send it to host DSP algorithm once calibraion value loaded from all device. */ if (tfa98xx_device_count == bytes[0]) { @@ -2902,7 +2902,7 @@ static int tfa98xx_send_mute_cmd(void) { uint8_t cmd[9] = {0x04, 0x81, 0x04, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff}; - pr_info("send mute command to host DSP.\n"); + pr_debug("send mute command to host DSP.\n"); return send_tfa_cal_in_band(&cmd[0], sizeof(cmd)); } #endif diff --git a/techpack/audio/dsp/msm-cirrus-playback.c b/techpack/audio/dsp/msm-cirrus-playback.c index 8add0c570a5c..d074740c823e 100755 --- a/techpack/audio/dsp/msm-cirrus-playback.c +++ b/techpack/audio/dsp/msm-cirrus-playback.c @@ -1141,7 +1141,7 @@ int crus_afe_port_start(u16 port_id) { EXPORT_SYMBOL(crus_afe_port_start); int crus_afe_port_close(u16 port_id) { - pr_info("%s: 0x%x\n", __func__, port_id); + pr_debug("%s: 0x%x\n", __func__, port_id); //CSPL do not be involved in AFE #if 0 @@ -1161,7 +1161,7 @@ static long crus_sp_shared_ioctl(struct file *f, unsigned int cmd, uint32_t bufsize = 0, size; void *io_data = NULL; - pr_info("%s\n", __func__); + pr_debug("%s\n", __func__); if (copy_from_user(&size, arg, sizeof(size))) { pr_err("CRUS_SP: copy_from_user (size) failed\n"); @@ -1223,7 +1223,7 @@ static long crus_sp_shared_ioctl(struct file *f, unsigned int cmd, port = this_ctrl.ff_port; break; default: - pr_info("%s: Unrecognized port ID (%d)\n", __func__, + pr_debug("%s: Unrecognized port ID (%d)\n", __func__, crus_sp_hdr.module_id); port = this_ctrl.ff_port; } @@ -1252,7 +1252,7 @@ exit: static long crus_sp_ioctl(struct file *f, unsigned int cmd, unsigned long arg) { - pr_info("%s\n", __func__); + pr_debug("%s\n", __func__); return crus_sp_shared_ioctl(f, cmd, (void __user *)arg); } @@ -1262,7 +1262,7 @@ static long crus_sp_compat_ioctl(struct file *f, { unsigned int cmd64; - pr_info("%s\n", __func__); + pr_debug("%s\n", __func__); switch (cmd) { case CRUS_SP_IOCTL_GET32: From c1d32ee4f83d86838b6fc52469c6ec0b292ade06 Mon Sep 17 00:00:00 2001 From: UtsavBalar1231 Date: Thu, 6 Aug 2020 16:50:09 +0530 Subject: [PATCH 448/592] msm: gsi: silence gsi_config_channel_mode logging Signed-off-by: UtsavBalar1231 --- drivers/platform/msm/gsi/gsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/msm/gsi/gsi.c b/drivers/platform/msm/gsi/gsi.c index 1a05c655dd27..5a85ca72d24d 100644 --- a/drivers/platform/msm/gsi/gsi.c +++ b/drivers/platform/msm/gsi/gsi.c @@ -3852,7 +3852,7 @@ int gsi_config_channel_mode(unsigned long chan_hdl, enum gsi_chan_mode mode) curr = GSI_CHAN_MODE_CALLBACK; if (mode == curr) { - GSIERR("already in requested mode %u chan_hdl=%lu\n", + GSIDBG("already in requested mode %u chan_hdl=%lu\n", curr, chan_hdl); spin_unlock_irqrestore(&gsi_ctx->slock, flags); return -GSI_STATUS_UNSUPPORTED_OP; From a9d63536bc8b4965fb42d2d9d342fd4ad7e16b8e Mon Sep 17 00:00:00 2001 From: Yaroslav Furman Date: Fri, 6 Dec 2019 02:52:36 +0300 Subject: [PATCH 449/592] msm: gsi: disable debug driver Signed-off-by: Yaroslav Furman Signed-off-by: UtsavBalar1231 --- drivers/platform/msm/Kconfig | 5 +++++ drivers/platform/msm/gsi/Makefile | 5 ++--- drivers/platform/msm/gsi/gsi.c | 4 ++-- drivers/platform/msm/gsi/gsi.h | 2 ++ 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/platform/msm/Kconfig b/drivers/platform/msm/Kconfig index 25893daa6886..7dbb3fe34e81 100644 --- a/drivers/platform/msm/Kconfig +++ b/drivers/platform/msm/Kconfig @@ -112,6 +112,11 @@ config GSI_REGISTER_VERSION_2 new registers offsets, new registers fields structure and new registers. +config GSI_DEBUG + bool "Debugging part of GSI core" + depends on GSI || DEBUG_FS + default n + config MSM_MHI_DEV tristate "Modem Device Interface Driver" depends on EP_PCIE && IPA3 diff --git a/drivers/platform/msm/gsi/Makefile b/drivers/platform/msm/gsi/Makefile index 90d1a19ac366..faf4dc031cc4 100644 --- a/drivers/platform/msm/gsi/Makefile +++ b/drivers/platform/msm/gsi/Makefile @@ -1,4 +1,3 @@ -gsidbg-$(CONFIG_GSI) += gsi_dbg.o -obj-$(CONFIG_GSI) += gsi.o gsidbg.o - +obj-$(CONFIG_GSI) += gsi.o +obj-$(CONFIG_GSI_DEBUG) += gsidbg.o gsi_dbg.o obj-$(CONFIG_IPA_EMULATION) += gsi_emulation.o diff --git a/drivers/platform/msm/gsi/gsi.c b/drivers/platform/msm/gsi/gsi.c index 5a85ca72d24d..b13347dbac96 100644 --- a/drivers/platform/msm/gsi/gsi.c +++ b/drivers/platform/msm/gsi/gsi.c @@ -38,8 +38,8 @@ #define GSI_STTS_REG_BITS 32 -#ifndef CONFIG_DEBUG_FS -void gsi_debugfs_init(void) +#ifndef CONFIG_GSI_DEBUG +static inline void gsi_debugfs_init(void) { } #endif diff --git a/drivers/platform/msm/gsi/gsi.h b/drivers/platform/msm/gsi/gsi.h index 2f044f2b0d0a..4f09f029639c 100644 --- a/drivers/platform/msm/gsi/gsi.h +++ b/drivers/platform/msm/gsi/gsi.h @@ -342,7 +342,9 @@ enum gsi_generic_ee_cmd_return_code { }; extern struct gsi_ctx *gsi_ctx; +#ifdef CONFIG_GSI_DEBUG void gsi_debugfs_init(void); +#endif uint16_t gsi_find_idx_from_addr(struct gsi_ring_ctx *ctx, uint64_t addr); void gsi_update_ch_dp_stats(struct gsi_chan_ctx *ctx, uint16_t used); From 822199a41b158f273fb52ad37ed2148ec3bb214d Mon Sep 17 00:00:00 2001 From: UtsavBalar1231 Date: Mon, 3 Aug 2020 19:18:48 +0530 Subject: [PATCH 450/592] Revert "ANDROID: drivers base/arch_topology: avoid a stuck risk when cpufreq policy free" no This reverts commit 3490e0b6e13438e4aca40a66861febf15c0a9afb. Signed-off-by: UtsavBalar1231 --- drivers/base/arch_topology.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c index 0d9e8a6d6789..4fdec17fbc1b 100644 --- a/drivers/base/arch_topology.c +++ b/drivers/base/arch_topology.c @@ -185,25 +185,20 @@ int detect_share_cap_flag(void) cpumask_equal(topology_sibling_cpumask(cpu), policy->related_cpus)) { share_cap_level = share_cap_thread; - cpufreq_cpu_put(policy); continue; } if (cpumask_equal(topology_core_cpumask(cpu), policy->related_cpus)) { share_cap_level = share_cap_core; - cpufreq_cpu_put(policy); continue; } if (cpumask_equal(cpu_cpu_mask(cpu), policy->related_cpus)) { share_cap_level = share_cap_die; - cpufreq_cpu_put(policy); continue; } - - cpufreq_cpu_put(policy); } if (share_cap != share_cap_level) { From a67e7ebd076a9a679ebb3a68f3c80a52c04b79f4 Mon Sep 17 00:00:00 2001 From: UtsavBalar1231 Date: Thu, 6 Aug 2020 13:02:32 +0530 Subject: [PATCH 451/592] Revert "drm/msm/dsi-staging: Add C-PHY support for phy ver 3.0" This reverts commit db18ff124685c3edbc02cae913be38e264c32475. Signed-off-by: UtsavBalar1231 --- .../gpu/drm/msm/dsi-staging/dsi_phy_hw_v3_0.c | 148 ++---------------- 1 file changed, 17 insertions(+), 131 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v3_0.c b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v3_0.c index 2f161a720d56..556c01911a68 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v3_0.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v3_0.c @@ -176,40 +176,7 @@ static void dsi_phy_hw_v3_0_lane_swap_config(struct dsi_phy_hw *phy, (lane_map->lane_map_v2[DSI_LOGICAL_LANE_3] << 4))); } -static void dsi_phy_hw_v3_0_cphy_lane_settings(struct dsi_phy_hw *phy, - struct dsi_phy_cfg *cfg) -{ - int i; - - /* Strength ctrl settings */ - for (i = DSI_LOGICAL_LANE_0; i < DSI_LOGICAL_LANE_3; i++) { - DSI_W32(phy, DSIPHY_LNX_LPTX_STR_CTRL(i), - cfg->strength.lane[i][0]); - /* - * Disable LPRX and CDRX for all lanes. And later on, it will - * be only enabled for the physical data lane corresponding - * to the logical data lane 0 - */ - DSI_W32(phy, DSIPHY_LNX_LPRX_CTRL(i), 0); - DSI_W32(phy, DSIPHY_LNX_PIN_SWAP(i), 0x0); - DSI_W32(phy, DSIPHY_LNX_HSTX_STR_CTRL(i), 0x88); - } - dsi_phy_hw_v3_0_config_lpcdrx(phy, cfg, true); - - /* other settings */ - for (i = DSI_LOGICAL_LANE_0; i < DSI_LOGICAL_LANE_3; i++) { - DSI_W32(phy, DSIPHY_LNX_CFG0(i), cfg->lanecfg.lane[i][0]); - DSI_W32(phy, DSIPHY_LNX_CFG1(i), cfg->lanecfg.lane[i][1]); - DSI_W32(phy, DSIPHY_LNX_CFG2(i), cfg->lanecfg.lane[i][2]); - DSI_W32(phy, DSIPHY_LNX_CFG3(i), 0x0A); - DSI_W32(phy, DSIPHY_LNX_OFFSET_TOP_CTRL(i), 0x0); - DSI_W32(phy, DSIPHY_LNX_OFFSET_BOT_CTRL(i), 0x0); - } - - DSI_W32(phy, DSIPHY_LNX_TX_DCTRL(3), 0x02); -} - -static void dsi_phy_hw_v3_0_dphy_lane_settings(struct dsi_phy_hw *phy, +static void dsi_phy_hw_v3_0_lane_settings(struct dsi_phy_hw *phy, struct dsi_phy_cfg *cfg) { int i; @@ -268,82 +235,32 @@ void dsi_phy_hw_v3_0_clamp_ctrl(struct dsi_phy_hw *phy, bool enable) } /** - * cphy_enable() - Enable CPHY hardware + * enable() - Enable PHY hardware * @phy: Pointer to DSI PHY hardware object. * @cfg: Per lane configurations for timing, strength and lane * configurations. */ -static void dsi_phy_hw_cphy_enable(struct dsi_phy_hw *phy, +void dsi_phy_hw_v3_0_enable(struct dsi_phy_hw *phy, struct dsi_phy_cfg *cfg) { + int rc = 0; + u32 status; + u32 const delay_us = 5; + u32 const timeout_us = 1000; struct dsi_phy_per_lane_cfgs *timing = &cfg->timing; u32 data; - /* de-assert digital and pll power down */ - data = BIT(6) | BIT(5); - DSI_W32(phy, DSIPHY_CMN_CTRL_0, data); + if (dsi_phy_hw_v3_0_is_pll_on(phy)) + pr_warn("PLL turned on before configuring PHY\n"); - /* Assert PLL core reset */ - DSI_W32(phy, DSIPHY_CMN_PLL_CNTRL, 0x00); - - /* turn off resync FIFO */ - DSI_W32(phy, DSIPHY_CMN_RBUF_CTRL, 0x00); - - DSI_W32(phy, DSIPHY_CMN_GLBL_CTRL, 0x40); - - /* Enable LDO */ - DSI_W32(phy, DSIPHY_CMN_VREG_CTRL, 0x59); - - /* Configure PHY lane swap */ - dsi_phy_hw_v3_0_lane_swap_config(phy, &cfg->lane_map); - - /* DSI PHY timings */ - DSI_W32(phy, DSIPHY_CMN_TIMING_CTRL_0, timing->lane_v3[0]); - DSI_W32(phy, DSIPHY_CMN_TIMING_CTRL_4, timing->lane_v3[4]); - DSI_W32(phy, DSIPHY_CMN_TIMING_CTRL_5, timing->lane_v3[5]); - DSI_W32(phy, DSIPHY_CMN_TIMING_CTRL_6, timing->lane_v3[6]); - DSI_W32(phy, DSIPHY_CMN_TIMING_CTRL_7, timing->lane_v3[7]); - DSI_W32(phy, DSIPHY_CMN_TIMING_CTRL_8, timing->lane_v3[8]); - DSI_W32(phy, DSIPHY_CMN_TIMING_CTRL_9, timing->lane_v3[9]); - DSI_W32(phy, DSIPHY_CMN_TIMING_CTRL_10, timing->lane_v3[10]); - DSI_W32(phy, DSIPHY_CMN_TIMING_CTRL_11, timing->lane_v3[11]); - - /* Remove power down from all blocks */ - DSI_W32(phy, DSIPHY_CMN_CTRL_0, 0x7f); - - DSI_W32(phy, DSIPHY_CMN_LANE_CTRL0, 0x07); - - switch (cfg->pll_source) { - case DSI_PLL_SOURCE_STANDALONE: - case DSI_PLL_SOURCE_NATIVE: - data = 0x0; /* internal PLL */ - break; - case DSI_PLL_SOURCE_NON_NATIVE: - data = 0x1; /* external PLL */ - break; - default: - break; + /* wait for REFGEN READY */ + rc = readl_poll_timeout_atomic(phy->base + DSIPHY_CMN_PHY_STATUS, + status, (status & BIT(0)), delay_us, timeout_us); + if (rc) { + pr_err("Ref gen not ready. Aborting\n"); + return; } - DSI_W32(phy, DSIPHY_CMN_CLK_CFG1, (data << 2)); /* set PLL src */ - /* DSI lane settings */ - dsi_phy_hw_v3_0_cphy_lane_settings(phy, cfg); - - pr_debug("[DSI_%d]C-Phy enabled ", phy->index); -} - - -/** - * dphy_enable() - Enable DPHY hardware - * @phy: Pointer to DSI PHY hardware object. - * @cfg: Per lane configurations for timing, strength and lane - * configurations. - */ -static void dsi_phy_hw_dphy_enable(struct dsi_phy_hw *phy, - struct dsi_phy_cfg *cfg) -{ - struct dsi_phy_per_lane_cfgs *timing = &cfg->timing; - u32 data; /* de-assert digital and pll power down */ data = BIT(6) | BIT(5); DSI_W32(phy, DSIPHY_CMN_CTRL_0, data); @@ -404,40 +321,9 @@ static void dsi_phy_hw_dphy_enable(struct dsi_phy_hw *phy, DSI_W32(phy, DSIPHY_CMN_CLK_CFG1, (data << 2)); /* set PLL src */ /* DSI lane settings */ - dsi_phy_hw_v3_0_dphy_lane_settings(phy, cfg); - - pr_debug("[DSI_%d]D-Phy enabled", phy->index); -} - -/** - * enable() - Enable PHY hardware - * @phy: Pointer to DSI PHY hardware object. - * @cfg: Per lane configurations for timing, strength and lane - * configurations. - */ -void dsi_phy_hw_v3_0_enable(struct dsi_phy_hw *phy, - struct dsi_phy_cfg *cfg) -{ - int rc = 0; - u32 status; - u32 const delay_us = 5; - u32 const timeout_us = 1000; - - if (dsi_phy_hw_v3_0_is_pll_on(phy)) - pr_warn("PLL turned on before configuring PHY\n"); - - /* wait for REFGEN READY */ - rc = readl_poll_timeout_atomic(phy->base + DSIPHY_CMN_PHY_STATUS, - status, (status & BIT(0)), delay_us, timeout_us); - if (rc) { - pr_err("Ref gen not ready. Aborting\n"); - return; - } - if (cfg->phy_type == DSI_PHY_TYPE_CPHY) - dsi_phy_hw_cphy_enable(phy, cfg); - else /* Default PHY type is DPHY */ - dsi_phy_hw_dphy_enable(phy, cfg); + dsi_phy_hw_v3_0_lane_settings(phy, cfg); + pr_debug("[DSI_%d]Phy enabled ", phy->index); } /** From 3828c3d071a448036455cf10e1b04a160c11b099 Mon Sep 17 00:00:00 2001 From: UtsavBalar1231 Date: Thu, 6 Aug 2020 12:46:58 +0530 Subject: [PATCH 452/592] Revert "drm/msm/dsi-staging: update PHY configuration to support cphy" This reverts commit 328e4eeb6f34f9a6fecf8a552bd3782f7c868765. Signed-off-by: UtsavBalar1231 --- .../bindings/drm/msm/mdss-dsi-panel.txt | 1 - drivers/gpu/drm/msm/dsi-staging/dsi_clk.h | 8 +- .../gpu/drm/msm/dsi-staging/dsi_clk_manager.c | 17 +-- drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c | 39 ++--- .../gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c | 5 +- .../gpu/drm/msm/dsi-staging/dsi_ctrl_reg.h | 3 +- drivers/gpu/drm/msm/dsi-staging/dsi_defs.h | 4 +- drivers/gpu/drm/msm/dsi-staging/dsi_display.c | 79 ++-------- drivers/gpu/drm/msm/dsi-staging/dsi_display.h | 1 - drivers/gpu/drm/msm/dsi-staging/dsi_panel.c | 6 - drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw.h | 2 - .../gpu/drm/msm/dsi-staging/dsi_phy_hw_v4_0.c | 137 +++--------------- 12 files changed, 51 insertions(+), 251 deletions(-) diff --git a/Documentation/devicetree/bindings/drm/msm/mdss-dsi-panel.txt b/Documentation/devicetree/bindings/drm/msm/mdss-dsi-panel.txt index cf9ed5124bca..5ff0fd686417 100644 --- a/Documentation/devicetree/bindings/drm/msm/mdss-dsi-panel.txt +++ b/Documentation/devicetree/bindings/drm/msm/mdss-dsi-panel.txt @@ -498,7 +498,6 @@ Optional properties: - qcom,panel-ack-disabled: A boolean property to indicate, whether we need to wait for any ACK from the panel for any commands that we send. - qcom,mdss-dsi-force-clock-lane-hs: Boolean to force dsi clock lanes to HS mode always. -- qcom,panel-cphy-mode: Boolean to specify whether panel is using cphy. - qcom,compression-mode: Select compression mode for panel. "fbc" - frame buffer compression diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_clk.h b/drivers/gpu/drm/msm/dsi-staging/dsi_clk.h index e77f337a282b..73e58047d0b5 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_clk.h +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_clk.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -117,13 +117,11 @@ struct dsi_link_lp_clk_info { /** * struct link_clk_freq - Clock frequency information for Link clocks * @byte_clk_rate: Frequency of DSI byte_clk in KHz. - * @byte_intf_clk_rate: Frequency of DSI byte_intf_clk in KHz. * @pixel_clk_rate: Frequency of DSI pixel_clk in KHz. * @esc_clk_rate: Frequency of DSI escape clock in KHz. */ struct link_clk_freq { u32 byte_clk_rate; - u32 byte_intf_clk_rate; u32 pix_clk_rate; u32 esc_clk_rate; }; @@ -308,12 +306,10 @@ int dsi_clk_set_pixel_clk_rate(void *client, u64 pixel_clk, u32 index); * dsi_clk_set_byte_clk_rate() - set frequency for byte clock * @client: DSI clock client pointer. * @byte_clk: Pixel clock rate in Hz. - * @byte_intf_clk: Byte interface clock rate in Hz. * @index: Index of the DSI controller. * return: error code in case of failure or 0 for success. */ -int dsi_clk_set_byte_clk_rate(void *client, u64 byte_clk, - u64 byte_intf_clk, u32 index); +int dsi_clk_set_byte_clk_rate(void *client, u64 byte_clk, u32 index); /** * dsi_clk_update_parent() - update parent clocks for specified clock diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_clk_manager.c b/drivers/gpu/drm/msm/dsi-staging/dsi_clk_manager.c index 63f003fd1c8e..0094d4c5d90f 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_clk_manager.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_clk_manager.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -139,16 +139,15 @@ int dsi_clk_set_pixel_clk_rate(void *client, u64 pixel_clk, u32 index) * dsi_clk_set_byte_clk_rate() - set frequency for byte clock * @client: DSI clock client pointer. * @byte_clk: Byte clock rate in Hz. - * @byte_intf_clk: Byte interface clock rate in Hz. * @index: Index of the DSI controller. * return: error code in case of failure or 0 for success. */ -int dsi_clk_set_byte_clk_rate(void *client, u64 byte_clk, - u64 byte_intf_clk, u32 index) +int dsi_clk_set_byte_clk_rate(void *client, u64 byte_clk, u32 index) { int rc = 0; struct dsi_clk_client_info *c = client; struct dsi_clk_mngr *mngr; + u64 byte_intf_rate; mngr = c->mngr; rc = clk_set_rate(mngr->link_clks[index].hs_clks.byte_clk, byte_clk); @@ -158,14 +157,12 @@ int dsi_clk_set_byte_clk_rate(void *client, u64 byte_clk, mngr->link_clks[index].freq.byte_clk_rate = byte_clk; if (mngr->link_clks[index].hs_clks.byte_intf_clk) { + byte_intf_rate = mngr->link_clks[index].freq.byte_clk_rate / 2; rc = clk_set_rate(mngr->link_clks[index].hs_clks.byte_intf_clk, - byte_intf_clk); + byte_intf_rate); if (rc) pr_err("failed to set clk rate for byte intf clk=%d\n", rc); - else - mngr->link_clks[index].freq.byte_intf_clk_rate - = byte_intf_clk; } return rc; @@ -374,10 +371,12 @@ static int dsi_link_hs_clk_set_rate(struct dsi_link_hs_clk_info *link_hs_clks, /* * If byte_intf_clk is present, set rate for that too. + * For DPHY: byte_intf_clk_rate = byte_clk_rate / 2 + * todo: this needs to be revisited when support for CPHY is added */ if (link_hs_clks->byte_intf_clk) { rc = clk_set_rate(link_hs_clks->byte_intf_clk, - l_clks->freq.byte_intf_clk_rate); + (l_clks->freq.byte_clk_rate / 2)); if (rc) { pr_err("set_rate failed for byte_intf_clk rc = %d\n", rc); diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c index f13020b8e9df..dfe2d5c2890f 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -847,11 +847,10 @@ static int dsi_ctrl_update_link_freqs(struct dsi_ctrl *dsi_ctrl, u32 bpp; u64 refresh_rate = TICKS_IN_MICRO_SECOND; u64 h_period, v_period, bit_rate, pclk_rate, bit_rate_per_lane, - byte_clk_rate, byte_intf_clk_rate; + byte_clk_rate; struct dsi_host_common_cfg *host_cfg = &config->common_config; struct dsi_split_link_config *split_link = &host_cfg->split_link; struct dsi_mode_info *timing = &config->video_timing; - u32 bits_per_symbol = 16, num_of_symbols = 7; /* For Cphy */ /* Get bits per pxl in desitnation format */ bpp = dsi_ctrl_pixel_format_to_bpp(host_cfg->dst_format); @@ -883,43 +882,23 @@ static int dsi_ctrl_update_link_freqs(struct dsi_ctrl *dsi_ctrl, bit_rate = h_period * v_period * refresh_rate * bpp; } else { bit_rate = config->bit_clk_rate_hz_override * num_of_lanes; - if (host_cfg->phy_type == DSI_PHY_TYPE_CPHY) { - bit_rate *= bits_per_symbol; - do_div(bit_rate, num_of_symbols); - } } + bit_rate_per_lane = bit_rate; + do_div(bit_rate_per_lane, num_of_lanes); pclk_rate = bit_rate; do_div(pclk_rate, bpp); - if (host_cfg->phy_type == DSI_PHY_TYPE_DPHY) { - bit_rate_per_lane = bit_rate; - do_div(bit_rate_per_lane, num_of_lanes); - byte_clk_rate = bit_rate_per_lane; - do_div(byte_clk_rate, 8); - byte_intf_clk_rate = byte_clk_rate; - do_div(byte_intf_clk_rate, 2); - config->bit_clk_rate_hz = byte_clk_rate * 8; - } else { - do_div(bit_rate, bits_per_symbol); - bit_rate *= num_of_symbols; - bit_rate_per_lane = bit_rate; - do_div(bit_rate_per_lane, num_of_lanes); - byte_clk_rate = bit_rate_per_lane; - do_div(byte_clk_rate, 7); - /* For CPHY, byte_intf_clk is same as byte_clk */ - byte_intf_clk_rate = byte_clk_rate; - config->bit_clk_rate_hz = byte_clk_rate * 7; - } + byte_clk_rate = bit_rate_per_lane; + do_div(byte_clk_rate, 8); pr_debug("bit_clk_rate = %llu, bit_clk_rate_per_lane = %llu\n", bit_rate, bit_rate_per_lane); - pr_debug("byte_clk_rate = %llu, byte_intf_clk_rate = %llu\n", - byte_clk_rate, byte_intf_clk_rate); - pr_debug("pclk_rate = %llu\n", pclk_rate); + pr_debug("byte_clk_rate = %llu, pclk_rate = %llu\n", + byte_clk_rate, pclk_rate); dsi_ctrl->clk_freq.byte_clk_rate = byte_clk_rate; - dsi_ctrl->clk_freq.byte_intf_clk_rate = byte_intf_clk_rate; dsi_ctrl->clk_freq.pix_clk_rate = pclk_rate; dsi_ctrl->clk_freq.esc_clk_rate = config->esc_clk_rate_hz; + config->bit_clk_rate_hz = dsi_ctrl->clk_freq.byte_clk_rate * 8; rc = dsi_clk_set_link_frequencies(clk_handle, dsi_ctrl->clk_freq, dsi_ctrl->cell_index); diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c index a7b79708a848..909a6840dcc7 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -127,9 +127,6 @@ void dsi_ctrl_hw_cmn_host_setup(struct dsi_ctrl_hw *ctrl, DSI_W32(ctrl, DSI_CTRL, reg_value); - if (cfg->phy_type == DSI_PHY_TYPE_CPHY) - DSI_W32(ctrl, DSI_CPHY_MODE_CTRL, BIT(0)); - if (ctrl->phy_isolation_enabled) DSI_W32(ctrl, DSI_DEBUG_CTRL, BIT(28)); pr_debug("[DSI_%d]Host configuration complete\n", ctrl->index); diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_reg.h b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_reg.h index 9f3c8c893794..72ac12dfd4b6 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_reg.h +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_reg.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -153,7 +153,6 @@ #define DSI_SECURE_DISPLAY_STATUS (0x02CC) #define DSI_SECURE_DISPLAY_BLOCK_COMMAND_COLOR (0x02D0) #define DSI_SECURE_DISPLAY_BLOCK_VIDEO_COLOR (0x02D4) -#define DSI_CPHY_MODE_CTRL (0x02D8) #define DSI_LOGICAL_LANE_SWAP_CTRL (0x0310) #define DSI_SPLIT_LINK (0x0330) diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h b/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h index b5ca835444b7..2cc47519e2a8 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -507,7 +507,6 @@ struct dsi_split_link_config { * @ext_bridge_map: External bridge config reg needs to match with the port * reg config. * @force_hs_clk_lane: Send continuous clock to the panel. - * @phy_type: DPHY/CPHY is enabled for this panel. * @dsi_split_link_config: Split Link Configuration. */ struct dsi_host_common_cfg { @@ -530,7 +529,6 @@ struct dsi_host_common_cfg { u32 ext_bridge_num; u32 ext_bridge_map[MAX_DSI_CTRLS_PER_DISPLAY]; bool force_hs_clk_lane; - enum dsi_phy_type phy_type; struct dsi_split_link_config split_link; }; diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c index 289cef8ab476..9f73a669539a 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -2512,20 +2512,6 @@ static int dsi_display_set_clk_src(struct dsi_display *display, bool on) struct dsi_display_ctrl *m_ctrl, *ctrl; struct dsi_clk_link_set *src; - /* - * For CPHY mode, the parent of mux_clks need to be set - * to Cphy_clks to have correct dividers for byte and - * pixel clocks. - */ - if (display->panel->host_config.phy_type == DSI_PHY_TYPE_CPHY) { - rc = dsi_clk_update_parent(&display->clock_info.cphy_clks, - &display->clock_info.mux_clks); - if (rc) { - pr_err("failed update mux parent to CPHY\n"); - return rc; - } - } - /* if XO clk is defined, select XO clk src when DSI is disabled */ if (on) src = &display->clock_info.mux_clks; @@ -3239,12 +3225,10 @@ static int dsi_display_clocks_init(struct dsi_display *display) const char *clk_name; const char *src_byte = "src_byte", *src_pixel = "src_pixel"; const char *mux_byte = "mux_byte", *mux_pixel = "mux_pixel"; - const char *cphy_byte = "cphy_byte", *cphy_pixel = "cphy_pixel"; const char *shadow_byte = "shadow_byte", *shadow_pixel = "shadow_pixel"; struct clk *dsi_clk; struct dsi_clk_link_set *src = &display->clock_info.src_clks; struct dsi_clk_link_set *mux = &display->clock_info.mux_clks; - struct dsi_clk_link_set *cphy = &display->clock_info.cphy_clks; struct dsi_clk_link_set *shadow = &display->clock_info.shadow_clks; struct dsi_clk_link_set *xo = &display->clock_info.xo_clks; struct dsi_dyn_clk_caps *dyn_clk_caps = &(display->panel->dyn_clk_caps); @@ -3277,15 +3261,6 @@ static int dsi_display_clocks_init(struct dsi_display *display) goto error; } - if (dsi_display_check_prefix(cphy_byte, clk_name)) { - cphy->byte_clk = NULL; - goto error; - } - if (dsi_display_check_prefix(cphy_pixel, clk_name)) { - cphy->pixel_clk = NULL; - goto error; - } - if (dyn_clk_caps->dyn_clk_support && (display->panel->panel_mode == DSI_OP_VIDEO_MODE)) { @@ -3317,16 +3292,6 @@ static int dsi_display_clocks_init(struct dsi_display *display) continue; } - if (dsi_display_check_prefix(cphy_byte, clk_name)) { - cphy->byte_clk = dsi_clk; - continue; - } - - if (dsi_display_check_prefix(cphy_pixel, clk_name)) { - cphy->pixel_clk = dsi_clk; - continue; - } - if (dsi_display_check_prefix(mux_byte, clk_name)) { mux->byte_clk = dsi_clk; continue; @@ -3932,8 +3897,6 @@ static int dsi_display_res_init(struct dsi_display *display) phy->cfg.force_clk_lane_hs = display->panel->host_config.force_hs_clk_lane; - phy->cfg.phy_type = - display->panel->host_config.phy_type; } rc = dsi_display_parse_lane_map(display); @@ -4129,9 +4092,7 @@ static int dsi_display_update_dsi_bitrate(struct dsi_display *display, struct dsi_display_ctrl *dsi_disp_ctrl = &display->ctrl[i]; struct dsi_ctrl *ctrl = dsi_disp_ctrl->ctrl; u32 num_of_lanes = 0, bpp; - u64 bit_rate, pclk_rate, bit_rate_per_lane, byte_clk_rate, - byte_intf_clk_rate; - u32 bits_per_symbol = 16, num_of_symbols = 7; /* For Cphy */ + u64 bit_rate, pclk_rate, bit_rate_per_lane, byte_clk_rate; struct dsi_host_common_cfg *host_cfg; mutex_lock(&ctrl->ctrl_lock); @@ -4155,35 +4116,18 @@ static int dsi_display_update_dsi_bitrate(struct dsi_display *display, bpp = dsi_pixel_format_to_bpp(host_cfg->dst_format); bit_rate = display->config.bit_clk_rate_hz * num_of_lanes; - + bit_rate_per_lane = bit_rate; + do_div(bit_rate_per_lane, num_of_lanes); pclk_rate = bit_rate; do_div(pclk_rate, bpp); - if (host_cfg->phy_type == DSI_PHY_TYPE_DPHY) { - bit_rate_per_lane = bit_rate; - do_div(bit_rate_per_lane, num_of_lanes); - byte_clk_rate = bit_rate_per_lane; - do_div(byte_clk_rate, 8); - byte_intf_clk_rate = byte_clk_rate; - do_div(byte_intf_clk_rate, 2); - } else { - do_div(bit_rate, bits_per_symbol); - bit_rate *= num_of_symbols; - bit_rate_per_lane = bit_rate; - do_div(bit_rate_per_lane, num_of_lanes); - byte_clk_rate = bit_rate_per_lane; - do_div(byte_clk_rate, 7); - /* For CPHY, byte_intf_clk is same as byte_clk */ - byte_intf_clk_rate = byte_clk_rate; - } - + byte_clk_rate = bit_rate_per_lane; + do_div(byte_clk_rate, 8); pr_debug("bit_clk_rate = %llu, bit_clk_rate_per_lane = %llu\n", bit_rate, bit_rate_per_lane); - pr_debug("byte_clk_rate = %llu, byte_intf_clk_rate = %llu\n", - byte_clk_rate, byte_intf_clk_rate); - pr_debug("pclk_rate = %llu\n", pclk_rate); + pr_debug("byte_clk_rate = %llu, pclk_rate = %llu\n", + byte_clk_rate, pclk_rate); ctrl->clk_freq.byte_clk_rate = byte_clk_rate; - ctrl->clk_freq.byte_intf_clk_rate = byte_intf_clk_rate; ctrl->clk_freq.pix_clk_rate = pclk_rate; rc = dsi_clk_set_link_frequencies(display->dsi_clk_handle, ctrl->clk_freq, ctrl->cell_index); @@ -4277,8 +4221,7 @@ static int _dsi_display_dyn_update_clks(struct dsi_display *display, if (!ctrl->ctrl) continue; rc = dsi_clk_set_byte_clk_rate(display->dsi_clk_handle, - ctrl->ctrl->clk_freq.byte_clk_rate, - ctrl->ctrl->clk_freq.byte_intf_clk_rate, i); + ctrl->ctrl->clk_freq.byte_clk_rate, i); if (rc) { pr_err("failed to set byte rate for index:%d\n", i); goto recover_byte_clk; @@ -4341,8 +4284,7 @@ recover_byte_clk: if (!ctrl->ctrl) continue; dsi_clk_set_byte_clk_rate(display->dsi_clk_handle, - bkp_freq->byte_clk_rate, - bkp_freq->byte_intf_clk_rate, i); + bkp_freq->byte_clk_rate, i); } exit: @@ -4378,7 +4320,6 @@ static int dsi_display_dynamic_clk_switch_vid(struct dsi_display *display, /* back up existing rates to handle failure case */ bkp_freq.byte_clk_rate = m_ctrl->ctrl->clk_freq.byte_clk_rate; - bkp_freq.byte_intf_clk_rate = m_ctrl->ctrl->clk_freq.byte_intf_clk_rate; bkp_freq.pix_clk_rate = m_ctrl->ctrl->clk_freq.pix_clk_rate; bkp_freq.esc_clk_rate = m_ctrl->ctrl->clk_freq.esc_clk_rate; diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.h b/drivers/gpu/drm/msm/dsi-staging/dsi_display.h index 970c7f35a060..04be58725e22 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.h +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.h @@ -120,7 +120,6 @@ struct dsi_display_boot_param { struct dsi_display_clk_info { struct dsi_clk_link_set src_clks; struct dsi_clk_link_set mux_clks; - struct dsi_clk_link_set cphy_clks; struct dsi_clk_link_set shadow_clks; struct dsi_clk_link_set xo_clks; }; diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c index 387c5b37dc59..371c78cd6dc1 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c @@ -1361,7 +1361,6 @@ static int dsi_panel_parse_misc_host_config(struct dsi_host_common_cfg *host, { u32 val = 0; int rc = 0; - bool panel_cphy_mode = false; rc = utils->read_u32(utils->data, "qcom,mdss-dsi-t-clk-post", &val); if (!rc) { @@ -1384,11 +1383,6 @@ static int dsi_panel_parse_misc_host_config(struct dsi_host_common_cfg *host, host->force_hs_clk_lane = utils->read_bool(utils->data, "qcom,mdss-dsi-force-clock-lane-hs"); - panel_cphy_mode = utils->read_bool(utils->data, - "qcom,panel-cphy-mode"); - host->phy_type = panel_cphy_mode ? DSI_PHY_TYPE_CPHY - : DSI_PHY_TYPE_DPHY; - return 0; } diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw.h b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw.h index 7cd824c7e08e..6b5b1dc643cb 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw.h +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw.h @@ -96,7 +96,6 @@ struct dsi_phy_per_lane_cfgs { * @lane_map: DSI logical to PHY lane mapping. * @lane_pnswap: P/N swap status on each lane. * @force_clk_lane_hs:Boolean whether to force clock lane in HS mode. - * @phy_type: Phy-type (Dphy/Cphy). * @bit_clk_rate_hz: DSI bit clk rate in HZ. */ struct dsi_phy_cfg { @@ -109,7 +108,6 @@ struct dsi_phy_cfg { struct dsi_lane_map lane_map; u8 lane_pnswap; bool force_clk_lane_hs; - enum dsi_phy_type phy_type; unsigned long bit_clk_rate_hz; }; diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v4_0.c b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v4_0.c index f76d5459bb1d..b0db818ce39d 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v4_0.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v4_0.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -144,98 +144,21 @@ static void dsi_phy_hw_v4_0_lane_settings(struct dsi_phy_hw *phy, (cfg->lane_pnswap >> i) & 0x1); } - if (cfg->phy_type == DSI_PHY_TYPE_CPHY) - DSI_W32(phy, DSIPHY_LNX_TX_DCTRL(3), 0x02); - } /** - * cphy_enable() - Enable CPHY hardware + * enable() - Enable PHY hardware * @phy: Pointer to DSI PHY hardware object. * @cfg: Per lane configurations for timing, strength and lane * configurations. */ -static void dsi_phy_hw_cphy_enable(struct dsi_phy_hw *phy, - struct dsi_phy_cfg *cfg) -{ - struct dsi_phy_per_lane_cfgs *timing = &cfg->timing; - u32 data; - /* For C-PHY, no low power settings for lower clk rate */ - u32 vreg_ctrl_0 = 0x5A; - u32 glbl_str_swi_cal_sel_ctrl = 0x03; - u32 glbl_hstx_str_ctrl_0 = 0x66; - - /* de-assert digital and pll power down */ - data = BIT(6) | BIT(5); - DSI_W32(phy, DSIPHY_CMN_CTRL_0, data); - - /* Assert PLL core reset */ - DSI_W32(phy, DSIPHY_CMN_PLL_CNTRL, 0x00); - - /* turn off resync FIFO */ - DSI_W32(phy, DSIPHY_CMN_RBUF_CTRL, 0x00); - - /* Configure PHY lane swap */ - dsi_phy_hw_v4_0_lane_swap_config(phy, &cfg->lane_map); - - DSI_W32(phy, DSIPHY_CMN_GLBL_CTRL, BIT(6)); - - /* Enable LDO */ - DSI_W32(phy, DSIPHY_CMN_VREG_CTRL_0, vreg_ctrl_0); - DSI_W32(phy, DSIPHY_CMN_VREG_CTRL_1, 0x5c); - - DSI_W32(phy, DSIPHY_CMN_GLBL_STR_SWI_CAL_SEL_CTRL, - glbl_str_swi_cal_sel_ctrl); - DSI_W32(phy, DSIPHY_CMN_GLBL_HSTX_STR_CTRL_0, glbl_hstx_str_ctrl_0); - DSI_W32(phy, DSIPHY_CMN_GLBL_PEMPH_CTRL_0, 0x00); - DSI_W32(phy, DSIPHY_CMN_GLBL_RESCODE_OFFSET_TOP_CTRL, 0x03); - DSI_W32(phy, DSIPHY_CMN_GLBL_RESCODE_OFFSET_BOT_CTRL, 0x3c); - DSI_W32(phy, DSIPHY_CMN_GLBL_LPTX_STR_CTRL, 0x55); - - /* Remove power down from all blocks */ - DSI_W32(phy, DSIPHY_CMN_CTRL_0, 0x7f); - - DSI_W32(phy, DSIPHY_CMN_LANE_CTRL0, 0x17); - - switch (cfg->pll_source) { - case DSI_PLL_SOURCE_STANDALONE: - case DSI_PLL_SOURCE_NATIVE: - data = 0x0; /* internal PLL */ - break; - case DSI_PLL_SOURCE_NON_NATIVE: - data = 0x1; /* external PLL */ - break; - default: - break; - } - DSI_W32(phy, DSIPHY_CMN_CLK_CFG1, (data << 2)); /* set PLL src */ - - /* DSI PHY timings */ - DSI_W32(phy, DSIPHY_CMN_TIMING_CTRL_0, timing->lane_v4[0]); - DSI_W32(phy, DSIPHY_CMN_TIMING_CTRL_4, timing->lane_v4[4]); - DSI_W32(phy, DSIPHY_CMN_TIMING_CTRL_5, timing->lane_v4[5]); - DSI_W32(phy, DSIPHY_CMN_TIMING_CTRL_6, timing->lane_v4[6]); - DSI_W32(phy, DSIPHY_CMN_TIMING_CTRL_7, timing->lane_v4[7]); - DSI_W32(phy, DSIPHY_CMN_TIMING_CTRL_8, timing->lane_v4[8]); - DSI_W32(phy, DSIPHY_CMN_TIMING_CTRL_9, timing->lane_v4[9]); - DSI_W32(phy, DSIPHY_CMN_TIMING_CTRL_10, timing->lane_v4[10]); - DSI_W32(phy, DSIPHY_CMN_TIMING_CTRL_11, timing->lane_v4[11]); - - /* DSI lane settings */ - dsi_phy_hw_v4_0_lane_settings(phy, cfg); - - pr_debug("[DSI_%d] C-Phy enabled ", phy->index); -} - -/** - * dphy_enable() - Enable DPHY hardware - * @phy: Pointer to DSI PHY hardware object. - * @cfg: Per lane configurations for timing, strength and lane - * configurations. - */ -static void dsi_phy_hw_dphy_enable(struct dsi_phy_hw *phy, +void dsi_phy_hw_v4_0_enable(struct dsi_phy_hw *phy, struct dsi_phy_cfg *cfg) { + int rc = 0; + u32 status; + u32 const delay_us = 5; + u32 const timeout_us = 1000; struct dsi_phy_per_lane_cfgs *timing = &cfg->timing; u32 data; bool less_than_1500_mhz = false; @@ -243,6 +166,17 @@ static void dsi_phy_hw_dphy_enable(struct dsi_phy_hw *phy, u32 glbl_str_swi_cal_sel_ctrl = 0; u32 glbl_hstx_str_ctrl_0 = 0; + if (dsi_phy_hw_v4_0_is_pll_on(phy)) + pr_warn("PLL turned on before configuring PHY\n"); + + /* wait for REFGEN READY */ + rc = readl_poll_timeout_atomic(phy->base + DSIPHY_CMN_PHY_STATUS, + status, (status & BIT(0)), delay_us, timeout_us); + if (rc) { + pr_err("Ref gen not ready. Aborting\n"); + return; + } + /* Alter PHY configurations if data rate less than 1.5GHZ*/ if (cfg->bit_clk_rate_hz < 1500000000) less_than_1500_mhz = true; @@ -266,7 +200,6 @@ static void dsi_phy_hw_dphy_enable(struct dsi_phy_hw *phy, /* Enable LDO */ DSI_W32(phy, DSIPHY_CMN_VREG_CTRL_0, vreg_ctrl_0); DSI_W32(phy, DSIPHY_CMN_VREG_CTRL_1, 0x5c); - DSI_W32(phy, DSIPHY_CMN_CTRL_3, 0x00); DSI_W32(phy, DSIPHY_CMN_GLBL_STR_SWI_CAL_SEL_CTRL, glbl_str_swi_cal_sel_ctrl); @@ -316,39 +249,7 @@ static void dsi_phy_hw_dphy_enable(struct dsi_phy_hw *phy, /* DSI lane settings */ dsi_phy_hw_v4_0_lane_settings(phy, cfg); - pr_debug("[DSI_%d] D-Phy enabled ", phy->index); -} - -/** - * enable() - Enable PHY hardware - * @phy: Pointer to DSI PHY hardware object. - * @cfg: Per lane configurations for timing, strength and lane - * configurations. - */ -void dsi_phy_hw_v4_0_enable(struct dsi_phy_hw *phy, - struct dsi_phy_cfg *cfg) -{ - int rc = 0; - u32 status; - u32 const delay_us = 5; - u32 const timeout_us = 1000; - - if (dsi_phy_hw_v4_0_is_pll_on(phy)) - pr_warn("PLL turned on before configuring PHY\n"); - - /* wait for REFGEN READY */ - rc = readl_poll_timeout_atomic(phy->base + DSIPHY_CMN_PHY_STATUS, - status, (status & BIT(0)), delay_us, timeout_us); - if (rc) { - pr_err("Ref gen not ready. Aborting\n"); - return; - } - - if (cfg->phy_type == DSI_PHY_TYPE_CPHY) - dsi_phy_hw_cphy_enable(phy, cfg); - else /* Default PHY type is DPHY */ - dsi_phy_hw_dphy_enable(phy, cfg); - + pr_debug("[DSI_%d]Phy enabled ", phy->index); } /** From 12417143e2768e473b14c9a046b135d2c737ab8f Mon Sep 17 00:00:00 2001 From: UtsavBalar1231 Date: Thu, 6 Aug 2020 13:46:40 +0530 Subject: [PATCH 453/592] Revert "drm/msm/sde: fix topology lookup table when ctl version is used" This reverts commit d91b1d17fef71edec7ea9405c91a6b7c0c305543. Signed-off-by: UtsavBalar1231 --- drivers/gpu/drm/msm/sde/sde_connector.c | 4 ++-- drivers/gpu/drm/msm/sde/sde_encoder.c | 3 +-- drivers/gpu/drm/msm/sde/sde_rm.c | 13 ++++++------- drivers/gpu/drm/msm/sde/sde_rm.h | 5 ++--- 4 files changed, 11 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_connector.c b/drivers/gpu/drm/msm/sde/sde_connector.c index 4d9a27891886..8f9254e526dd 100644 --- a/drivers/gpu/drm/msm/sde/sde_connector.c +++ b/drivers/gpu/drm/msm/sde/sde_connector.c @@ -2224,8 +2224,8 @@ static int sde_connector_populate_mode_info(struct drm_connector *conn, sde_kms_info_add_keyint(info, "bit_clk_rate", mode_info.clk_rate); - topology_idx = (int)sde_rm_get_topology_name(&sde_kms->rm, - mode_info.topology); + topology_idx = (int)sde_rm_get_topology_name( + mode_info.topology); if (topology_idx < SDE_RM_TOPOLOGY_MAX) { sde_kms_info_add_keystr(info, "topology", e_topology_name[topology_idx].name); diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c index d4cd7deaa620..5f193c496494 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder.c @@ -1143,8 +1143,7 @@ static int sde_encoder_virt_atomic_check( if (crtc_state->active) topology = &sde_conn_state->mode_info.topology; - ret = sde_rm_update_topology(&sde_kms->rm, conn_state, - topology); + ret = sde_rm_update_topology(conn_state, topology); if (ret) { SDE_ERROR_ENC(sde_enc, "RM failed to update topology, rc: %d\n", ret); diff --git a/drivers/gpu/drm/msm/sde/sde_rm.c b/drivers/gpu/drm/msm/sde/sde_rm.c index ccfe8239efaa..66fd28093ffc 100644 --- a/drivers/gpu/drm/msm/sde/sde_rm.c +++ b/drivers/gpu/drm/msm/sde/sde_rm.c @@ -190,14 +190,14 @@ void sde_rm_init_hw_iter( iter->type = type; } -enum sde_rm_topology_name sde_rm_get_topology_name(struct sde_rm *rm, +enum sde_rm_topology_name sde_rm_get_topology_name( struct msm_display_topology topology) { int i; for (i = 0; i < SDE_RM_TOPOLOGY_MAX; i++) - if (RM_IS_TOPOLOGY_MATCH(rm->topology_tbl[i], topology)) - return rm->topology_tbl[i].top_name; + if (RM_IS_TOPOLOGY_MATCH(g_top_table[i], topology)) + return g_top_table[i].top_name; return SDE_RM_TOPOLOGY_NONE; } @@ -1645,8 +1645,7 @@ static struct drm_connector *_sde_rm_get_connector( return NULL; } -int sde_rm_update_topology(struct sde_rm *rm, - struct drm_connector_state *conn_state, +int sde_rm_update_topology(struct drm_connector_state *conn_state, struct msm_display_topology *topology) { int i, ret = 0; @@ -1659,8 +1658,8 @@ int sde_rm_update_topology(struct sde_rm *rm, if (topology) { top = *topology; for (i = 0; i < SDE_RM_TOPOLOGY_MAX; i++) - if (RM_IS_TOPOLOGY_MATCH(rm->topology_tbl[i], top)) { - top_name = rm->topology_tbl[i].top_name; + if (RM_IS_TOPOLOGY_MATCH(g_top_table[i], top)) { + top_name = g_top_table[i].top_name; break; } } diff --git a/drivers/gpu/drm/msm/sde/sde_rm.h b/drivers/gpu/drm/msm/sde/sde_rm.h index 486b73f1dfb4..ab6beaf928dc 100644 --- a/drivers/gpu/drm/msm/sde/sde_rm.h +++ b/drivers/gpu/drm/msm/sde/sde_rm.h @@ -162,7 +162,7 @@ struct sde_rm_hw_request { * @topology: msm_display_topology topology config * @Return: name of the given topology */ -enum sde_rm_topology_name sde_rm_get_topology_name(struct sde_rm *rm, +enum sde_rm_topology_name sde_rm_get_topology_name( struct msm_display_topology topology); @@ -279,8 +279,7 @@ int sde_rm_cont_splash_res_init(struct msm_drm_private *priv, * @topology: topology selected for the display * @return: 0 on success or error */ -int sde_rm_update_topology(struct sde_rm *rm, - struct drm_connector_state *conn_state, +int sde_rm_update_topology(struct drm_connector_state *conn_state, struct msm_display_topology *topology); /** From ec015a7209ca01884d10daf134b48ec2e7f28a5f Mon Sep 17 00:00:00 2001 From: UtsavBalar1231 Date: Tue, 4 Aug 2020 19:23:09 +0530 Subject: [PATCH 454/592] drm: msm: sde: workaround for miui like fod behaviour Signed-off-by: UtsavBalar1231 --- drivers/gpu/drm/msm/sde/sde_connector.c | 38 +++++++++++++------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_connector.c b/drivers/gpu/drm/msm/sde/sde_connector.c index 8f9254e526dd..89e1bf30b513 100644 --- a/drivers/gpu/drm/msm/sde/sde_connector.c +++ b/drivers/gpu/drm/msm/sde/sde_connector.c @@ -688,7 +688,7 @@ int sde_connector_update_hbm(struct sde_connector *c_conn) connector = &c_conn->base; if (c_conn->connector_type != DRM_MODE_CONNECTOR_DSI) - return 0; + return rc; c_state = to_sde_connector_state(connector->state); @@ -701,11 +701,11 @@ int sde_connector_update_hbm(struct sde_connector *c_conn) } if (!dsi_display->panel->fod_dimlayer_enabled) { - return 0; + return rc; } if (!c_conn->encoder || !c_conn->encoder->crtc || !c_conn->encoder->crtc->state) { - return 0; + return rc; } dim_layer_status = sde_crtc_get_dim_layer_status(c_conn->encoder->crtc->state); @@ -728,10 +728,11 @@ int sde_connector_update_hbm(struct sde_connector *c_conn) dsi_display_write_panel(dsi_display, &dsi_display->panel->cur_mode->priv_info->cmd_sets[DSI_CMD_SET_DOZE_LBM]); dsi_display->drm_dev->doze_brightness = DOZE_BRIGHTNESS_LBM; } - sde_encoder_wait_for_event(c_conn->encoder, MSM_ENC_VBLANK); dsi_display->panel->in_aod = true; dsi_display->panel->skip_dimmingon = STATE_DIM_BLOCK; } else { + dsi_display->panel->fod_dimlayer_hbm_enabled = false; + dsi_display->panel->hbm_enabled = false; /* disable FOD HBM */ if (dsi_display->panel->elvss_dimming_check_enable) { rc = dsi_display_write_panel(dsi_display, &dsi_display->panel->hbm_fod_off); @@ -739,18 +740,19 @@ int sde_connector_update_hbm(struct sde_connector *c_conn) rc = dsi_display_write_panel(dsi_display, &dsi_display->panel->cur_mode->priv_info->cmd_sets[DSI_CMD_SET_DISP_HBM_FOD_OFF]); } - /* reset backlight level */ - dsi_panel_set_backlight(dsi_display->panel, dsi_display->panel->last_bl_lvl); - dsi_display->panel->skip_dimmingon = STATE_DIM_RESTORE; - dsi_display->panel->hbm_enabled = false; - dsi_display->panel->fod_dimlayer_hbm_enabled = false; pr_debug("HBM fod off\n"); sysfs_notify(&dsi_display->drm_conn->kdev->kobj, NULL, "dimlayer_hbm_enabled"); pr_debug("notify hbm off to displayfeature\n"); + + /* reset backlight level after HBM off*/ + dsi_panel_set_backlight(dsi_display->panel, dsi_display->panel->last_bl_lvl); + + /* notify brightness clone bl event */ + sysfs_notify(&c_conn->bl_device->dev.kobj, NULL, "brightness_clone"); + dsi_display->panel->dc_enable = true; pr_debug("fod restore DC\n"); - sysfs_notify(&c_conn->bl_device->dev.kobj, NULL, "brightness_clone"); } mutex_unlock(&dsi_display->panel->panel_lock); if (rc) { @@ -765,6 +767,10 @@ int sde_connector_update_hbm(struct sde_connector *c_conn) pr_debug("wait one frame for hbm on\n"); if (dsi_display->panel->last_bl_lvl || dsi_display->drm_dev->state == MSM_DRM_BLANK_LP1 || dsi_display->drm_dev->state == MSM_DRM_BLANK_LP2) { + dsi_display->panel->fod_dimlayer_hbm_enabled = true; + dsi_display->panel->skip_dimmingon = STATE_DIM_BLOCK; + dsi_display->panel->hbm_enabled = true; + pr_debug("HBM fod on\n"); /* enable FOD HBM */ if (dsi_display->panel->elvss_dimming_check_enable) { rc = dsi_display_write_panel(dsi_display, &dsi_display->panel->hbm_fod_on); @@ -772,15 +778,11 @@ int sde_connector_update_hbm(struct sde_connector *c_conn) rc = dsi_display_write_panel(dsi_display, &dsi_display->panel->cur_mode->priv_info->cmd_sets[DSI_CMD_SET_DISP_HBM_FOD_ON]); } - /* reset backlight level */ - dsi_panel_set_backlight(dsi_display->panel, dsi_display->panel->last_bl_lvl); - - dsi_display->panel->skip_dimmingon = STATE_DIM_BLOCK; - dsi_display->panel->hbm_enabled = true; - dsi_display->panel->fod_dimlayer_hbm_enabled = true; - pr_debug("HBM fod on\n"); sysfs_notify(&dsi_display->drm_conn->kdev->kobj, NULL, "dimlayer_hbm_enabled"); pr_debug("notify hbm on to displayfeature\n"); + + /* reset backlight level after HBM on*/ + dsi_panel_set_backlight(dsi_display->panel, dsi_display->panel->last_bl_lvl); } if (dsi_display->panel->dc_enable) { @@ -801,7 +803,7 @@ int sde_connector_update_hbm(struct sde_connector *c_conn) } } pr_debug("dim_layer_status:%d fod_dimlayer_hbm_enabled:%d\n", dim_layer_status, dsi_display->panel->fod_dimlayer_hbm_enabled); - return 0; + return rc; } int sde_connector_pre_kickoff(struct drm_connector *connector) From 4fe78d0b095e9cf64d78e511285b2252a48b7870 Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Tue, 5 May 2020 10:07:59 +0200 Subject: [PATCH 455/592] drm: msm: phy-v3: Add delay in ULPS exit on-command The ULPS exit sequence requires us to set ULPS ON on all lanes before setting ULPS OFF and this may take some microseconds to be applied on some PHY versions: add the required delay. Signed-off-by: UtsavBalar1231 --- drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v3_0.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v3_0.c b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v3_0.c index 556c01911a68..7dee8a5b6497 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v3_0.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v3_0.c @@ -476,6 +476,8 @@ void dsi_phy_hw_v3_0_ulps_exit(struct dsi_phy_hw *phy, * to be in stop state. */ DSI_W32(phy, DSIPHY_CMN_LANE_CTRL3, reg); + usleep_range(5, 15); + DSI_W32(phy, DSIPHY_CMN_LANE_CTRL3, 0); usleep_range(100, 110); } From 964b93d3f9d4ec34eb9957039d97c738de6f8500 Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Tue, 5 May 2020 09:52:52 +0200 Subject: [PATCH 456/592] drm: msm: phy-v3: Disable phy idle power collapse on poweron This PHY requires us to manually disable phy idle power collapse everytime we power it on, as it comes up with PC enabled by default. Signed-off-by: UtsavBalar1231 --- drivers/gpu/drm/msm/dsi-staging/dsi_display.c | 28 +++++++++++++++++++ drivers/gpu/drm/msm/dsi-staging/dsi_phy.c | 22 +++++++++++++++ drivers/gpu/drm/msm/dsi-staging/dsi_phy.h | 6 ++++ drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw.h | 6 ++++ .../gpu/drm/msm/dsi-staging/dsi_phy_hw_v3_0.c | 27 ++++++++++++++++++ 5 files changed, 89 insertions(+) diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c index 9f73a669539a..dcc9c95481de 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c @@ -2505,6 +2505,28 @@ error: return rc; } +static int dsi_display_phy_idle_pc(struct dsi_display *display, + bool idle_pc_enabled) +{ + struct dsi_display_ctrl *ctrl; + int i, rc = 0; + + display_for_each_ctrl(i, display) { + ctrl = &display->ctrl[i]; + if (!ctrl->phy) + continue; + + rc = dsi_phy_set_idle_pc(ctrl->phy, idle_pc_enabled); + if (rc) { + pr_err("[%s] Failed to set idle pc, rc=%d\n", + ctrl->ctrl->name, rc); + goto error; + } + } +error: + return rc; +} + static int dsi_display_set_clk_src(struct dsi_display *display, bool on) { int rc = 0; @@ -3634,6 +3656,12 @@ int dsi_pre_clkon_cb(void *priv, pr_debug("%s: Enable DSI core power\n", __func__); } + if ((clk_type & DSI_LINK_CLK) && (new_state == DSI_CLK_ON) && + !display->is_cont_splash_enabled) { + /* Enabling LINK clocks: disable PHY idle power collapse */ + dsi_display_phy_idle_pc(display, false); + } + return rc; } diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c b/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c index 2b65c7cd164e..58256a5efda5 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c @@ -755,6 +755,28 @@ error: return rc; } +int dsi_phy_set_idle_pc(struct msm_dsi_phy *dsi_phy, bool idle_pc_enabled) +{ + int rc = 0; + + if (!dsi_phy) { + pr_err("PHY is NULL!!!\n"); + return -EINVAL; + } + + /* If PHY does not require special IdlePC handling, go out early */ + if (!dsi_phy->hw.ops.set_idle_pc) + return 0; + + mutex_lock(&dsi_phy->phy_lock); + + dsi_phy->hw.ops.set_idle_pc(&dsi_phy->hw, idle_pc_enabled); + + mutex_unlock(&dsi_phy->phy_lock); + + return rc; +} + static int dsi_phy_enable_ulps(struct msm_dsi_phy *phy, struct dsi_host_config *config, bool clamp_enabled) { diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy.h b/drivers/gpu/drm/msm/dsi-staging/dsi_phy.h index 1d5d0be2742d..566d49d14862 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy.h +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy.h @@ -171,6 +171,12 @@ int dsi_phy_validate_mode(struct msm_dsi_phy *dsi_phy, */ int dsi_phy_set_power_state(struct msm_dsi_phy *dsi_phy, bool enable); +/** + * dsi_phy_set_idle_pc() - set/unset idle dsi phy idle power collapse + * + */ +int dsi_phy_set_idle_pc(struct msm_dsi_phy *dsi_phy, bool idle_pc_enabled); + /** * dsi_phy_enable() - enable DSI PHY hardware * @dsi_phy: DSI PHY handle. diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw.h b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw.h index 6b5b1dc643cb..abb2299a67a1 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw.h +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw.h @@ -261,6 +261,12 @@ struct dsi_phy_hw_ops { */ void (*phy_idle_off)(struct dsi_phy_hw *phy); + /** + * set_idle_pc() - Enter/exit PHY idle power collapse + */ + + void (*set_idle_pc)(struct dsi_phy_hw *phy, bool idle_pc_enabled); + /** * calculate_timing_params() - calculates timing parameters. * @phy: Pointer to DSI PHY hardware object. diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v3_0.c b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v3_0.c index 7dee8a5b6497..602f09d4e72b 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v3_0.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v3_0.c @@ -234,6 +234,33 @@ void dsi_phy_hw_v3_0_clamp_ctrl(struct dsi_phy_hw *phy, bool enable) wmb(); /* Ensure that the freezeio bit is toggled */ } +void dsi_phy_hw_v3_0_set_idle_pc(struct dsi_phy_hw *phy, bool idle_pc_enabled) +{ + u32 reg; + + pr_debug("PHY: %s idle power collapse\n", + idle_pc_enabled ? "Enabling" : "Disabling"); + + /* Does SDM845 support PHY idle power collapse, or just FreezeIO? */ + if (!of_machine_is_compatible("qcom,msm8998")) + return; + + if (idle_pc_enabled) { + pr_err("PHY: Enable idlepc not supported\n"); + return; + } + + reg = DSI_R32(phy, DSIPHY_CMN_CTRL_1); + DSI_W32(phy, DSIPHY_CMN_CTRL_1, reg | BIT(5)); + wmb(); + usleep_range(10, 15); + + reg = DSI_R32(phy, DSIPHY_CMN_CTRL_1); + reg &= ~(BIT(5)); + DSI_W32(phy, DSIPHY_CMN_CTRL_1, reg); + wmb(); +} + /** * enable() - Enable PHY hardware * @phy: Pointer to DSI PHY hardware object. From 312fe28b4190a17f1005e4764da592a262e24565 Mon Sep 17 00:00:00 2001 From: Lipsa Rout Date: Tue, 3 Dec 2019 19:02:41 +0530 Subject: [PATCH 457/592] BACKPORT: disp: msm: dsi: Update dsi byte interface clock calculation Update dsi byte interface clock as per hardware recommendation. For Phy ver 2.0 and below: byte intf clk equals to byte clk. For Phy ver 3.0 and above: byte intf clk equals to byte clk / 2. Change-Id: Ic3af2e4348403aeacb2e1c73c4dc133db63a51a4 Signed-off-by: Ritesh Kumar Signed-off-by: Lipsa Rout Signed-off-by: UtsavBalar1231 --- drivers/gpu/drm/msm/dsi-staging/dsi_clk.h | 6 +++- .../gpu/drm/msm/dsi-staging/dsi_clk_manager.c | 15 ++++---- drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c | 11 ++++-- drivers/gpu/drm/msm/dsi-staging/dsi_defs.h | 2 ++ drivers/gpu/drm/msm/dsi-staging/dsi_display.c | 36 ++++++++++++++++--- drivers/gpu/drm/msm/dsi-staging/dsi_phy.c | 5 +++ drivers/gpu/drm/msm/dsi-staging/dsi_phy.h | 8 +++++ 7 files changed, 69 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_clk.h b/drivers/gpu/drm/msm/dsi-staging/dsi_clk.h index 73e58047d0b5..b0ee9ac7047a 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_clk.h +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_clk.h @@ -117,11 +117,13 @@ struct dsi_link_lp_clk_info { /** * struct link_clk_freq - Clock frequency information for Link clocks * @byte_clk_rate: Frequency of DSI byte_clk in KHz. + * @byte_intf_clk_rate: Frequency of DSI byte_intf_clk in KHz. * @pixel_clk_rate: Frequency of DSI pixel_clk in KHz. * @esc_clk_rate: Frequency of DSI escape clock in KHz. */ struct link_clk_freq { u32 byte_clk_rate; + u32 byte_intf_clk_rate; u32 pix_clk_rate; u32 esc_clk_rate; }; @@ -306,10 +308,12 @@ int dsi_clk_set_pixel_clk_rate(void *client, u64 pixel_clk, u32 index); * dsi_clk_set_byte_clk_rate() - set frequency for byte clock * @client: DSI clock client pointer. * @byte_clk: Pixel clock rate in Hz. + * @byte_intf_clk: Byte interface clock rate in Hz. * @index: Index of the DSI controller. * return: error code in case of failure or 0 for success. */ -int dsi_clk_set_byte_clk_rate(void *client, u64 byte_clk, u32 index); +int dsi_clk_set_byte_clk_rate(void *client, u64 byte_clk, + u64 byte_intf_clk, u32 index); /** * dsi_clk_update_parent() - update parent clocks for specified clock diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_clk_manager.c b/drivers/gpu/drm/msm/dsi-staging/dsi_clk_manager.c index 0094d4c5d90f..3868504391a6 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_clk_manager.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_clk_manager.c @@ -139,15 +139,16 @@ int dsi_clk_set_pixel_clk_rate(void *client, u64 pixel_clk, u32 index) * dsi_clk_set_byte_clk_rate() - set frequency for byte clock * @client: DSI clock client pointer. * @byte_clk: Byte clock rate in Hz. + * @byte_intf_clk: Byte interface clock rate in Hz. * @index: Index of the DSI controller. * return: error code in case of failure or 0 for success. */ -int dsi_clk_set_byte_clk_rate(void *client, u64 byte_clk, u32 index) +int dsi_clk_set_byte_clk_rate(void *client, u64 byte_clk, + u64 byte_intf_clk, u32 index) { int rc = 0; struct dsi_clk_client_info *c = client; struct dsi_clk_mngr *mngr; - u64 byte_intf_rate; mngr = c->mngr; rc = clk_set_rate(mngr->link_clks[index].hs_clks.byte_clk, byte_clk); @@ -157,12 +158,14 @@ int dsi_clk_set_byte_clk_rate(void *client, u64 byte_clk, u32 index) mngr->link_clks[index].freq.byte_clk_rate = byte_clk; if (mngr->link_clks[index].hs_clks.byte_intf_clk) { - byte_intf_rate = mngr->link_clks[index].freq.byte_clk_rate / 2; rc = clk_set_rate(mngr->link_clks[index].hs_clks.byte_intf_clk, - byte_intf_rate); + byte_intf_clk); if (rc) pr_err("failed to set clk rate for byte intf clk=%d\n", rc); + else + mngr->link_clks[index].freq.byte_intf_clk_rate = + byte_intf_clk; } return rc; @@ -371,12 +374,10 @@ static int dsi_link_hs_clk_set_rate(struct dsi_link_hs_clk_info *link_hs_clks, /* * If byte_intf_clk is present, set rate for that too. - * For DPHY: byte_intf_clk_rate = byte_clk_rate / 2 - * todo: this needs to be revisited when support for CPHY is added */ if (link_hs_clks->byte_intf_clk) { rc = clk_set_rate(link_hs_clks->byte_intf_clk, - (l_clks->freq.byte_clk_rate / 2)); + l_clks->freq.byte_intf_clk_rate); if (rc) { pr_err("set_rate failed for byte_intf_clk rc = %d\n", rc); diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c index dfe2d5c2890f..b358947f842e 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c @@ -844,10 +844,10 @@ static int dsi_ctrl_update_link_freqs(struct dsi_ctrl *dsi_ctrl, { int rc = 0; u32 num_of_lanes = 0; - u32 bpp; + u32 bpp, byte_intf_clk_div; u64 refresh_rate = TICKS_IN_MICRO_SECOND; u64 h_period, v_period, bit_rate, pclk_rate, bit_rate_per_lane, - byte_clk_rate; + byte_clk_rate, byte_intf_clk_rate; struct dsi_host_common_cfg *host_cfg = &config->common_config; struct dsi_split_link_config *split_link = &host_cfg->split_link; struct dsi_mode_info *timing = &config->video_timing; @@ -890,14 +890,21 @@ static int dsi_ctrl_update_link_freqs(struct dsi_ctrl *dsi_ctrl, do_div(pclk_rate, bpp); byte_clk_rate = bit_rate_per_lane; do_div(byte_clk_rate, 8); + byte_intf_clk_rate = byte_clk_rate; + byte_intf_clk_div = host_cfg->byte_intf_clk_div; + do_div(byte_intf_clk_rate, byte_intf_clk_div); + pr_debug("bit_clk_rate = %llu, bit_clk_rate_per_lane = %llu\n", bit_rate, bit_rate_per_lane); + pr_debug("bit_clk_rate = %llu, byte_intf_clk_rate = %llu\n", + bit_rate, byte_intf_clk_rate); pr_debug("byte_clk_rate = %llu, pclk_rate = %llu\n", byte_clk_rate, pclk_rate); dsi_ctrl->clk_freq.byte_clk_rate = byte_clk_rate; dsi_ctrl->clk_freq.pix_clk_rate = pclk_rate; dsi_ctrl->clk_freq.esc_clk_rate = config->esc_clk_rate_hz; + dsi_ctrl->clk_freq.byte_intf_clk_rate = byte_intf_clk_rate; config->bit_clk_rate_hz = dsi_ctrl->clk_freq.byte_clk_rate * 8; rc = dsi_clk_set_link_frequencies(clk_handle, dsi_ctrl->clk_freq, diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h b/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h index 2cc47519e2a8..3ee6a2811103 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h @@ -508,6 +508,7 @@ struct dsi_split_link_config { * reg config. * @force_hs_clk_lane: Send continuous clock to the panel. * @dsi_split_link_config: Split Link Configuration. + * @byte_intf_clk_div: Determines the factor for calculating byte intf clock. */ struct dsi_host_common_cfg { enum dsi_pixel_format dst_format; @@ -530,6 +531,7 @@ struct dsi_host_common_cfg { u32 ext_bridge_map[MAX_DSI_CTRLS_PER_DISPLAY]; bool force_hs_clk_lane; struct dsi_split_link_config split_link; + u32 byte_intf_clk_div; }; /** diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c index dcc9c95481de..82850515407f 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c @@ -4097,6 +4097,22 @@ static bool dsi_display_is_seamless_dfps_possible( return true; } +void dsi_display_update_byte_intf_div(struct dsi_display *display) +{ + struct dsi_host_common_cfg *config; + struct dsi_display_ctrl *m_ctrl; + int phy_ver; + + m_ctrl = &display->ctrl[display->cmd_master_idx]; + config = &display->panel->host_config; + + phy_ver = dsi_phy_get_version(m_ctrl->phy); + if (phy_ver <= DSI_PHY_VERSION_2_0) + config->byte_intf_clk_div = 1; + else + config->byte_intf_clk_div = 2; +} + static int dsi_display_update_dsi_bitrate(struct dsi_display *display, u32 bit_clk_rate) { @@ -4119,8 +4135,9 @@ static int dsi_display_update_dsi_bitrate(struct dsi_display *display, display_for_each_ctrl(i, display) { struct dsi_display_ctrl *dsi_disp_ctrl = &display->ctrl[i]; struct dsi_ctrl *ctrl = dsi_disp_ctrl->ctrl; - u32 num_of_lanes = 0, bpp; - u64 bit_rate, pclk_rate, bit_rate_per_lane, byte_clk_rate; + u32 num_of_lanes = 0, bpp, byte_intf_clk_div; + u64 bit_rate, pclk_rate, bit_rate_per_lane, byte_clk_rate, + byte_intf_clk_rate; struct dsi_host_common_cfg *host_cfg; mutex_lock(&ctrl->ctrl_lock); @@ -4150,12 +4167,19 @@ static int dsi_display_update_dsi_bitrate(struct dsi_display *display, do_div(pclk_rate, bpp); byte_clk_rate = bit_rate_per_lane; do_div(byte_clk_rate, 8); + byte_intf_clk_rate = byte_clk_rate; + byte_intf_clk_div = host_cfg->byte_intf_clk_div; + do_div(byte_intf_clk_rate, byte_intf_clk_div); + pr_debug("bit_clk_rate = %llu, bit_clk_rate_per_lane = %llu\n", bit_rate, bit_rate_per_lane); + pr_debug("bit_clk_rate = %llu, byte_intf_clk_rate = %llu\n", + bit_rate, byte_intf_clk_rate); pr_debug("byte_clk_rate = %llu, pclk_rate = %llu\n", byte_clk_rate, pclk_rate); ctrl->clk_freq.byte_clk_rate = byte_clk_rate; + ctrl->clk_freq.byte_intf_clk_rate = byte_intf_clk_rate; ctrl->clk_freq.pix_clk_rate = pclk_rate; rc = dsi_clk_set_link_frequencies(display->dsi_clk_handle, ctrl->clk_freq, ctrl->cell_index); @@ -4249,7 +4273,8 @@ static int _dsi_display_dyn_update_clks(struct dsi_display *display, if (!ctrl->ctrl) continue; rc = dsi_clk_set_byte_clk_rate(display->dsi_clk_handle, - ctrl->ctrl->clk_freq.byte_clk_rate, i); + ctrl->ctrl->clk_freq.byte_clk_rate, + ctrl->ctrl->clk_freq.byte_intf_clk_rate, i); if (rc) { pr_err("failed to set byte rate for index:%d\n", i); goto recover_byte_clk; @@ -4312,7 +4337,8 @@ recover_byte_clk: if (!ctrl->ctrl) continue; dsi_clk_set_byte_clk_rate(display->dsi_clk_handle, - bkp_freq->byte_clk_rate, i); + bkp_freq->byte_clk_rate, + bkp_freq->byte_intf_clk_rate, i); } exit: @@ -4348,6 +4374,7 @@ static int dsi_display_dynamic_clk_switch_vid(struct dsi_display *display, /* back up existing rates to handle failure case */ bkp_freq.byte_clk_rate = m_ctrl->ctrl->clk_freq.byte_clk_rate; + bkp_freq.byte_intf_clk_rate = m_ctrl->ctrl->clk_freq.byte_intf_clk_rate; bkp_freq.pix_clk_rate = m_ctrl->ctrl->clk_freq.pix_clk_rate; bkp_freq.esc_clk_rate = m_ctrl->ctrl->clk_freq.esc_clk_rate; @@ -5324,6 +5351,7 @@ static int dsi_display_bind(struct device *dev, } } + dsi_display_update_byte_intf_div(display); rc = dsi_display_mipi_host_init(display); if (rc) { pr_err("[%s] failed to initialize mipi host, rc=%d\n", diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c b/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c index 58256a5efda5..fdaa94277b9a 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c @@ -103,6 +103,11 @@ static const struct of_device_id msm_dsi_phy_of_match[] = { {} }; +int dsi_phy_get_version(struct msm_dsi_phy *phy) +{ + return phy->ver_info->version; +} + static int dsi_phy_regmap_init(struct platform_device *pdev, struct msm_dsi_phy *phy) { diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy.h b/drivers/gpu/drm/msm/dsi-staging/dsi_phy.h index 566d49d14862..bb6e750b74c0 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy.h +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy.h @@ -129,6 +129,14 @@ struct msm_dsi_phy *dsi_phy_get(struct device_node *of_node); */ void dsi_phy_put(struct msm_dsi_phy *dsi_phy); +/** + * dsi_phy_get_version() - returns dsi phy version + * @dsi_phy: DSI PHY handle. + * + * Return: phy version + */ +int dsi_phy_get_version(struct msm_dsi_phy *phy); + /** * dsi_phy_drv_init() - initialize dsi phy driver * @dsi_phy: DSI PHY handle. From 7dbf135fc5ea1bb75269a7f7c163c1795595a17b Mon Sep 17 00:00:00 2001 From: Ritesh Kumar Date: Wed, 24 Jun 2020 02:00:36 +0530 Subject: [PATCH 458/592] BACKPORT: disp: msm: dsi: Fix pll delay calculation during clock switch During clock switch, Pll delay is calculated considering escape clock to be in KHz. But escape clock is in Hz. This leads to wrong pll delay calculation. Change-Id: I616d16cc3d775a37e77c7c35bb860c23b1f9e37a Signed-off-by: Ritesh Kumar Signed-off-by: UtsavBalar1231 --- drivers/gpu/drm/msm/dsi-staging/dsi_clk.h | 8 ++++---- drivers/gpu/drm/msm/dsi-staging/dsi_defs.h | 2 +- drivers/gpu/drm/msm/dsi-staging/dsi_display.c | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_clk.h b/drivers/gpu/drm/msm/dsi-staging/dsi_clk.h index b0ee9ac7047a..a1121a9b6126 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_clk.h +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_clk.h @@ -116,10 +116,10 @@ struct dsi_link_lp_clk_info { /** * struct link_clk_freq - Clock frequency information for Link clocks - * @byte_clk_rate: Frequency of DSI byte_clk in KHz. - * @byte_intf_clk_rate: Frequency of DSI byte_intf_clk in KHz. - * @pixel_clk_rate: Frequency of DSI pixel_clk in KHz. - * @esc_clk_rate: Frequency of DSI escape clock in KHz. + * @byte_clk_rate: Frequency of DSI byte_clk in Hz. + * @byte_intf_clk_rate: Frequency of DSI byte_intf_clk in Hz. + * @pixel_clk_rate: Frequency of DSI pixel_clk in Hz. + * @esc_clk_rate: Frequency of DSI escape clock in Hz. */ struct link_clk_freq { u32 byte_clk_rate; diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h b/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h index 3ee6a2811103..0f737bf5e61f 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h @@ -587,7 +587,7 @@ struct dsi_cmd_engine_cfg { * @common_config: Host configuration common to both Video and Cmd mode. * @video_engine: Video engine configuration if panel is in video mode. * @cmd_engine: Cmd engine configuration if panel is in cmd mode. - * @esc_clk_rate_khz: Esc clock frequency in Hz. + * @esc_clk_rate_hz: Esc clock frequency in Hz. * @bit_clk_rate_hz: Bit clock frequency in Hz. * @bit_clk_rate_hz_override: DSI bit clk rate override from dt/sysfs. * @video_timing: Video timing information of a frame. diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c index 82850515407f..0490a4450356 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c @@ -4216,12 +4216,12 @@ static void _dsi_display_calc_pipe_delay(struct dsi_display *display, cfg = &(m_ctrl->phy->cfg); - esc_clk_rate_hz = dsi_ctrl->clk_freq.esc_clk_rate * 1000; - pclk_to_esc_ratio = ((dsi_ctrl->clk_freq.pix_clk_rate * 1000) / + esc_clk_rate_hz = dsi_ctrl->clk_freq.esc_clk_rate; + pclk_to_esc_ratio = (dsi_ctrl->clk_freq.pix_clk_rate / esc_clk_rate_hz); - byte_to_esc_ratio = ((dsi_ctrl->clk_freq.byte_clk_rate * 1000) / + byte_to_esc_ratio = (dsi_ctrl->clk_freq.byte_clk_rate / esc_clk_rate_hz); - hr_bit_to_esc_ratio = ((dsi_ctrl->clk_freq.byte_clk_rate * 4 * 1000) / + hr_bit_to_esc_ratio = ((dsi_ctrl->clk_freq.byte_clk_rate * 4) / esc_clk_rate_hz); hsync_period = DSI_H_TOTAL_DSC(&mode->timing); From 486c0c6f8f1ce38c1b3190118a221edd0a5d57e8 Mon Sep 17 00:00:00 2001 From: Ritesh Kumar Date: Fri, 26 Jun 2020 02:00:36 +0530 Subject: [PATCH 459/592] BACKPORT: disp: msm: dsi: Update pll delay calculation as per latest DSI HPG As per DSI HPG, pll delay should be 25usec for phy ver 4.0 and 100usec for phy ver 2.0 and 3.0. This change updates pll delay calculation during dynamic DSI clock switch accordingly. Change-Id: Ief5cbdc9304cf5ad025fe3bbe689b93834a1f710 Signed-off-by: Ritesh Kumar Signed-off-by: UtsavBalar1231 --- drivers/gpu/drm/msm/dsi-staging/dsi_display.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c index 0490a4450356..cf82d664d4a5 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c @@ -4210,6 +4210,7 @@ static void _dsi_display_calc_pipe_delay(struct dsi_display *display, struct dsi_display_ctrl *m_ctrl; struct dsi_ctrl *dsi_ctrl; struct dsi_phy_cfg *cfg; + int phy_ver; m_ctrl = &display->ctrl[display->clk_master_idx]; dsi_ctrl = m_ctrl->ctrl; @@ -4247,8 +4248,17 @@ static void _dsi_display_calc_pipe_delay(struct dsi_display *display, ((cfg->timing.lane_v3[4] >> 1) + 1)) / hr_bit_to_esc_ratio); - /* 130 us pll delay recommended by h/w doc */ - delay->pll_delay = ((130 * esc_clk_rate_hz) / 1000000) * 2; + /* + * 100us pll delay recommended for phy ver 2.0 and 3.0 + * 25us pll delay recommended for phy ver 4.0 + */ + phy_ver = dsi_phy_get_version(m_ctrl->phy); + if (phy_ver <= DSI_PHY_VERSION_3_0) + delay->pll_delay = 100; + else + delay->pll_delay = 25; + + delay->pll_delay = ((delay->pll_delay * esc_clk_rate_hz) / 1000000); } static int _dsi_display_dyn_update_clks(struct dsi_display *display, From 83da8abe9e6e4e465a83460292adb9848528e472 Mon Sep 17 00:00:00 2001 From: Martijn Coenen Date: Thu, 6 Aug 2020 21:42:11 +0530 Subject: [PATCH 460/592] ANDROID: ARM64: configs: raphael: enable CONFIG_EXT4_FS_POSIX_ACL This is required on devices without sdcardfs. Bug: 158733532 Test: manual Change-Id: I21d6ee488b7e4a094260cffc654a4c9dc3392081 Signed-off-by: Martijn Coenen Signed-off-by: UtsavBalar1231 --- arch/arm64/configs/raphael_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/configs/raphael_defconfig b/arch/arm64/configs/raphael_defconfig index 17f8b9590fb1..eea8b4c56f14 100644 --- a/arch/arm64/configs/raphael_defconfig +++ b/arch/arm64/configs/raphael_defconfig @@ -4738,7 +4738,7 @@ CONFIG_DCACHE_WORD_ACCESS=y # CONFIG_EXT3_FS is not set CONFIG_EXT4_FS=y CONFIG_EXT4_USE_FOR_EXT2=y -# CONFIG_EXT4_FS_POSIX_ACL is not set +CONFIG_EXT4_FS_POSIX_ACL=y CONFIG_EXT4_FS_SECURITY=y CONFIG_EXT4_ENCRYPTION=y CONFIG_EXT4_FS_ENCRYPTION=y From 99e7949c1257187ba0aad33d11514c52f7c56d65 Mon Sep 17 00:00:00 2001 From: Pavankumar Kondeti Date: Mon, 13 Jul 2020 11:21:14 +0530 Subject: [PATCH 461/592] sched/fair: Add timeout for detach_tasks() in load balance When the busy CPU has thousands of tasks, the current loop break of 32 does not scale nicely. Because each task deactivation may take ~5 msec. Since this all happens from interrupts disabled (from softirq also), it is resulting in watchdog bark. Hence add 5 msec timeout in detach_tasks() to abort the load balance. Change-Id: I290f75076f13a44d866dc4fe5fe6653733d28fbc Signed-off-by: Pavankumar Kondeti Signed-off-by: UtsavBalar1231 --- kernel/sched/fair.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index ac8a967d81ed..4fd27fd17349 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -9287,17 +9287,21 @@ static int detach_tasks(struct lb_env *env) unsigned long load = 0; int detached = 0; int orig_loop = env->loop; + u64 start_t = rq_clock(env->src_rq); lockdep_assert_held(&env->src_rq->lock); if (env->imbalance <= 0) return 0; - if (!same_cluster(env->dst_cpu, env->src_cpu)) - env->flags |= LBF_IGNORE_PREFERRED_CLUSTER_TASKS; + if (env->src_rq->nr_running < 32) { + if (!same_cluster(env->dst_cpu, env->src_cpu)) + env->flags |= LBF_IGNORE_PREFERRED_CLUSTER_TASKS; - if (capacity_orig_of(env->dst_cpu) < capacity_orig_of(env->src_cpu)) - env->flags |= LBF_IGNORE_BIG_TASKS; + if (capacity_orig_of(env->dst_cpu) < + capacity_orig_of(env->src_cpu)) + env->flags |= LBF_IGNORE_BIG_TASKS; + } redo: while (!list_empty(tasks)) { @@ -9315,6 +9319,10 @@ redo: if (env->loop > env->loop_max) break; + /* Abort the loop, if we spent more than 5 msec */ + if (rq_clock(env->src_rq) - start_t > 5000000) + break; + /* take a breather every nr_migrate tasks */ if (env->loop > env->loop_break) { env->loop_break += sched_nr_migrate_break; From 34e6577c89cafa244c00ccf3abb9217685bbad0c Mon Sep 17 00:00:00 2001 From: Pavankumar Kondeti Date: Tue, 14 Jul 2020 12:24:11 +0530 Subject: [PATCH 462/592] sched/walt: Avoid taking rq lock for every IRQ update sched_account_irqtime() is called for every IRQ/SoftIRQ update. The rq->lock is needed only in idle context in which case update_task_ravg() is called. For IRQ load updates, rq->lock is not needed, since these are tracked per-cpu and migrations are not applicable for irqload. By not taking rq lock for every interrupt, we don't delay the irq exit path under heavy rq lock contention. For example, this CPU is loaded with thousands of tasks and rq->lock is acquired during load balance. Change-Id: Iebba1a84408509ce93b3a8a0dcc1a9ea1f1bc930 Signed-off-by: Pavankumar Kondeti Signed-off-by: UtsavBalar1231 --- kernel/sched/walt.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/kernel/sched/walt.c b/kernel/sched/walt.c index 9251e239ebcb..22658e8afdb4 100644 --- a/kernel/sched/walt.c +++ b/kernel/sched/walt.c @@ -432,22 +432,27 @@ void sched_account_irqtime(int cpu, struct task_struct *curr, u64 delta, u64 wallclock) { struct rq *rq = cpu_rq(cpu); - unsigned long flags, nr_windows; + unsigned long nr_windows; u64 cur_jiffies_ts; - raw_spin_lock_irqsave(&rq->lock, flags); - /* - * cputime (wallclock) uses sched_clock so use the same here for - * consistency. + * We called with interrupts disabled. Take the rq lock only + * if we are in idle context in which case update_task_ravg() + * call is needed. */ - delta += sched_clock() - wallclock; - cur_jiffies_ts = get_jiffies_64(); - - if (is_idle_task(curr)) + if (is_idle_task(curr)) { + raw_spin_lock(&rq->lock); + /* + * cputime (wallclock) uses sched_clock so use the same here + * for consistency. + */ + delta += sched_clock() - wallclock; update_task_ravg(curr, rq, IRQ_UPDATE, sched_ktime_clock(), delta); + raw_spin_unlock(&rq->lock); + } + cur_jiffies_ts = get_jiffies_64(); nr_windows = cur_jiffies_ts - rq->irqload_ts; if (nr_windows) { @@ -465,7 +470,6 @@ void sched_account_irqtime(int cpu, struct task_struct *curr, rq->cur_irqload += delta; rq->irqload_ts = cur_jiffies_ts; - raw_spin_unlock_irqrestore(&rq->lock, flags); } /* From 4ab420dd42ba54f4a6e8e541f4aac8e6086e6d41 Mon Sep 17 00:00:00 2001 From: blong Date: Thu, 8 Aug 2019 16:16:02 +0800 Subject: [PATCH 463/592] Sched/fair: Improve the scheduler This change is for general scheduler improvements. Change-Id: I95dca7ecedb3921196203cb5f2ed1b6b221b7703 Signed-off-by: blong Signed-off-by: UtsavBalar1231 --- kernel/sched/fair.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 4fd27fd17349..cdbefb5ecf17 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -7420,6 +7420,7 @@ static int get_start_cpu(struct task_struct *p) { struct root_domain *rd = cpu_rq(smp_processor_id())->rd; int start_cpu = rd->min_cap_orig_cpu; + int task_boost = per_task_boost(p); bool boosted = schedtune_task_boost(p) > 0 || task_boost_policy(p) == SCHED_BOOST_ON_BIG; bool task_skip_min = (sched_boost() != CONSERVATIVE_BOOST) @@ -7430,10 +7431,16 @@ static int get_start_cpu(struct task_struct *p) * or just mid will be -1, there never be any other combinations of -1s * beyond these */ - if (task_skip_min || boosted) { + if (task_skip_min || boosted || task_boost == 1) { start_cpu = rd->mid_cap_orig_cpu == -1 ? rd->max_cap_orig_cpu : rd->mid_cap_orig_cpu; } + + if (task_boost == 2) { + start_cpu = rd->max_cap_orig_cpu; + return start_cpu; + } + if (start_cpu == -1 || start_cpu == rd->max_cap_orig_cpu) return start_cpu; From 6b235d6248160020cec6b6ec8e0175f5485ddd9b Mon Sep 17 00:00:00 2001 From: blong Date: Fri, 6 Sep 2019 16:56:36 +0800 Subject: [PATCH 464/592] Sched/fair: Improve the scheduler This change is for general scheduler improvement. Change-Id: Iefac9abcc7f4e3833e2434d0f508c493bdf0b28c Signed-off-by: blong Signed-off-by: UtsavBalar1231 --- fs/proc/base.c | 2 +- include/linux/sched.h | 8 ++++++++ kernel/sched/core.c | 2 +- kernel/sched/fair.c | 42 +++++++++++++++++++++++++++++++++++------- 4 files changed, 45 insertions(+), 9 deletions(-) diff --git a/fs/proc/base.c b/fs/proc/base.c index 769ea7f7a9a6..8eccdf2df797 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -3037,7 +3037,7 @@ static ssize_t proc_sched_task_boost_write(struct file *file, err = kstrtoint(strstrip(buffer), 0, &sched_boost); if (err) goto out; - if (sched_boost < 0 || sched_boost > 2) { + if (sched_boost < TASK_BOOST_NONE || sched_boost >= TASK_BOOST_END) { err = -EINVAL; goto out; } diff --git a/include/linux/sched.h b/include/linux/sched.h index bff0ed6de4c7..b4faf79cb4e3 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -123,6 +123,14 @@ enum fps { FPS120 = 120, }; +enum task_boost_type { + TASK_BOOST_NONE = 0, + TASK_BOOST_ON_MID, + TASK_BOOST_ON_MAX, + TASK_BOOST_STRICT_MAX, + TASK_BOOST_END, +}; + #ifdef CONFIG_DEBUG_ATOMIC_SLEEP /* diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 01d0ab93cedb..8f7ee573a73e 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -7389,7 +7389,7 @@ const u32 sched_prio_to_wmult[40] = { */ int set_task_boost(int boost, u64 period) { - if (boost < 0 || boost > 2) + if (boost < TASK_BOOST_NONE || boost >= TASK_BOOST_END) return -EINVAL; if (boost) { current->boost = boost; diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index cdbefb5ecf17..a7a711e69726 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -7335,7 +7335,7 @@ static inline bool task_fits_max(struct task_struct *p, int cpu) walt_should_kick_upmigrate(p, cpu)) return false; } else { /* mid cap cpu */ - if (task_boost > 1) + if (task_boost > TASK_BOOST_ON_MID) return false; } @@ -7361,6 +7361,7 @@ struct find_best_target_env { int fastpath; int skip_cpu; int start_cpu; + bool strict_max; }; static inline bool prefer_spread_on_idle(int cpu) @@ -7422,7 +7423,8 @@ static int get_start_cpu(struct task_struct *p) int start_cpu = rd->min_cap_orig_cpu; int task_boost = per_task_boost(p); bool boosted = schedtune_task_boost(p) > 0 || - task_boost_policy(p) == SCHED_BOOST_ON_BIG; + task_boost_policy(p) == SCHED_BOOST_ON_BIG || + task_boost == TASK_BOOST_ON_MID; bool task_skip_min = (sched_boost() != CONSERVATIVE_BOOST) && get_rtg_status(p) && p->unfilter; @@ -7431,12 +7433,12 @@ static int get_start_cpu(struct task_struct *p) * or just mid will be -1, there never be any other combinations of -1s * beyond these */ - if (task_skip_min || boosted || task_boost == 1) { + if (task_skip_min || boosted) { start_cpu = rd->mid_cap_orig_cpu == -1 ? rd->max_cap_orig_cpu : rd->mid_cap_orig_cpu; } - if (task_boost == 2) { + if (task_boost > TASK_BOOST_ON_MID) { start_cpu = rd->max_cap_orig_cpu; return start_cpu; } @@ -7502,6 +7504,9 @@ static inline int find_best_target(struct task_struct *p, int *backup_cpu, if (prefer_idle && boosted) target_capacity = 0; + if (fbt_env->strict_max) + most_spare_wake_cap = LONG_MIN; + /* Find start CPU based on boost value */ start_cpu = fbt_env->start_cpu; /* Find SD for the start CPU */ @@ -7821,7 +7826,8 @@ static inline int find_best_target(struct task_struct *p, int *backup_cpu, * accommodated in the higher capacity CPUs. */ if ((prefer_idle && best_idle_cpu != -1) || - (boosted && (best_idle_cpu != -1 || target_cpu != -1))) { + (boosted && (best_idle_cpu != -1 || target_cpu != -1 || + (fbt_env->strict_max && most_spare_cap_cpu != -1)))) { if (boosted) { if (!next_group_higher_cap) break; @@ -8122,7 +8128,8 @@ static int find_energy_efficient_cpu(struct sched_domain *sd, int placement_boost = task_boost_policy(p); u64 start_t = 0; int next_cpu = -1, backup_cpu = -1; - int boosted = (schedtune_task_boost(p) > 0 || per_task_boost(p) > 0); + int task_boost = per_task_boost(p); + int boosted = (schedtune_task_boost(p) > 0) || (task_boost > 0); int start_cpu; if (is_many_wakeup(sibling_count_hint) && prev_cpu != cpu && @@ -8208,6 +8215,8 @@ static int find_energy_efficient_cpu(struct sched_domain *sd, fbt_env.boosted = boosted; fbt_env.skip_cpu = is_many_wakeup(sibling_count_hint) ? cpu : -1; + fbt_env.strict_max = is_rtg && + (task_boost == TASK_BOOST_STRICT_MAX); /* Find a cpu with sufficient capacity */ target_cpu = find_best_target(p, &eenv->cpu[EAS_CPU_BKP].cpu_id, @@ -9120,6 +9129,16 @@ static inline int migrate_degrades_locality(struct task_struct *p, } #endif +static inline bool can_migrate_boosted_task(struct task_struct *p, + int src_cpu, int dst_cpu) +{ + if (per_task_boost(p) == TASK_BOOST_STRICT_MAX && + task_in_related_thread_group(p) && + (capacity_orig_of(dst_cpu) < capacity_orig_of(src_cpu))) + return false; + return true; +} + /* * can_migrate_task - may task p from runqueue rq be migrated to this_cpu? */ @@ -9140,6 +9159,12 @@ int can_migrate_task(struct task_struct *p, struct lb_env *env) if (throttled_lb_pair(task_group(p), env->src_cpu, env->dst_cpu)) return 0; + /* + * don't allow pull boost task to smaller cores. + */ + if (!can_migrate_boosted_task(p, env->src_cpu, env->dst_cpu)) + return 0; + if (!cpumask_test_cpu(env->dst_cpu, &p->cpus_allowed)) { int cpu; @@ -11208,7 +11233,10 @@ no_move: * if the curr task on busiest cpu can't be * moved to this_cpu */ - if (!cpumask_test_cpu(this_cpu, &busiest->curr->cpus_allowed)) { + if (!cpumask_test_cpu(this_cpu, + &busiest->curr->cpus_allowed) + || !can_migrate_boosted_task(busiest->curr, + cpu_of(busiest), this_cpu)) { raw_spin_unlock_irqrestore(&busiest->lock, flags); env.flags |= LBF_ALL_PINNED; From 0a3aef126bc24be084fc4eafc3fb55e8685be524 Mon Sep 17 00:00:00 2001 From: Maria Yu Date: Thu, 5 Sep 2019 10:32:39 +0800 Subject: [PATCH 465/592] sched/fair: bonus vruntime for task boost 3 When task boost with special value 3 also have vruntime bonus to run faster. Change-Id: I7da2dd985a961671b27036a0d5b13cb79480c933 Signed-off-by: Maria Yu Signed-off-by: UtsavBalar1231 --- kernel/sched/fair.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index a7a711e69726..1607d0ead01a 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -3947,6 +3947,9 @@ place_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int initial) thresh >>= 1; vruntime -= thresh; + if (entity_is_task(se) && per_task_boost(task_of(se)) == + TASK_BOOST_STRICT_MAX) + vruntime -= sysctl_sched_latency; } /* ensure we never gain time by being placed backwards. */ From 98f2b070e726d9ca770fd80f61cad87c4ea919c6 Mon Sep 17 00:00:00 2001 From: Satya Durga Srinivasu Prabhala Date: Thu, 2 Apr 2020 10:26:33 -0700 Subject: [PATCH 466/592] sched: Improve the scheduler This change is for general scheduler improvements. Change-Id: Iaefb893a84055748be7f2108179e3b869ac00318 Signed-off-by: Satya Durga Srinivasu Prabhala Signed-off-by: UtsavBalar1231 --- fs/proc/base.c | 53 +++++++++++++++++++++++++++++++++++++++++++ include/linux/sched.h | 1 + kernel/sched/core.c | 3 +++ kernel/sched/fair.c | 17 +++++++++++--- 4 files changed, 71 insertions(+), 3 deletions(-) diff --git a/fs/proc/base.c b/fs/proc/base.c index 8eccdf2df797..6e0e64bd11a0 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -1638,6 +1638,58 @@ static const struct file_operations proc_pid_sched_group_id_operations = { .release = single_release, }; +static int sched_low_latency_show(struct seq_file *m, void *v) +{ + struct inode *inode = m->private; + struct task_struct *p; + bool low_latency; + + p = get_proc_task(inode); + if (!p) + return -ESRCH; + + low_latency = p->low_latency; + seq_printf(m, "%d\n", low_latency); + + put_task_struct(p); + + return 0; +} + +static ssize_t +sched_low_latency_write(struct file *file, const char __user *buf, + size_t count, loff_t *offset) +{ + struct task_struct *p = get_proc_task(file_inode(file)); + bool low_latency; + int err; + + if (!p) + return -ESRCH; + + err = kstrtobool_from_user(buf, count, &low_latency); + if (err) + goto out; + + p->low_latency = low_latency; +out: + put_task_struct(p); + return err < 0 ? err : count; +} + +static int sched_low_latency_open(struct inode *inode, struct file *filp) +{ + return single_open(filp, sched_low_latency_show, inode); +} + +static const struct file_operations proc_pid_sched_low_latency_operations = { + .open = sched_low_latency_open, + .read = seq_read, + .write = sched_low_latency_write, + .llseek = seq_lseek, + .release = single_release, +}; + #endif /* CONFIG_SCHED_WALT */ #ifdef CONFIG_SCHED_AUTOGROUP @@ -3293,6 +3345,7 @@ static const struct pid_entry tgid_base_stuff[] = { REG("sched_group_id", 00666, proc_pid_sched_group_id_operations), REG("sched_boost", 0666, proc_task_boost_enabled_operations), REG("sched_boost_period_ms", 0666, proc_task_boost_period_operations), + REG("sched_low_latency", 00666, proc_pid_sched_low_latency_operations), #endif #ifdef CONFIG_SCHED_DEBUG REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations), diff --git a/include/linux/sched.h b/include/linux/sched.h index b4faf79cb4e3..6aed489d93ee 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -821,6 +821,7 @@ struct task_struct { u64 cpu_cycles; bool misfit; u32 unfilter; + bool low_latency; #endif #ifdef CONFIG_CGROUP_SCHED diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 8f7ee573a73e..4c60f9ee77aa 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -2316,6 +2316,9 @@ static void __sched_fork(unsigned long clone_flags, struct task_struct *p) p->boost_expires = 0; p->boost_period = 0; +#ifdef CONFIG_SCHED_WALT + p->low_latency = 0; +#endif INIT_LIST_HEAD(&p->se.group_node); #ifdef CONFIG_FAIR_GROUP_SCHED diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 1607d0ead01a..3753db83747d 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -3947,9 +3947,20 @@ place_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int initial) thresh >>= 1; vruntime -= thresh; - if (entity_is_task(se) && per_task_boost(task_of(se)) == - TASK_BOOST_STRICT_MAX) - vruntime -= sysctl_sched_latency; + if (entity_is_task(se)) { + if (per_task_boost(task_of(se)) == + TASK_BOOST_STRICT_MAX) + vruntime -= sysctl_sched_latency; +#ifdef CONFIG_SCHED_WALT + else if (unlikely(task_of(se)->low_latency)) { + vruntime -= sysctl_sched_latency; + vruntime -= thresh; + se->vruntime = min_vruntime(vruntime, + se->vruntime); + return; + } +#endif + } } /* ensure we never gain time by being placed backwards. */ From dffac07da20dbd5e4437d167214c2f30e937736d Mon Sep 17 00:00:00 2001 From: Lingutla Chandrasekhar Date: Mon, 9 Mar 2020 11:38:35 +0530 Subject: [PATCH 467/592] sched: Improve the scheduler This change is for general scheduler improvements. Change-Id: If3a85c0d4aeb56e4b3493fa09bb295114edf2137 Signed-off-by: Lingutla Chandrasekhar Signed-off-by: UtsavBalar1231 --- kernel/sched/walt.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/sched/walt.c b/kernel/sched/walt.c index 22658e8afdb4..407d4a8a47c0 100644 --- a/kernel/sched/walt.c +++ b/kernel/sched/walt.c @@ -3556,6 +3556,9 @@ int walt_proc_group_thresholds_handler(struct ctl_table *table, int write, struct rq *rq = cpu_rq(cpumask_first(cpu_possible_mask)); unsigned long flags; + if (unlikely(num_sched_clusters <= 0)) + return -EPERM; + mutex_lock(&mutex); ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos); if (ret || !write) { From 697c23a960f7ed767273bfb379d396c8f77e35fa Mon Sep 17 00:00:00 2001 From: Skylar Chang Date: Wed, 25 Mar 2020 21:40:05 -0700 Subject: [PATCH 468/592] ipa3: mpm: remove WARN_ON for security concern Removing the WARN_ON on dmesg due to security concern to expose device address, change to use IPA_MPM_ERR in ipc logs for debugging reference. Change-Id: I73d5ba9ad43cb43c7eb89801e1131482310b8464 Signed-off-by: Skylar Chang Signed-off-by: UtsavBalar1231 --- drivers/platform/msm/ipa/ipa_v3/ipa_mpm.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_mpm.c b/drivers/platform/msm/ipa/ipa_v3/ipa_mpm.c index d1a9ab8bf8a5..c2422e8b2a52 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_mpm.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_mpm.c @@ -642,7 +642,6 @@ static void ipa_mpm_smmu_unmap(dma_addr_t carved_iova, int sz, int dir, if (carved_iova <= 0) { IPA_MPM_ERR("carved_iova is zero/negative\n"); - WARN_ON(1); return; } @@ -1444,9 +1443,8 @@ static int ipa_mpm_vote_unvote_pcie_clk(enum ipa_mpm_clk_vote_type vote, if ((atomic_read( &ipa_mpm_ctx->md[probe_id].clk_cnt.pcie_clk_cnt) == 0)) { - IPA_MPM_DBG("probe_id %d PCIE clock already devoted\n", + IPA_MPM_ERR("probe_id %d PCIE clock already devoted\n", probe_id); - WARN_ON(1); return 0; } mhi_device_put(ipa_mpm_ctx->md[probe_id].mhi_dev, MHI_VOTE_BUS); @@ -1480,9 +1478,8 @@ static void ipa_mpm_vote_unvote_ipa_clk(enum ipa_mpm_clk_vote_type vote, if ((atomic_read (&ipa_mpm_ctx->md[probe_id].clk_cnt.ipa_clk_cnt) == 0)) { - IPA_MPM_DBG("probe_id %d IPA clock count < 0\n", + IPA_MPM_ERR("probe_id %d IPA clock count < 0\n", probe_id); - WARN_ON(1); return; } IPA_ACTIVE_CLIENTS_DEC_SPECIAL(ipa_mpm_mhip_chan_str[probe_id]); @@ -2037,7 +2034,6 @@ static int ipa_mpm_mhi_probe_cb(struct mhi_device *mhi_dev, ret = mhi_prepare_for_transfer(ipa_mpm_ctx->md[probe_id].mhi_dev); if (ret) { IPA_MPM_ERR("mhi_prepare_for_transfer failed %d\n", ret); - WARN_ON(1); /* * WA to handle prepare_for_tx failures. * Though prepare for transfer fails, indicate success From 642c687bdb1a5e3239de12c4ba3a56eda21a6f5d Mon Sep 17 00:00:00 2001 From: Hemant Kumar Date: Sun, 28 Jun 2020 22:12:45 -0700 Subject: [PATCH 469/592] mhi: devices: mhi_netdev: Update napi poll weight to 128 Increasing napi poll weight to 128 helps processing OOB sooner. This reduces the napi schedule overhead if number of outstanding events are higher and OOB event is posted later in the pending list of events. Change-Id: Ia51fcef7ded560e1986a1e6d80fdd162df7c1903 Signed-off-by: Hemant Kumar Signed-off-by: UtsavBalar1231 --- drivers/bus/mhi/devices/mhi_netdev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/bus/mhi/devices/mhi_netdev.c b/drivers/bus/mhi/devices/mhi_netdev.c index 28a619fef3c0..7690addfbf12 100644 --- a/drivers/bus/mhi/devices/mhi_netdev.c +++ b/drivers/bus/mhi/devices/mhi_netdev.c @@ -30,6 +30,7 @@ #define WATCHDOG_TIMEOUT (30 * HZ) #define IPC_LOG_PAGES (100) #define MAX_NETBUF_SIZE (128) +#define MHI_NETDEV_NAPI_POLL_WEIGHT (128) #ifdef CONFIG_MHI_DEBUG @@ -710,7 +711,7 @@ static int mhi_netdev_enable_iface(struct mhi_netdev *mhi_netdev) } netif_napi_add(mhi_netdev->ndev, mhi_netdev->napi, - mhi_netdev_poll, NAPI_POLL_WEIGHT); + mhi_netdev_poll, MHI_NETDEV_NAPI_POLL_WEIGHT); ret = register_netdev(mhi_netdev->ndev); if (ret) { MSG_ERR("Network device registration failed\n"); From 73f77057538538f06d35d81fff16863422cbebe7 Mon Sep 17 00:00:00 2001 From: Lina Iyer Date: Mon, 11 May 2020 11:14:16 -0600 Subject: [PATCH 470/592] drivers: cpuidle: lpm-levels: check for valid LPM stats When DEBUG_FS is not defined, the cluster->stats may be initialized to an error value. Check for valid stats pointer before updating the start and end times. Change-Id: I126766a017ebd9a84bd40f19ab3ff47877615429 Signed-off-by: Lina Iyer Signed-off-by: UtsavBalar1231 --- drivers/cpuidle/lpm-levels.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/cpuidle/lpm-levels.c b/drivers/cpuidle/lpm-levels.c index 2fd5e9a1d753..dedee32df33c 100644 --- a/drivers/cpuidle/lpm-levels.c +++ b/drivers/cpuidle/lpm-levels.c @@ -1164,7 +1164,8 @@ static void cluster_prepare(struct lpm_cluster *cluster, if (cluster_configure(cluster, i, from_idle, predicted)) goto failed; - cluster->stats->sleep_time = start_time; + if (!IS_ERR_OR_NULL(cluster->stats)) + cluster->stats->sleep_time = start_time; cluster_prepare(cluster->parent, &cluster->num_children_in_sync, i, from_idle, start_time); @@ -1172,7 +1173,8 @@ static void cluster_prepare(struct lpm_cluster *cluster, return; failed: spin_unlock(&cluster->sync_lock); - cluster->stats->sleep_time = 0; + if (!IS_ERR_OR_NULL(cluster->stats)) + cluster->stats->sleep_time = 0; } static void cluster_unprepare(struct lpm_cluster *cluster, @@ -1211,7 +1213,7 @@ static void cluster_unprepare(struct lpm_cluster *cluster, if (!first_cpu || cluster->last_level == cluster->default_level) goto unlock_return; - if (cluster->stats->sleep_time) + if (!IS_ERR_OR_NULL(cluster->stats) && cluster->stats->sleep_time) cluster->stats->sleep_time = end_time - cluster->stats->sleep_time; lpm_stats_cluster_exit(cluster->stats, cluster->last_level, success); @@ -1648,6 +1650,9 @@ static void register_cluster_lpm_stats(struct lpm_cluster *cl, cl->stats = lpm_stats_config_level(cl->cluster_name, level_name, cl->nlevels, parent ? parent->stats : NULL, NULL); + if (IS_ERR_OR_NULL(cl->stats)) + pr_info("Cluster (%s) stats not registered\n", + cl->cluster_name); kfree(level_name); From 2d6a7108ed74e0c857f78809d74511f52dbf9c85 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 5 Aug 2020 11:49:14 +0200 Subject: [PATCH 471/592] Revert "scsi: libsas: direct call probe and destruct" This reverts commit 3a156abd24346a3188eb7e88cf86386a409e0d02 which is commit 0558f33c06bb910e2879e355192227a8e8f0219d upstream. John writes: This patch was one of a series from Jason to fix this WARN issue, below: https://lore.kernel.org/linux-scsi/8f6e3763-2b04-23e8-f1ec-8ed3c58f55d3@huawei.com/ I'm doubtful that it should be taken in isolation. Maybe 1 or 2 other patches are required. The WARN was really annoying, so we could spend a bit of time to test a backport of what is strictly required. Let us know. Cc: Jason Yan CC: John Garry CC: Johannes Thumshirn CC: Ewan Milne CC: Christoph Hellwig CC: Tomas Henzl CC: Dan Williams Cc: Hannes Reinecke Cc: Martin K. Petersen Cc: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/libsas/sas_ata.c | 1 + drivers/scsi/libsas/sas_discover.c | 32 +++++++++++++----------------- drivers/scsi/libsas/sas_expander.c | 8 +++++--- drivers/scsi/libsas/sas_internal.h | 1 - drivers/scsi/libsas/sas_port.c | 3 --- include/scsi/libsas.h | 3 ++- include/scsi/scsi_transport_sas.h | 1 - 7 files changed, 22 insertions(+), 27 deletions(-) diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index 2b3637b40dde..70be4425ae0b 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c @@ -730,6 +730,7 @@ int sas_discover_sata(struct domain_device *dev) if (res) return res; + sas_discover_event(dev->port, DISCE_PROBE); return 0; } diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c index d6365e2fcc60..b200edc665a5 100644 --- a/drivers/scsi/libsas/sas_discover.c +++ b/drivers/scsi/libsas/sas_discover.c @@ -221,9 +221,13 @@ void sas_notify_lldd_dev_gone(struct domain_device *dev) } } -static void sas_probe_devices(struct asd_sas_port *port) +static void sas_probe_devices(struct work_struct *work) { struct domain_device *dev, *n; + struct sas_discovery_event *ev = to_sas_discovery_event(work); + struct asd_sas_port *port = ev->port; + + clear_bit(DISCE_PROBE, &port->disc.pending); /* devices must be domain members before link recovery and probe */ list_for_each_entry(dev, &port->disco_list, disco_list_node) { @@ -299,6 +303,7 @@ int sas_discover_end_dev(struct domain_device *dev) res = sas_notify_lldd_dev_found(dev); if (res) return res; + sas_discover_event(dev->port, DISCE_PROBE); return 0; } @@ -357,9 +362,13 @@ static void sas_unregister_common_dev(struct asd_sas_port *port, struct domain_d sas_put_device(dev); } -void sas_destruct_devices(struct asd_sas_port *port) +static void sas_destruct_devices(struct work_struct *work) { struct domain_device *dev, *n; + struct sas_discovery_event *ev = to_sas_discovery_event(work); + struct asd_sas_port *port = ev->port; + + clear_bit(DISCE_DESTRUCT, &port->disc.pending); list_for_each_entry_safe(dev, n, &port->destroy_list, disco_list_node) { list_del_init(&dev->disco_list_node); @@ -370,16 +379,6 @@ void sas_destruct_devices(struct asd_sas_port *port) } } -static void sas_destruct_ports(struct asd_sas_port *port) -{ - struct sas_port *sas_port, *p; - - list_for_each_entry_safe(sas_port, p, &port->sas_port_del_list, del_list) { - list_del_init(&sas_port->del_list); - sas_port_delete(sas_port); - } -} - void sas_unregister_dev(struct asd_sas_port *port, struct domain_device *dev) { if (!test_bit(SAS_DEV_DESTROY, &dev->state) && @@ -394,6 +393,7 @@ void sas_unregister_dev(struct asd_sas_port *port, struct domain_device *dev) if (!test_and_set_bit(SAS_DEV_DESTROY, &dev->state)) { sas_rphy_unlink(dev->rphy); list_move_tail(&dev->disco_list_node, &port->destroy_list); + sas_discover_event(dev->port, DISCE_DESTRUCT); } } @@ -499,8 +499,6 @@ static void sas_discover_domain(struct work_struct *work) port->port_dev = NULL; } - sas_probe_devices(port); - SAS_DPRINTK("DONE DISCOVERY on port %d, pid:%d, result:%d\n", port->id, task_pid_nr(current), error); } @@ -534,10 +532,6 @@ static void sas_revalidate_domain(struct work_struct *work) port->id, task_pid_nr(current), res); out: mutex_unlock(&ha->disco_mutex); - - sas_destruct_devices(port); - sas_destruct_ports(port); - sas_probe_devices(port); } /* ---------- Events ---------- */ @@ -593,8 +587,10 @@ void sas_init_disc(struct sas_discovery *disc, struct asd_sas_port *port) static const work_func_t sas_event_fns[DISC_NUM_EVENTS] = { [DISCE_DISCOVER_DOMAIN] = sas_discover_domain, [DISCE_REVALIDATE_DOMAIN] = sas_revalidate_domain, + [DISCE_PROBE] = sas_probe_devices, [DISCE_SUSPEND] = sas_suspend_devices, [DISCE_RESUME] = sas_resume_devices, + [DISCE_DESTRUCT] = sas_destruct_devices, }; disc->pending = 0; diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index 84df6cf46760..f77d72f01da9 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c @@ -1946,8 +1946,7 @@ static void sas_unregister_devs_sas_addr(struct domain_device *parent, sas_port_delete_phy(phy->port, phy->phy); sas_device_set_phy(found, phy->port); if (phy->port->num_phys == 0) - list_add_tail(&phy->port->del_list, - &parent->port->sas_port_del_list); + sas_port_delete(phy->port); phy->port = NULL; } } @@ -2157,7 +2156,7 @@ int sas_ex_revalidate_domain(struct domain_device *port_dev) struct domain_device *dev = NULL; res = sas_find_bcast_dev(port_dev, &dev); - if (res == 0 && dev) { + while (res == 0 && dev) { struct expander_device *ex = &dev->ex_dev; int i = 0, phy_id; @@ -2169,6 +2168,9 @@ int sas_ex_revalidate_domain(struct domain_device *port_dev) res = sas_rediscover(dev, phy_id); i = phy_id + 1; } while (i < ex->num_phys); + + dev = NULL; + res = sas_find_bcast_dev(port_dev, &dev); } return res; } diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h index f3449fde9c5f..c07e08136491 100644 --- a/drivers/scsi/libsas/sas_internal.h +++ b/drivers/scsi/libsas/sas_internal.h @@ -98,7 +98,6 @@ int sas_try_ata_reset(struct asd_sas_phy *phy); void sas_hae_reset(struct work_struct *work); void sas_free_device(struct kref *kref); -void sas_destruct_devices(struct asd_sas_port *port); #ifdef CONFIG_SCSI_SAS_HOST_SMP extern void sas_smp_host_handler(struct bsg_job *job, struct Scsi_Host *shost); diff --git a/drivers/scsi/libsas/sas_port.c b/drivers/scsi/libsas/sas_port.c index 5d3244c8f280..d3c5297c6c89 100644 --- a/drivers/scsi/libsas/sas_port.c +++ b/drivers/scsi/libsas/sas_port.c @@ -66,7 +66,6 @@ static void sas_resume_port(struct asd_sas_phy *phy) rc = sas_notify_lldd_dev_found(dev); if (rc) { sas_unregister_dev(port, dev); - sas_destruct_devices(port); continue; } @@ -220,7 +219,6 @@ void sas_deform_port(struct asd_sas_phy *phy, int gone) if (port->num_phys == 1) { sas_unregister_domain_devices(port, gone); - sas_destruct_devices(port); sas_port_delete(port->port); port->port = NULL; } else { @@ -325,7 +323,6 @@ static void sas_init_port(struct asd_sas_port *port, INIT_LIST_HEAD(&port->dev_list); INIT_LIST_HEAD(&port->disco_list); INIT_LIST_HEAD(&port->destroy_list); - INIT_LIST_HEAD(&port->sas_port_del_list); spin_lock_init(&port->phy_list_lock); INIT_LIST_HEAD(&port->phy_list); port->ha = sas_ha; diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 1b1cf9eff3b5..a966d281dedc 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -87,8 +87,10 @@ enum discover_event { DISCE_DISCOVER_DOMAIN = 0U, DISCE_REVALIDATE_DOMAIN = 1, DISCE_PORT_GONE = 2, + DISCE_PROBE = 3, DISCE_SUSPEND = 4, DISCE_RESUME = 5, + DISCE_DESTRUCT = 6, DISC_NUM_EVENTS = 7, }; @@ -267,7 +269,6 @@ struct asd_sas_port { struct list_head dev_list; struct list_head disco_list; struct list_head destroy_list; - struct list_head sas_port_del_list; enum sas_linkrate linkrate; struct sas_work work; diff --git a/include/scsi/scsi_transport_sas.h b/include/scsi/scsi_transport_sas.h index 05ec927a3c72..62895b405933 100644 --- a/include/scsi/scsi_transport_sas.h +++ b/include/scsi/scsi_transport_sas.h @@ -156,7 +156,6 @@ struct sas_port { struct mutex phy_list_mutex; struct list_head phy_list; - struct list_head del_list; /* libsas only */ }; #define dev_to_sas_port(d) \ From 583bcbc024f6bf8daa266f4f71b99e9d6e78c40b Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Fri, 10 Jul 2020 15:23:19 +0200 Subject: [PATCH 472/592] random32: update the net random state on interrupt and activity commit f227e3ec3b5cad859ad15666874405e8c1bbc1d4 upstream. This modifies the first 32 bits out of the 128 bits of a random CPU's net_rand_state on interrupt or CPU activity to complicate remote observations that could lead to guessing the network RNG's internal state. Note that depending on some network devices' interrupt rate moderation or binding, this re-seeding might happen on every packet or even almost never. In addition, with NOHZ some CPUs might not even get timer interrupts, leaving their local state rarely updated, while they are running networked processes making use of the random state. For this reason, we also perform this update in update_process_times() in order to at least update the state when there is user or system activity, since it's the only case we care about. Reported-by: Amit Klein Suggested-by: Linus Torvalds Cc: Eric Dumazet Cc: "Jason A. Donenfeld" Cc: Andy Lutomirski Cc: Kees Cook Cc: Thomas Gleixner Cc: Peter Zijlstra Cc: Signed-off-by: Willy Tarreau Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/char/random.c | 1 + include/linux/random.h | 3 +++ kernel/time/timer.c | 8 ++++++++ lib/random32.c | 2 +- 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/char/random.c b/drivers/char/random.c index 868d2620b7ac..b202f66fc383 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1246,6 +1246,7 @@ void add_interrupt_randomness(int irq, int irq_flags) fast_mix(fast_pool); add_interrupt_bench(cycles); + this_cpu_add(net_rand_state.s1, fast_pool->pool[cycles & 3]); if (unlikely(crng_init == 0)) { if ((fast_pool->count >= 64) && diff --git a/include/linux/random.h b/include/linux/random.h index 4024f7d9c77d..283b37065e1c 100644 --- a/include/linux/random.h +++ b/include/linux/random.h @@ -9,6 +9,7 @@ #include #include +#include #include @@ -116,6 +117,8 @@ struct rnd_state { __u32 s1, s2, s3, s4; }; +DECLARE_PER_CPU(struct rnd_state, net_rand_state) __latent_entropy; + u32 prandom_u32_state(struct rnd_state *state); void prandom_bytes_state(struct rnd_state *state, void *buf, size_t nbytes); void prandom_seed_full_state(struct rnd_state __percpu *pcpu_state); diff --git a/kernel/time/timer.c b/kernel/time/timer.c index 7e88c87c3554..d4bc272e03ee 100644 --- a/kernel/time/timer.c +++ b/kernel/time/timer.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -1595,6 +1596,13 @@ void update_process_times(int user_tick) scheduler_tick(); if (IS_ENABLED(CONFIG_POSIX_TIMERS)) run_posix_cpu_timers(p); + + /* The current CPU might make use of net randoms without receiving IRQs + * to renew them often enough. Let's update the net_rand_state from a + * non-constant value that's not affine to the number of calls to make + * sure it's updated when there's some activity (we don't care in idle). + */ + this_cpu_add(net_rand_state.s1, rol32(jiffies, 24) + user_tick); } /** diff --git a/lib/random32.c b/lib/random32.c index 0a90cb0e0fb6..bab8adfd7014 100644 --- a/lib/random32.c +++ b/lib/random32.c @@ -48,7 +48,7 @@ static inline void prandom_state_selftest(void) } #endif -static DEFINE_PER_CPU(struct rnd_state, net_rand_state) __latent_entropy; +DEFINE_PER_CPU(struct rnd_state, net_rand_state) __latent_entropy; /** * prandom_u32_state - seeded pseudo-random number generator. From eec3b3c667ae875a3d88b7be8f659a1a076b0c3b Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Thu, 30 Jul 2020 22:05:01 +0300 Subject: [PATCH 473/592] ARM: percpu.h: fix build error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit aa54ea903abb02303bf55855fb51e3fcee135d70 upstream. Fix build error for the case: defined(CONFIG_SMP) && !defined(CONFIG_CPU_V6) config: keystone_defconfig CC arch/arm/kernel/signal.o In file included from ../include/linux/random.h:14, from ../arch/arm/kernel/signal.c:8: ../arch/arm/include/asm/percpu.h: In function ‘__my_cpu_offset’: ../arch/arm/include/asm/percpu.h:29:34: error: ‘current_stack_pointer’ undeclared (first use in this function); did you mean ‘user_stack_pointer’? : "Q" (*(const unsigned long *)current_stack_pointer)); ^~~~~~~~~~~~~~~~~~~~~ user_stack_pointer Fixes: f227e3ec3b5c ("random32: update the net random state on interrupt and activity") Signed-off-by: Grygorii Strashko Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- arch/arm/include/asm/percpu.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/include/asm/percpu.h b/arch/arm/include/asm/percpu.h index a89b4076cde4..72821b4721ad 100644 --- a/arch/arm/include/asm/percpu.h +++ b/arch/arm/include/asm/percpu.h @@ -16,6 +16,8 @@ #ifndef _ASM_ARM_PERCPU_H_ #define _ASM_ARM_PERCPU_H_ +#include + /* * Same as asm-generic/percpu.h, except that we store the per cpu offset * in the TPIDRPRW. TPIDRPRW only exists on V6K and V7 From 8de9a00bf997a62df8a2a1ba3d0d8eb73f55b463 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Thu, 30 Jul 2020 07:59:24 +0200 Subject: [PATCH 474/592] random: fix circular include dependency on arm64 after addition of percpu.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 1c9df907da83812e4f33b59d3d142c864d9da57f upstream. Daniel Díaz and Kees Cook independently reported that commit f227e3ec3b5c ("random32: update the net random state on interrupt and activity") broke arm64 due to a circular dependency on include files since the addition of percpu.h in random.h. The correct fix would definitely be to move all the prandom32 stuff out of random.h but for backporting, a smaller solution is preferred. This one replaces linux/percpu.h with asm/percpu.h, and this fixes the problem on x86_64, arm64, arm, and mips. Note that moving percpu.h around didn't change anything and that removing it entirely broke differently. When backporting, such options might still be considered if this patch fails to help. [ It turns out that an alternate fix seems to be to just remove the troublesome remove from the arm64 that causes the circular dependency. But we might as well do the whole belt-and-suspenders thing, and minimize inclusion in too. Either will fix the problem, and both are good changes. - Linus ] Reported-by: Daniel Díaz Reported-by: Kees Cook Tested-by: Marc Zyngier Fixes: f227e3ec3b5c Cc: Stephen Rothwell Signed-off-by: Willy Tarreau Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- include/linux/random.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/random.h b/include/linux/random.h index 283b37065e1c..5fcb0c42a8b9 100644 --- a/include/linux/random.h +++ b/include/linux/random.h @@ -9,7 +9,7 @@ #include #include -#include +#include #include From 8dacd74f7987c1e744e988cb12fd18ab1aa2d6e0 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 29 Jul 2020 19:11:00 -0700 Subject: [PATCH 475/592] random32: remove net_rand_state from the latent entropy gcc plugin commit 83bdc7275e6206f560d247be856bceba3e1ed8f2 upstream. It turns out that the plugin right now ends up being really unhappy about the change from 'static' to 'extern' storage that happened in commit f227e3ec3b5c ("random32: update the net random state on interrupt and activity"). This is probably a trivial fix for the latent_entropy plugin, but for now, just remove net_rand_state from the list of things the plugin worries about. Reported-by: Stephen Rothwell Cc: Emese Revfy Cc: Kees Cook Cc: Willy Tarreau Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- include/linux/random.h | 2 +- lib/random32.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/random.h b/include/linux/random.h index 5fcb0c42a8b9..02e7e797b19a 100644 --- a/include/linux/random.h +++ b/include/linux/random.h @@ -117,7 +117,7 @@ struct rnd_state { __u32 s1, s2, s3, s4; }; -DECLARE_PER_CPU(struct rnd_state, net_rand_state) __latent_entropy; +DECLARE_PER_CPU(struct rnd_state, net_rand_state); u32 prandom_u32_state(struct rnd_state *state); void prandom_bytes_state(struct rnd_state *state, void *buf, size_t nbytes); diff --git a/lib/random32.c b/lib/random32.c index bab8adfd7014..6e2c48ab8072 100644 --- a/lib/random32.c +++ b/lib/random32.c @@ -48,7 +48,7 @@ static inline void prandom_state_selftest(void) } #endif -DEFINE_PER_CPU(struct rnd_state, net_rand_state) __latent_entropy; +DEFINE_PER_CPU(struct rnd_state, net_rand_state); /** * prandom_u32_state - seeded pseudo-random number generator. From 35cd3649ad750a1c9ff579d8ad59ad624419205f Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 31 Jul 2020 07:51:14 +0200 Subject: [PATCH 476/592] random32: move the pseudo-random 32-bit definitions to prandom.h commit c0842fbc1b18c7a044e6ff3e8fa78bfa822c7d1a upstream. The addition of percpu.h to the list of includes in random.h revealed some circular dependencies on arm64 and possibly other platforms. This include was added solely for the pseudo-random definitions, which have nothing to do with the rest of the definitions in this file but are still there for legacy reasons. This patch moves the pseudo-random parts to linux/prandom.h and the percpu.h include with it, which is now guarded by _LINUX_PRANDOM_H and protected against recursive inclusion. A further cleanup step would be to remove this from entirely, and make people who use the prandom infrastructure include just the new header file. That's a bit of a churn patch, but grepping for "prandom_" and "next_pseudo_random32" "struct rnd_state" should catch most users. But it turns out that that nice cleanup step is fairly painful, because a _lot_ of code currently seems to depend on the implicit include of , which can currently come in a lot of ways, including such fairly core headfers as . So the "nice cleanup" part may or may never happen. Fixes: 1c9df907da83 ("random: fix circular include dependency on arm64 after addition of percpu.h") Tested-by: Guenter Roeck Acked-by: Willy Tarreau Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- include/linux/prandom.h | 78 +++++++++++++++++++++++++++++++++++++++++ include/linux/random.h | 66 +++------------------------------- 2 files changed, 82 insertions(+), 62 deletions(-) create mode 100644 include/linux/prandom.h diff --git a/include/linux/prandom.h b/include/linux/prandom.h new file mode 100644 index 000000000000..aa16e6468f91 --- /dev/null +++ b/include/linux/prandom.h @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * include/linux/prandom.h + * + * Include file for the fast pseudo-random 32-bit + * generation. + */ +#ifndef _LINUX_PRANDOM_H +#define _LINUX_PRANDOM_H + +#include +#include + +u32 prandom_u32(void); +void prandom_bytes(void *buf, size_t nbytes); +void prandom_seed(u32 seed); +void prandom_reseed_late(void); + +struct rnd_state { + __u32 s1, s2, s3, s4; +}; + +DECLARE_PER_CPU(struct rnd_state, net_rand_state); + +u32 prandom_u32_state(struct rnd_state *state); +void prandom_bytes_state(struct rnd_state *state, void *buf, size_t nbytes); +void prandom_seed_full_state(struct rnd_state __percpu *pcpu_state); + +#define prandom_init_once(pcpu_state) \ + DO_ONCE(prandom_seed_full_state, (pcpu_state)) + +/** + * prandom_u32_max - returns a pseudo-random number in interval [0, ep_ro) + * @ep_ro: right open interval endpoint + * + * Returns a pseudo-random number that is in interval [0, ep_ro). Note + * that the result depends on PRNG being well distributed in [0, ~0U] + * u32 space. Here we use maximally equidistributed combined Tausworthe + * generator, that is, prandom_u32(). This is useful when requesting a + * random index of an array containing ep_ro elements, for example. + * + * Returns: pseudo-random number in interval [0, ep_ro) + */ +static inline u32 prandom_u32_max(u32 ep_ro) +{ + return (u32)(((u64) prandom_u32() * ep_ro) >> 32); +} + +/* + * Handle minimum values for seeds + */ +static inline u32 __seed(u32 x, u32 m) +{ + return (x < m) ? x + m : x; +} + +/** + * prandom_seed_state - set seed for prandom_u32_state(). + * @state: pointer to state structure to receive the seed. + * @seed: arbitrary 64-bit value to use as a seed. + */ +static inline void prandom_seed_state(struct rnd_state *state, u64 seed) +{ + u32 i = (seed >> 32) ^ (seed << 10) ^ seed; + + state->s1 = __seed(i, 2U); + state->s2 = __seed(i, 8U); + state->s3 = __seed(i, 16U); + state->s4 = __seed(i, 128U); +} + +/* Pseudo random number generator from numerical recipes. */ +static inline u32 next_pseudo_random32(u32 seed) +{ + return seed * 1664525 + 1013904223; +} + +#endif diff --git a/include/linux/random.h b/include/linux/random.h index 02e7e797b19a..8eda8c0cbba7 100644 --- a/include/linux/random.h +++ b/include/linux/random.h @@ -9,7 +9,6 @@ #include #include -#include #include @@ -108,63 +107,12 @@ declare_get_random_var_wait(long) unsigned long randomize_page(unsigned long start, unsigned long range); -u32 prandom_u32(void); -void prandom_bytes(void *buf, size_t nbytes); -void prandom_seed(u32 seed); -void prandom_reseed_late(void); - -struct rnd_state { - __u32 s1, s2, s3, s4; -}; - -DECLARE_PER_CPU(struct rnd_state, net_rand_state); - -u32 prandom_u32_state(struct rnd_state *state); -void prandom_bytes_state(struct rnd_state *state, void *buf, size_t nbytes); -void prandom_seed_full_state(struct rnd_state __percpu *pcpu_state); - -#define prandom_init_once(pcpu_state) \ - DO_ONCE(prandom_seed_full_state, (pcpu_state)) - -/** - * prandom_u32_max - returns a pseudo-random number in interval [0, ep_ro) - * @ep_ro: right open interval endpoint - * - * Returns a pseudo-random number that is in interval [0, ep_ro). Note - * that the result depends on PRNG being well distributed in [0, ~0U] - * u32 space. Here we use maximally equidistributed combined Tausworthe - * generator, that is, prandom_u32(). This is useful when requesting a - * random index of an array containing ep_ro elements, for example. - * - * Returns: pseudo-random number in interval [0, ep_ro) - */ -static inline u32 prandom_u32_max(u32 ep_ro) -{ - return (u32)(((u64) prandom_u32() * ep_ro) >> 32); -} - /* - * Handle minimum values for seeds + * This is designed to be standalone for just prandom + * users, but for now we include it from + * for legacy reasons. */ -static inline u32 __seed(u32 x, u32 m) -{ - return (x < m) ? x + m : x; -} - -/** - * prandom_seed_state - set seed for prandom_u32_state(). - * @state: pointer to state structure to receive the seed. - * @seed: arbitrary 64-bit value to use as a seed. - */ -static inline void prandom_seed_state(struct rnd_state *state, u64 seed) -{ - u32 i = (seed >> 32) ^ (seed << 10) ^ seed; - - state->s1 = __seed(i, 2U); - state->s2 = __seed(i, 8U); - state->s3 = __seed(i, 16U); - state->s4 = __seed(i, 128U); -} +#include #ifdef CONFIG_ARCH_RANDOM # include @@ -195,10 +143,4 @@ static inline bool arch_has_random_seed(void) } #endif -/* Pseudo random number generator from numerical recipes. */ -static inline u32 next_pseudo_random32(u32 seed) -{ - return seed * 1664525 + 1013904223; -} - #endif /* _LINUX_RANDOM_H */ From baf191c492c6592430ce684fb3464120d47d11f9 Mon Sep 17 00:00:00 2001 From: Jiang Ying Date: Wed, 5 Aug 2020 15:57:21 +0800 Subject: [PATCH 477/592] ext4: fix direct I/O read error This patch is used to fix ext4 direct I/O read error when the read size is not aligned with block size. Then, I will use a test to explain the error. (1) Make a file that is not aligned with block size: $dd if=/dev/zero of=./test.jar bs=1000 count=3 (2) I wrote a source file named "direct_io_read_file.c" as following: #include #include #include #include #include #include #include #define BUF_SIZE 1024 int main() { int fd; int ret; unsigned char *buf; ret = posix_memalign((void **)&buf, 512, BUF_SIZE); if (ret) { perror("posix_memalign failed"); exit(1); } fd = open("./test.jar", O_RDONLY | O_DIRECT, 0755); if (fd < 0){ perror("open ./test.jar failed"); exit(1); } do { ret = read(fd, buf, BUF_SIZE); printf("ret=%d\n",ret); if (ret < 0) { perror("write test.jar failed"); } } while (ret > 0); free(buf); close(fd); } (3) Compile the source file: $gcc direct_io_read_file.c -D_GNU_SOURCE (4) Run the test program: $./a.out The result is as following: ret=1024 ret=1024 ret=952 ret=-1 write test.jar failed: Invalid argument. I have tested this program on XFS filesystem, XFS does not have this problem, because XFS use iomap_dio_rw() to do direct I/O read. And the comparing between read offset and file size is done in iomap_dio_rw(), the code is as following: if (pos < size) { retval = filemap_write_and_wait_range(mapping, pos, pos + iov_length(iov, nr_segs) - 1); if (!retval) { retval = mapping->a_ops->direct_IO(READ, iocb, iov, pos, nr_segs); } ... } ...only when "pos < size", direct I/O can be done, or 0 will be return. I have tested the fix patch on Ext4, it is up to the mustard of EINVAL in man2(read) as following: #include ssize_t read(int fd, void *buf, size_t count); EINVAL fd is attached to an object which is unsuitable for reading; or the file was opened with the O_DIRECT flag, and either the address specified in buf, the value specified in count, or the current file offset is not suitably aligned. So I think this patch can be applied to fix ext4 direct I/O error. However Ext4 introduces direct I/O read using iomap infrastructure on kernel 5.5, the patch is commit ("ext4: introduce direct I/O read using iomap infrastructure"), then Ext4 will be the same as XFS, they all use iomap_dio_rw() to do direct I/O read. So this problem does not exist on kernel 5.5 for Ext4. >From above description, we can see this problem exists on all the kernel versions between kernel 3.14 and kernel 5.4. It will cause the Applications to fail to read. For example, when the search service downloads a new full index file, the search engine is loading the previous index file and is processing the search request, it can not use buffer io that may squeeze the previous index file in use from pagecache, so the serch service must use direct I/O read. Please apply this patch on these kernel versions, or please use the method on kernel 5.5 to fix this problem. Fixes: 9fe55eea7e4b ("Fix race when checking i_size on direct i/o read") Reviewed-by: Jan Kara Co-developed-by: Wang Long Signed-off-by: Wang Long Signed-off-by: Jiang Ying Signed-off-by: Greg Kroah-Hartman --- fs/ext4/inode.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 5f03a4fabeaa..845b8620afcf 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -3794,6 +3794,11 @@ static ssize_t ext4_direct_IO_read(struct kiocb *iocb, struct iov_iter *iter) struct inode *inode = mapping->host; size_t count = iov_iter_count(iter); ssize_t ret; + loff_t offset = iocb->ki_pos; + loff_t size = i_size_read(inode); + + if (offset >= size) + return 0; /* * Shared inode_lock is enough for us - it protects against concurrent From e4efec8c28bce3be6078657f0846e59ccded593b Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 3 Oct 2017 19:14:38 +0100 Subject: [PATCH 478/592] ARM: 8702/1: head-common.S: Clear lr before jumping to start_kernel() commit 59b6359dd92d18f5dc04b14a4c926fa08ab66f7c upstream. If CONFIG_DEBUG_LOCK_ALLOC=y, the kernel log is spammed with a few hundred identical messages: unwind: Unknown symbol address c0800300 unwind: Index not found c0800300 c0800300 is the return address from the last subroutine call (to __memzero()) in __mmap_switched(). Apparently having this address in the link register confuses the unwinder. To fix this, reset the link register to zero before jumping to start_kernel(). Fixes: 9520b1a1b5f7a348 ("ARM: head-common.S: speed up startup code") Suggested-by: Ard Biesheuvel Signed-off-by: Geert Uytterhoeven Acked-by: Nicolas Pitre Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman Signed-off-by: Nick Desaulniers --- arch/arm/kernel/head-common.S | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S index 7e662bdd5cb3..932b2244e709 100644 --- a/arch/arm/kernel/head-common.S +++ b/arch/arm/kernel/head-common.S @@ -101,6 +101,7 @@ __mmap_switched: str r2, [r6] @ Save atags pointer cmp r7, #0 strne r0, [r7] @ Save control register values + mov lr, #0 b start_kernel ENDPROC(__mmap_switched) From 14b58326976de6ef3998eefec1dd7f8b38b97a75 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 7 Aug 2020 09:38:42 +0200 Subject: [PATCH 479/592] Linux 4.14.193 Tested-by: Shuah Khan Signed-off-by: Greg Kroah-Hartman --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 60570fad811e..b30927f29e2b 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 VERSION = 4 PATCHLEVEL = 14 -SUBLEVEL = 192 +SUBLEVEL = 193 EXTRAVERSION = NAME = Petit Gorille From a6de041df69bcfd8f6e184001c191cfa8da36de8 Mon Sep 17 00:00:00 2001 From: Pragaspathi Thilagaraj Date: Thu, 23 Jul 2020 00:18:23 +0530 Subject: [PATCH 480/592] qcacld-3.0: Flush pmksa cache for SAP when SAP stop In certain case, the active SAP interface will be deleted by __wlan_hdd_del_virtual_intf by upper layer. In that case, Driver should flush pmksa in SAP cache. Change-Id: I9a152df7a4c27aef82664f039fbca18259d6b63a CRs-Fixed: 2635424 --- core/hdd/src/wlan_hdd_main.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 87ba68553d0c..a14b66a171e2 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -6308,6 +6308,14 @@ QDF_STATUS hdd_stop_adapter_ext(struct hdd_context *hdd_ctx, /* Diassociate with all the peers before stop ap post */ if (test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags)) wlan_hdd_del_station(adapter); + + qdf_ret_status = + sme_roam_del_pmkid_from_cache(hdd_ctx->mac_handle, + adapter->session_id, + NULL, true); + if (QDF_IS_STATUS_ERROR(qdf_ret_status)) + hdd_err("Cannot flush PMKSA Cache"); + /* Flush IPA exception path packets */ sap_config = &adapter->session.ap.sap_config; if (sap_config) From 8db9bad289815e10ff3b0a6ee3625f689b10f763 Mon Sep 17 00:00:00 2001 From: Martijn Coenen Date: Wed, 13 May 2020 15:38:35 +0200 Subject: [PATCH 481/592] BACKPORT: loop: Call loop_config_discard() only after new config is applied loop_set_status() calls loop_config_discard() to configure discard for the loop device; however, the discard configuration depends on whether the loop device uses encryption, and when we call it the encryption configuration has not been updated yet. Move the call down so we apply the correct discard configuration based on the new configuration. Signed-off-by: Martijn Coenen Reviewed-by: Christoph Hellwig Reviewed-by: Bob Liu Reviewed-by: Bart Van Assche Signed-off-by: Jens Axboe (cherry picked from commit 7c5014b0987a30e4989c90633c198aced454c0ec) Bug: 148607611 Change-Id: I77cb81b7c8038ebdb2d4cd6161c034a9e94cf516 --- drivers/block/loop.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index c518f9336ab3..1453c0ac085e 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -1167,8 +1167,6 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info) } } - loop_config_discard(lo); - memcpy(lo->lo_file_name, info->lo_file_name, LO_NAME_SIZE); memcpy(lo->lo_crypt_name, info->lo_crypt_name, LO_NAME_SIZE); lo->lo_file_name[LO_NAME_SIZE-1] = 0; @@ -1192,6 +1190,8 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info) lo->lo_key_owner = uid; } + loop_config_discard(lo); + /* update dio if lo_offset or transfer is changed */ __loop_update_dio(lo, lo->use_dio); From 6e0c4b058649df3377a19ab82a53657112172143 Mon Sep 17 00:00:00 2001 From: Martijn Coenen Date: Wed, 13 May 2020 15:38:36 +0200 Subject: [PATCH 482/592] BACKPORT: loop: Remove sector_t truncation checks sector_t is now always u64, so we don't need to check for truncation. Signed-off-by: Martijn Coenen Reviewed-by: Christoph Hellwig Signed-off-by: Jens Axboe (cherry picked from commit 083a6a50783ef54256eec3499e6575237e0e3d53) Bug: 148607611 Change-Id: I1db87e391aca6226d542c5b74e569184ec059073 --- drivers/block/loop.c | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 1453c0ac085e..3e8d5b81c031 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -225,24 +225,20 @@ static void __loop_update_dio(struct loop_device *lo, bool dio) blk_mq_unfreeze_queue(lo->lo_queue); } -static int +static void figure_loop_size(struct loop_device *lo, loff_t offset, loff_t sizelimit) { loff_t size = get_size(offset, sizelimit, lo->lo_backing_file); - sector_t x = (sector_t)size; struct block_device *bdev = lo->lo_device; - if (unlikely((loff_t)x != size)) - return -EFBIG; if (lo->lo_offset != offset) lo->lo_offset = offset; if (lo->lo_sizelimit != sizelimit) lo->lo_sizelimit = sizelimit; - set_capacity(lo->lo_disk, x); + set_capacity(lo->lo_disk, size); bd_set_size(bdev, (loff_t)get_capacity(bdev->bd_disk) << 9); /* let user-space know about the new size */ kobject_uevent(&disk_to_dev(bdev->bd_disk)->kobj, KOBJ_CHANGE); - return 0; } static inline int @@ -917,10 +913,8 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode, !file->f_op->write_iter) lo_flags |= LO_FLAGS_READ_ONLY; - error = -EFBIG; size = get_loop_size(lo, file); - if ((loff_t)(sector_t)size != size) - goto out_putf; + error = loop_prepare_queue(lo); if (error) goto out_putf; @@ -1161,10 +1155,7 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info) lo->lo_device->bd_inode->i_mapping->nrpages); goto exit; } - if (figure_loop_size(lo, info->lo_offset, info->lo_sizelimit)) { - err = -EFBIG; - goto exit; - } + figure_loop_size(lo, info->lo_offset, info->lo_sizelimit); } memcpy(lo->lo_file_name, info->lo_file_name, LO_NAME_SIZE); @@ -1363,7 +1354,9 @@ static int loop_set_capacity(struct loop_device *lo) if (unlikely(lo->lo_state != Lo_bound)) return -ENXIO; - return figure_loop_size(lo, lo->lo_offset, lo->lo_sizelimit); + figure_loop_size(lo, lo->lo_offset, lo->lo_sizelimit); + + return 0; } static int loop_set_dio(struct loop_device *lo, unsigned long arg) From 88bd1b944fabf68be2ee7395c5d976c948f74146 Mon Sep 17 00:00:00 2001 From: Martijn Coenen Date: Wed, 13 May 2020 15:38:37 +0200 Subject: [PATCH 483/592] BACKPORT: loop: Factor out setting loop device size This code is used repeatedly. Signed-off-by: Martijn Coenen Reviewed-by: Christoph Hellwig Signed-off-by: Jens Axboe (cherry picked from commit 5795b6f5607f7e4db62ddea144727780cb351a9b) Bug: 148607611 Change-Id: I332d05033e13b6c9f75f9d959a4682135bd6c53c --- drivers/block/loop.c | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 3e8d5b81c031..d062754bdb44 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -225,20 +225,35 @@ static void __loop_update_dio(struct loop_device *lo, bool dio) blk_mq_unfreeze_queue(lo->lo_queue); } +/** + * loop_set_size() - sets device size and notifies userspace + * @lo: struct loop_device to set the size for + * @size: new size of the loop device + * + * Callers must validate that the size passed into this function fits into + * a sector_t, eg using loop_validate_size() + */ +static void loop_set_size(struct loop_device *lo, loff_t size) +{ + struct block_device *bdev = lo->lo_device; + + set_capacity(lo->lo_disk, size); + bd_set_size(bdev, size << 9); + /* let user-space know about the new size */ + kobject_uevent(&disk_to_dev(bdev->bd_disk)->kobj, KOBJ_CHANGE); +} + static void figure_loop_size(struct loop_device *lo, loff_t offset, loff_t sizelimit) { loff_t size = get_size(offset, sizelimit, lo->lo_backing_file); - struct block_device *bdev = lo->lo_device; if (lo->lo_offset != offset) lo->lo_offset = offset; if (lo->lo_sizelimit != sizelimit) lo->lo_sizelimit = sizelimit; - set_capacity(lo->lo_disk, size); - bd_set_size(bdev, (loff_t)get_capacity(bdev->bd_disk) << 9); - /* let user-space know about the new size */ - kobject_uevent(&disk_to_dev(bdev->bd_disk)->kobj, KOBJ_CHANGE); + + loop_set_size(lo, size); } static inline int @@ -947,11 +962,8 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode, } loop_update_dio(lo); - set_capacity(lo->lo_disk, size); - bd_set_size(bdev, size << 9); loop_sysfs_init(lo); - /* let user-space know about the new size */ - kobject_uevent(&disk_to_dev(bdev->bd_disk)->kobj, KOBJ_CHANGE); + loop_set_size(lo, size); set_blocksize(bdev, S_ISBLK(inode->i_mode) ? block_size(inode->i_bdev) : PAGE_SIZE); From 12930c318ee0748db513940795f8348a639209fc Mon Sep 17 00:00:00 2001 From: Martijn Coenen Date: Wed, 13 May 2020 15:38:39 +0200 Subject: [PATCH 484/592] BACKPORT: loop: Refactor loop_set_status() size calculation figure_loop_size() calculates the loop size based on the passed in parameters, but at the same time it updates the offset and sizelimit parameters in the loop device configuration. That is a somewhat unexpected side effect of a function with this name, and it is only only needed by one of the two callers of this function - loop_set_status(). Move the lo_offset and lo_sizelimit assignment back into loop_set_status(), and use the newly factored out functions to validate and apply the newly calculated size. This allows us to get rid of figure_loop_size() in a follow-up commit. Signed-off-by: Martijn Coenen Reviewed-by: Christoph Hellwig Signed-off-by: Jens Axboe (cherry picked from commit b0bd158dd630bd47640e0e418c062cda1e0da5ad) Bug: 148607611 Change-Id: Ib8e10eb734c3f95f3c433c13012b378373336d10 --- drivers/block/loop.c | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index d062754bdb44..30816dc64067 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -248,11 +248,6 @@ figure_loop_size(struct loop_device *lo, loff_t offset, loff_t sizelimit) { loff_t size = get_size(offset, sizelimit, lo->lo_backing_file); - if (lo->lo_offset != offset) - lo->lo_offset = offset; - if (lo->lo_sizelimit != sizelimit) - lo->lo_sizelimit = sizelimit; - loop_set_size(lo, size); } @@ -1115,6 +1110,7 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info) int err; struct loop_func_table *xfer; kuid_t uid = current_uid(); + bool size_changed = false; if (lo->lo_encrypt_key_size && !uid_eq(lo->lo_key_owner, uid) && @@ -1127,6 +1123,7 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info) if (lo->lo_offset != info->lo_offset || lo->lo_sizelimit != info->lo_sizelimit) { + size_changed = true; sync_blockdev(lo->lo_device); invalidate_bdev(lo->lo_device); } @@ -1134,6 +1131,15 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info) /* I/O need to be drained during transfer transition */ blk_mq_freeze_queue(lo->lo_queue); + if (size_changed && lo->lo_device->bd_inode->i_mapping->nrpages) { + /* If any pages were dirtied after kill_bdev(), try again */ + err = -EAGAIN; + pr_warn("%s: loop%d (%s) has still dirty pages (nrpages=%lu)\n", + __func__, lo->lo_number, lo->lo_file_name, + lo->lo_device->bd_inode->i_mapping->nrpages); + goto exit; + } + err = loop_release_xfer(lo); if (err) goto exit; @@ -1157,19 +1163,6 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info) if (err) goto exit; - if (lo->lo_offset != info->lo_offset || - lo->lo_sizelimit != info->lo_sizelimit) { - /* kill_bdev should have truncated all the pages */ - if (lo->lo_device->bd_inode->i_mapping->nrpages) { - err = -EAGAIN; - pr_warn("%s: loop%d (%s) has still dirty pages (nrpages=%lu)\n", - __func__, lo->lo_number, lo->lo_file_name, - lo->lo_device->bd_inode->i_mapping->nrpages); - goto exit; - } - figure_loop_size(lo, info->lo_offset, info->lo_sizelimit); - } - memcpy(lo->lo_file_name, info->lo_file_name, LO_NAME_SIZE); memcpy(lo->lo_crypt_name, info->lo_crypt_name, LO_NAME_SIZE); lo->lo_file_name[LO_NAME_SIZE-1] = 0; @@ -1193,6 +1186,12 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info) lo->lo_key_owner = uid; } + if (size_changed) { + loff_t new_size = get_size(lo->lo_offset, lo->lo_sizelimit, + lo->lo_backing_file); + loop_set_size(lo, new_size); + } + loop_config_discard(lo); /* update dio if lo_offset or transfer is changed */ From f0d239341ff6045a0ba575cd5a52dc3cb9bcae9d Mon Sep 17 00:00:00 2001 From: Martijn Coenen Date: Wed, 13 May 2020 15:38:40 +0200 Subject: [PATCH 485/592] BACKPORT: loop: Remove figure_loop_size() This function was now only used by loop_set_capacity(). Just open code the remaining code in the caller instead. Signed-off-by: Martijn Coenen Reviewed-by: Christoph Hellwig Signed-off-by: Jens Axboe (cherry picked from commit 0a6ed1b5ff6757f11ad2d57906ceb40488a5ee52) Bug: 148607611 Change-Id: Icc5ef56a5f0264b9bfa15fbbe8062a74a59d88cb --- drivers/block/loop.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 30816dc64067..043f62a0fca2 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -243,14 +243,6 @@ static void loop_set_size(struct loop_device *lo, loff_t size) kobject_uevent(&disk_to_dev(bdev->bd_disk)->kobj, KOBJ_CHANGE); } -static void -figure_loop_size(struct loop_device *lo, loff_t offset, loff_t sizelimit) -{ - loff_t size = get_size(offset, sizelimit, lo->lo_backing_file); - - loop_set_size(lo, size); -} - static inline int lo_do_transfer(struct loop_device *lo, int cmd, struct page *rpage, unsigned roffs, @@ -1163,6 +1155,8 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info) if (err) goto exit; + lo->lo_offset = info->lo_offset; + lo->lo_sizelimit = info->lo_sizelimit; memcpy(lo->lo_file_name, info->lo_file_name, LO_NAME_SIZE); memcpy(lo->lo_crypt_name, info->lo_crypt_name, LO_NAME_SIZE); lo->lo_file_name[LO_NAME_SIZE-1] = 0; @@ -1362,10 +1356,13 @@ loop_get_status64(struct loop_device *lo, struct loop_info64 __user *arg) { static int loop_set_capacity(struct loop_device *lo) { + loff_t size; + if (unlikely(lo->lo_state != Lo_bound)) return -ENXIO; - figure_loop_size(lo, lo->lo_offset, lo->lo_sizelimit); + size = get_loop_size(lo, lo->lo_backing_file); + loop_set_size(lo, size); return 0; } From 3104d60f63bbda739005b4e04e5809ce05a45019 Mon Sep 17 00:00:00 2001 From: Martijn Coenen Date: Wed, 13 May 2020 15:38:41 +0200 Subject: [PATCH 486/592] BACKPORT: loop: Factor out configuring loop from status Factor out this code into a separate function, so it can be reused by other code more easily. Signed-off-by: Martijn Coenen Reviewed-by: Christoph Hellwig Signed-off-by: Jens Axboe (cherry picked from commit 0c3796c244598122a5d59d56f30d19390096817f) Bug: 148607611 Change-Id: I6bb8054a3963ba67bb44b07010d00ee53dbfef81 --- drivers/block/loop.c | 94 +++++++++++++++++++++++++++----------------- 1 file changed, 57 insertions(+), 37 deletions(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 043f62a0fca2..c9911e6fe06d 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -1096,64 +1096,43 @@ static int loop_clr_fd(struct loop_device *lo) return 0; } +/** + * loop_set_status_from_info - configure device from loop_info + * @lo: struct loop_device to configure + * @info: struct loop_info64 to configure the device with + * + * Configures the loop device parameters according to the passed + * in loop_info64 configuration. + */ static int -loop_set_status(struct loop_device *lo, const struct loop_info64 *info) +loop_set_status_from_info(struct loop_device *lo, + const struct loop_info64 *info) { int err; struct loop_func_table *xfer; kuid_t uid = current_uid(); - bool size_changed = false; - if (lo->lo_encrypt_key_size && - !uid_eq(lo->lo_key_owner, uid) && - !capable(CAP_SYS_ADMIN)) - return -EPERM; - if (lo->lo_state != Lo_bound) - return -ENXIO; if ((unsigned int) info->lo_encrypt_key_size > LO_KEY_SIZE) return -EINVAL; - if (lo->lo_offset != info->lo_offset || - lo->lo_sizelimit != info->lo_sizelimit) { - size_changed = true; - sync_blockdev(lo->lo_device); - invalidate_bdev(lo->lo_device); - } - - /* I/O need to be drained during transfer transition */ - blk_mq_freeze_queue(lo->lo_queue); - - if (size_changed && lo->lo_device->bd_inode->i_mapping->nrpages) { - /* If any pages were dirtied after kill_bdev(), try again */ - err = -EAGAIN; - pr_warn("%s: loop%d (%s) has still dirty pages (nrpages=%lu)\n", - __func__, lo->lo_number, lo->lo_file_name, - lo->lo_device->bd_inode->i_mapping->nrpages); - goto exit; - } - err = loop_release_xfer(lo); if (err) - goto exit; + return err; if (info->lo_encrypt_type) { unsigned int type = info->lo_encrypt_type; - if (type >= MAX_LO_CRYPT) { - err = -EINVAL; - goto exit; - } + if (type >= MAX_LO_CRYPT) + return -EINVAL; xfer = xfer_funcs[type]; - if (xfer == NULL) { - err = -EINVAL; - goto exit; - } + if (xfer == NULL) + return -EINVAL; } else xfer = NULL; err = loop_init_xfer(lo, xfer, info); if (err) - goto exit; + return err; lo->lo_offset = info->lo_offset; lo->lo_sizelimit = info->lo_sizelimit; @@ -1180,6 +1159,47 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info) lo->lo_key_owner = uid; } + return 0; +} + +static int +loop_set_status(struct loop_device *lo, const struct loop_info64 *info) +{ + int err; + kuid_t uid = current_uid(); + bool size_changed = false; + + if (lo->lo_encrypt_key_size && + !uid_eq(lo->lo_key_owner, uid) && + !capable(CAP_SYS_ADMIN)) + return -EPERM; + if (lo->lo_state != Lo_bound) { + return -ENXIO; + } + + if (lo->lo_offset != info->lo_offset || + lo->lo_sizelimit != info->lo_sizelimit) { + size_changed = true; + sync_blockdev(lo->lo_device); + invalidate_bdev(lo->lo_device); + } + + /* I/O need to be drained during transfer transition */ + blk_mq_freeze_queue(lo->lo_queue); + + if (size_changed && lo->lo_device->bd_inode->i_mapping->nrpages) { + /* If any pages were dirtied after kill_bdev(), try again */ + err = -EAGAIN; + pr_warn("%s: loop%d (%s) has still dirty pages (nrpages=%lu)\n", + __func__, lo->lo_number, lo->lo_file_name, + lo->lo_device->bd_inode->i_mapping->nrpages); + goto exit; + } + + err = loop_set_status_from_info(lo, info); + if (err) + goto exit; + if (size_changed) { loff_t new_size = get_size(lo->lo_offset, lo->lo_sizelimit, lo->lo_backing_file); From e25cf72f82f02a9b77e8e6387d0a00af5b618d27 Mon Sep 17 00:00:00 2001 From: Martijn Coenen Date: Wed, 13 May 2020 15:38:42 +0200 Subject: [PATCH 487/592] BACKPORT: loop: Move loop_set_status_from_info() and friends up So we can use it without forward declaration. This is a separate commit to make it easier to verify that this is just a move, without functional modifications. Signed-off-by: Martijn Coenen Reviewed-by: Christoph Hellwig Signed-off-by: Jens Axboe (cherry picked from commit 62ab466ca881fe200c21aa74b65f8bd83ec482dc) Bug: 148607611 Change-Id: I8c68ebbe65cbec476f9f2d4c1d60eb343e88bb56 --- drivers/block/loop.c | 206 +++++++++++++++++++++---------------------- 1 file changed, 103 insertions(+), 103 deletions(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index c9911e6fe06d..0074e8328d5a 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -882,6 +882,109 @@ static int loop_prepare_queue(struct loop_device *lo) return 0; } +static int +loop_release_xfer(struct loop_device *lo) +{ + int err = 0; + struct loop_func_table *xfer = lo->lo_encryption; + + if (xfer) { + if (xfer->release) + err = xfer->release(lo); + lo->transfer = NULL; + lo->lo_encryption = NULL; + module_put(xfer->owner); + } + return err; +} + +static int +loop_init_xfer(struct loop_device *lo, struct loop_func_table *xfer, + const struct loop_info64 *i) +{ + int err = 0; + + if (xfer) { + struct module *owner = xfer->owner; + + if (!try_module_get(owner)) + return -EINVAL; + if (xfer->init) + err = xfer->init(lo, i); + if (err) + module_put(owner); + else + lo->lo_encryption = xfer; + } + return err; +} + +/** + * loop_set_status_from_info - configure device from loop_info + * @lo: struct loop_device to configure + * @info: struct loop_info64 to configure the device with + * + * Configures the loop device parameters according to the passed + * in loop_info64 configuration. + */ +static int +loop_set_status_from_info(struct loop_device *lo, + const struct loop_info64 *info) +{ + int err; + struct loop_func_table *xfer; + kuid_t uid = current_uid(); + + if ((unsigned int) info->lo_encrypt_key_size > LO_KEY_SIZE) + return -EINVAL; + + err = loop_release_xfer(lo); + if (err) + return err; + + if (info->lo_encrypt_type) { + unsigned int type = info->lo_encrypt_type; + + if (type >= MAX_LO_CRYPT) + return -EINVAL; + xfer = xfer_funcs[type]; + if (xfer == NULL) + return -EINVAL; + } else + xfer = NULL; + + err = loop_init_xfer(lo, xfer, info); + if (err) + return err; + + lo->lo_offset = info->lo_offset; + lo->lo_sizelimit = info->lo_sizelimit; + memcpy(lo->lo_file_name, info->lo_file_name, LO_NAME_SIZE); + memcpy(lo->lo_crypt_name, info->lo_crypt_name, LO_NAME_SIZE); + lo->lo_file_name[LO_NAME_SIZE-1] = 0; + lo->lo_crypt_name[LO_NAME_SIZE-1] = 0; + + if (!xfer) + xfer = &none_funcs; + lo->transfer = xfer->transfer; + lo->ioctl = xfer->ioctl; + + if ((lo->lo_flags & LO_FLAGS_AUTOCLEAR) != + (info->lo_flags & LO_FLAGS_AUTOCLEAR)) + lo->lo_flags ^= LO_FLAGS_AUTOCLEAR; + + lo->lo_encrypt_key_size = info->lo_encrypt_key_size; + lo->lo_init[0] = info->lo_init[0]; + lo->lo_init[1] = info->lo_init[1]; + if (info->lo_encrypt_key_size) { + memcpy(lo->lo_encrypt_key, info->lo_encrypt_key, + info->lo_encrypt_key_size); + lo->lo_key_owner = uid; + } + + return 0; +} + static int loop_set_fd(struct loop_device *lo, fmode_t mode, struct block_device *bdev, unsigned int arg) { @@ -975,43 +1078,6 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode, return error; } -static int -loop_release_xfer(struct loop_device *lo) -{ - int err = 0; - struct loop_func_table *xfer = lo->lo_encryption; - - if (xfer) { - if (xfer->release) - err = xfer->release(lo); - lo->transfer = NULL; - lo->lo_encryption = NULL; - module_put(xfer->owner); - } - return err; -} - -static int -loop_init_xfer(struct loop_device *lo, struct loop_func_table *xfer, - const struct loop_info64 *i) -{ - int err = 0; - - if (xfer) { - struct module *owner = xfer->owner; - - if (!try_module_get(owner)) - return -EINVAL; - if (xfer->init) - err = xfer->init(lo, i); - if (err) - module_put(owner); - else - lo->lo_encryption = xfer; - } - return err; -} - static int loop_clr_fd(struct loop_device *lo) { struct file *filp = lo->lo_backing_file; @@ -1096,72 +1162,6 @@ static int loop_clr_fd(struct loop_device *lo) return 0; } -/** - * loop_set_status_from_info - configure device from loop_info - * @lo: struct loop_device to configure - * @info: struct loop_info64 to configure the device with - * - * Configures the loop device parameters according to the passed - * in loop_info64 configuration. - */ -static int -loop_set_status_from_info(struct loop_device *lo, - const struct loop_info64 *info) -{ - int err; - struct loop_func_table *xfer; - kuid_t uid = current_uid(); - - if ((unsigned int) info->lo_encrypt_key_size > LO_KEY_SIZE) - return -EINVAL; - - err = loop_release_xfer(lo); - if (err) - return err; - - if (info->lo_encrypt_type) { - unsigned int type = info->lo_encrypt_type; - - if (type >= MAX_LO_CRYPT) - return -EINVAL; - xfer = xfer_funcs[type]; - if (xfer == NULL) - return -EINVAL; - } else - xfer = NULL; - - err = loop_init_xfer(lo, xfer, info); - if (err) - return err; - - lo->lo_offset = info->lo_offset; - lo->lo_sizelimit = info->lo_sizelimit; - memcpy(lo->lo_file_name, info->lo_file_name, LO_NAME_SIZE); - memcpy(lo->lo_crypt_name, info->lo_crypt_name, LO_NAME_SIZE); - lo->lo_file_name[LO_NAME_SIZE-1] = 0; - lo->lo_crypt_name[LO_NAME_SIZE-1] = 0; - - if (!xfer) - xfer = &none_funcs; - lo->transfer = xfer->transfer; - lo->ioctl = xfer->ioctl; - - if ((lo->lo_flags & LO_FLAGS_AUTOCLEAR) != - (info->lo_flags & LO_FLAGS_AUTOCLEAR)) - lo->lo_flags ^= LO_FLAGS_AUTOCLEAR; - - lo->lo_encrypt_key_size = info->lo_encrypt_key_size; - lo->lo_init[0] = info->lo_init[0]; - lo->lo_init[1] = info->lo_init[1]; - if (info->lo_encrypt_key_size) { - memcpy(lo->lo_encrypt_key, info->lo_encrypt_key, - info->lo_encrypt_key_size); - lo->lo_key_owner = uid; - } - - return 0; -} - static int loop_set_status(struct loop_device *lo, const struct loop_info64 *info) { From adf8c71b0f5f3ca13fd33fbac9c8bd98c265dde4 Mon Sep 17 00:00:00 2001 From: Martijn Coenen Date: Wed, 13 May 2020 15:38:43 +0200 Subject: [PATCH 488/592] BACKPORT: loop: Rework lo_ioctl() __user argument casting In preparation for a new ioctl that needs to copy_from_user(); makes the code easier to read as well. Signed-off-by: Martijn Coenen Reviewed-by: Christoph Hellwig Signed-off-by: Jens Axboe Bug: 148607611 (cherry picked from commit 571fae6e290d64a3e8132c455e7786c99c467ed1) Change-Id: If17eea1cc3ddbc9b37d7c11760685721765730d8 --- drivers/block/loop.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 0074e8328d5a..836e01d597af 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -1442,6 +1442,7 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) { struct loop_device *lo = bdev->bd_disk->private_data; + void __user *argp = (void __user *) arg; int err; mutex_lock_nested(&lo->lo_ctl_mutex, 1); @@ -1461,21 +1462,19 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode, case LOOP_SET_STATUS: err = -EPERM; if ((mode & FMODE_WRITE) || capable(CAP_SYS_ADMIN)) - err = loop_set_status_old(lo, - (struct loop_info __user *)arg); + err = loop_set_status_old(lo, argp); break; case LOOP_GET_STATUS: - err = loop_get_status_old(lo, (struct loop_info __user *) arg); + err = loop_get_status_old(lo, argp); /* loop_get_status() unlocks lo_ctl_mutex */ goto out_unlocked; case LOOP_SET_STATUS64: err = -EPERM; if ((mode & FMODE_WRITE) || capable(CAP_SYS_ADMIN)) - err = loop_set_status64(lo, - (struct loop_info64 __user *) arg); + err = loop_set_status64(lo, argp); break; case LOOP_GET_STATUS64: - err = loop_get_status64(lo, (struct loop_info64 __user *) arg); + err = loop_get_status64(lo, argp); /* loop_get_status() unlocks lo_ctl_mutex */ goto out_unlocked; case LOOP_SET_CAPACITY: From 3db6bf49d845e5e807931dd6c51fd7c312609741 Mon Sep 17 00:00:00 2001 From: Martijn Coenen Date: Wed, 13 May 2020 15:38:44 +0200 Subject: [PATCH 489/592] BACKPORT: loop: Clean up LOOP_SET_STATUS lo_flags handling LOOP_SET_STATUS(64) will actually allow some lo_flags to be modified; in particular, LO_FLAGS_AUTOCLEAR can be set and cleared, whereas LO_FLAGS_PARTSCAN can be set to request a partition scan. Make this explicit by updating the UAPI to include the flags that can be set/cleared using this ioctl. The implementation can then blindly take over the passed in flags, and use the previous flags for those flags that can't be set / cleared using LOOP_SET_STATUS. Signed-off-by: Martijn Coenen Reviewed-by: Christoph Hellwig Signed-off-by: Jens Axboe Bug: 148607611 (cherry picked from commit faf1d25440d6ad06d509dada4b6fe62fea844370) Change-Id: I90ff339bff3d6435810cfa8e8202ee4dc23e47c7 --- drivers/block/loop.c | 18 ++++++++++++------ include/uapi/linux/loop.h | 10 ++++++++-- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 836e01d597af..921c3b326ce9 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -969,9 +969,7 @@ loop_set_status_from_info(struct loop_device *lo, lo->transfer = xfer->transfer; lo->ioctl = xfer->ioctl; - if ((lo->lo_flags & LO_FLAGS_AUTOCLEAR) != - (info->lo_flags & LO_FLAGS_AUTOCLEAR)) - lo->lo_flags ^= LO_FLAGS_AUTOCLEAR; + lo->lo_flags = info->lo_flags; lo->lo_encrypt_key_size = info->lo_encrypt_key_size; lo->lo_init[0] = info->lo_init[0]; @@ -1167,6 +1165,7 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info) { int err; kuid_t uid = current_uid(); + int prev_lo_flags; bool size_changed = false; if (lo->lo_encrypt_key_size && @@ -1196,10 +1195,18 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info) goto exit; } + prev_lo_flags = lo->lo_flags; + err = loop_set_status_from_info(lo, info); if (err) goto exit; + /* Mask out flags that can't be set using LOOP_SET_STATUS. */ + lo->lo_flags &= ~LOOP_SET_STATUS_SETTABLE_FLAGS; + /* For those flags, use the previous values instead */ + lo->lo_flags |= prev_lo_flags & ~LOOP_SET_STATUS_SETTABLE_FLAGS; + /* For flags that can't be cleared, use previous values too */ + lo->lo_flags |= prev_lo_flags & ~LOOP_SET_STATUS_CLEARABLE_FLAGS; if (size_changed) { loff_t new_size = get_size(lo->lo_offset, lo->lo_sizelimit, lo->lo_backing_file); @@ -1214,9 +1221,8 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info) exit: blk_mq_unfreeze_queue(lo->lo_queue); - if (!err && (info->lo_flags & LO_FLAGS_PARTSCAN) && - !(lo->lo_flags & LO_FLAGS_PARTSCAN)) { - lo->lo_flags |= LO_FLAGS_PARTSCAN; + if (!err && (lo->lo_flags & LO_FLAGS_PARTSCAN) && + !(prev_lo_flags & LO_FLAGS_PARTSCAN)) { lo->lo_disk->flags &= ~GENHD_FL_NO_PART_SCAN; loop_reread_partitions(lo, lo->lo_device); } diff --git a/include/uapi/linux/loop.h b/include/uapi/linux/loop.h index 080a8df134ef..6b32fee80ce0 100644 --- a/include/uapi/linux/loop.h +++ b/include/uapi/linux/loop.h @@ -25,6 +25,12 @@ enum { LO_FLAGS_DIRECT_IO = 16, }; +/* LO_FLAGS that can be set using LOOP_SET_STATUS(64) */ +#define LOOP_SET_STATUS_SETTABLE_FLAGS (LO_FLAGS_AUTOCLEAR | LO_FLAGS_PARTSCAN) + +/* LO_FLAGS that can be cleared using LOOP_SET_STATUS(64) */ +#define LOOP_SET_STATUS_CLEARABLE_FLAGS (LO_FLAGS_AUTOCLEAR) + #include /* for __kernel_old_dev_t */ #include /* for __u64 */ @@ -37,7 +43,7 @@ struct loop_info { int lo_offset; int lo_encrypt_type; int lo_encrypt_key_size; /* ioctl w/o */ - int lo_flags; /* ioctl r/o */ + int lo_flags; char lo_name[LO_NAME_SIZE]; unsigned char lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */ unsigned long lo_init[2]; @@ -53,7 +59,7 @@ struct loop_info64 { __u32 lo_number; /* ioctl r/o */ __u32 lo_encrypt_type; __u32 lo_encrypt_key_size; /* ioctl w/o */ - __u32 lo_flags; /* ioctl r/o */ + __u32 lo_flags; __u8 lo_file_name[LO_NAME_SIZE]; __u8 lo_crypt_name[LO_NAME_SIZE]; __u8 lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */ From 2061c5856b6886554f01cce8b96b8f1595695e98 Mon Sep 17 00:00:00 2001 From: Martijn Coenen Date: Wed, 13 May 2020 15:38:45 +0200 Subject: [PATCH 490/592] BACKPORT: loop: Add LOOP_CONFIGURE ioctl This allows userspace to completely setup a loop device with a single ioctl, removing the in-between state where the device can be partially configured - eg the loop device has a backing file associated with it, but is reading from the wrong offset. Besides removing the intermediate state, another big benefit of this ioctl is that LOOP_SET_STATUS can be slow; the main reason for this slowness is that LOOP_SET_STATUS(64) calls blk_mq_freeze_queue() to freeze the associated queue; this requires waiting for RCU synchronization, which I've measured can take about 15-20ms on this device on average. In addition to doing what LOOP_SET_STATUS can do, LOOP_CONFIGURE can also be used to: - Set the correct block size immediately by setting loop_config.block_size (avoids LOOP_SET_BLOCK_SIZE) - Explicitly request direct I/O mode by setting LO_FLAGS_DIRECT_IO in loop_config.info.lo_flags (avoids LOOP_SET_DIRECT_IO) - Explicitly request read-only mode by setting LO_FLAGS_READ_ONLY in loop_config.info.lo_flags Here's setting up ~70 regular loop devices with an offset on an x86 Android device, using LOOP_SET_FD and LOOP_SET_STATUS: vsoc_x86:/system/apex # time for i in `seq 30 100`; do losetup -r -o 4096 /dev/block/loop$i com.android.adbd.apex; done 0m03.40s real 0m00.02s user 0m00.03s system Here's configuring ~70 devices in the same way, but using a modified losetup that uses the new LOOP_CONFIGURE ioctl: vsoc_x86:/system/apex # time for i in `seq 30 100`; do losetup -r -o 4096 /dev/block/loop$i com.android.adbd.apex; done 0m01.94s real 0m00.01s user 0m00.01s system Signed-off-by: Martijn Coenen Reviewed-by: Christoph Hellwig Signed-off-by: Jens Axboe (cherry picked from commit 3448914e8cc550ba792d4ccc74471d1ca4293aae) Bug: 148607611 Change-Id: I839ee9c9df8dbd9f4cc0fa5c8119c01abfcac1d9 --- drivers/block/loop.c | 92 ++++++++++++++++++++++++++++++--------- include/uapi/linux/loop.h | 21 +++++++++ 2 files changed, 93 insertions(+), 20 deletions(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 921c3b326ce9..2a520acbab38 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -225,6 +225,19 @@ static void __loop_update_dio(struct loop_device *lo, bool dio) blk_mq_unfreeze_queue(lo->lo_queue); } +/** + * loop_validate_block_size() - validates the passed in block size + * @bsize: size to validate + */ +static int +loop_validate_block_size(unsigned short bsize) +{ + if (bsize < 512 || bsize > PAGE_SIZE || !is_power_of_2(bsize)) + return -EINVAL; + + return 0; +} + /** * loop_set_size() - sets device size and notifies userspace * @lo: struct loop_device to set the size for @@ -983,21 +996,22 @@ loop_set_status_from_info(struct loop_device *lo, return 0; } -static int loop_set_fd(struct loop_device *lo, fmode_t mode, - struct block_device *bdev, unsigned int arg) +static int loop_configure(struct loop_device *lo, fmode_t mode, + struct block_device *bdev, + const struct loop_config *config) { struct file *file; struct inode *inode; struct address_space *mapping; - int lo_flags = 0; int error; loff_t size; + unsigned short bsize; /* This is safe, since we have a reference from open(). */ __module_get(THIS_MODULE); error = -EBADF; - file = fget(arg); + file = fget(config->fd); if (!file) goto out; @@ -1012,11 +1026,26 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode, mapping = file->f_mapping; inode = mapping->host; + size = get_loop_size(lo, file); + + if ((config->info.lo_flags & ~LOOP_CONFIGURE_SETTABLE_FLAGS) != 0) { + error = -EINVAL; + goto out_putf; + } + + if (config->block_size) { + error = loop_validate_block_size(config->block_size); + if (error) + goto out_putf; + } + + error = loop_set_status_from_info(lo, &config->info); + if (error) + goto out_putf; + if (!(file->f_mode & FMODE_WRITE) || !(mode & FMODE_WRITE) || !file->f_op->write_iter) - lo_flags |= LO_FLAGS_READ_ONLY; - - size = get_loop_size(lo, file); + lo->lo_flags |= LO_FLAGS_READ_ONLY; error = loop_prepare_queue(lo); if (error) @@ -1024,19 +1053,15 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode, error = 0; - set_device_ro(bdev, (lo_flags & LO_FLAGS_READ_ONLY) != 0); + set_device_ro(bdev, (lo->lo_flags & LO_FLAGS_READ_ONLY) != 0); - lo->use_dio = false; + lo->use_dio = lo->lo_flags & LO_FLAGS_DIRECT_IO; lo->lo_device = bdev; - lo->lo_flags = lo_flags; lo->lo_backing_file = file; - lo->transfer = NULL; - lo->ioctl = NULL; - lo->lo_sizelimit = 0; lo->old_gfp_mask = mapping_gfp_mask(mapping); mapping_set_gfp_mask(mapping, lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS)); - if (!(lo_flags & LO_FLAGS_READ_ONLY) && file->f_op->fsync) + if (!(lo->lo_flags & LO_FLAGS_READ_ONLY) && file->f_op->fsync) blk_queue_write_cache(lo->lo_queue, true, false); if (io_is_direct(lo->lo_backing_file) && inode->i_sb->s_bdev) { @@ -1053,8 +1078,13 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode, loop_sysfs_init(lo); loop_set_size(lo, size); - set_blocksize(bdev, S_ISBLK(inode->i_mode) ? - block_size(inode->i_bdev) : PAGE_SIZE); + if (config->block_size) + bsize = config->block_size; + else + bsize = S_ISBLK(inode->i_mode) ? + block_size(inode->i_bdev) : PAGE_SIZE; + + set_blocksize(bdev, bsize); lo->lo_state = Lo_bound; if (part_shift) @@ -1414,8 +1444,9 @@ static int loop_set_block_size(struct loop_device *lo, unsigned long arg) if (lo->lo_state != Lo_bound) return -ENXIO; - if (arg < 512 || arg > PAGE_SIZE || !is_power_of_2(arg)) - return -EINVAL; + err = loop_validate_block_size(arg); + if (err) + return err; if (lo->lo_queue->limits.logical_block_size == arg) return 0; @@ -1453,9 +1484,29 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode, mutex_lock_nested(&lo->lo_ctl_mutex, 1); switch (cmd) { - case LOOP_SET_FD: - err = loop_set_fd(lo, mode, bdev, arg); + case LOOP_SET_FD: { + /* + * Legacy case - pass in a zeroed out struct loop_config with + * only the file descriptor set , which corresponds with the + * default parameters we'd have used otherwise. + */ + struct loop_config config; + + memset(&config, 0, sizeof(config)); + config.fd = arg; + + err = loop_configure(lo, mode, bdev, &config); break; + } + case LOOP_CONFIGURE: { + struct loop_config config; + + if (copy_from_user(&config, argp, sizeof(config))) + return -EFAULT; + + err = loop_configure(lo, mode, bdev, &config); + break; + } case LOOP_CHANGE_FD: err = loop_change_fd(lo, bdev, arg); break; @@ -1650,6 +1701,7 @@ static int lo_compat_ioctl(struct block_device *bdev, fmode_t mode, case LOOP_CLR_FD: case LOOP_GET_STATUS64: case LOOP_SET_STATUS64: + case LOOP_CONFIGURE: arg = (unsigned long) compat_ptr(arg); case LOOP_SET_FD: case LOOP_CHANGE_FD: diff --git a/include/uapi/linux/loop.h b/include/uapi/linux/loop.h index 6b32fee80ce0..24a1c45bd1ae 100644 --- a/include/uapi/linux/loop.h +++ b/include/uapi/linux/loop.h @@ -31,6 +31,10 @@ enum { /* LO_FLAGS that can be cleared using LOOP_SET_STATUS(64) */ #define LOOP_SET_STATUS_CLEARABLE_FLAGS (LO_FLAGS_AUTOCLEAR) +/* LO_FLAGS that can be set using LOOP_CONFIGURE */ +#define LOOP_CONFIGURE_SETTABLE_FLAGS (LO_FLAGS_READ_ONLY | LO_FLAGS_AUTOCLEAR \ + | LO_FLAGS_PARTSCAN | LO_FLAGS_DIRECT_IO) + #include /* for __kernel_old_dev_t */ #include /* for __u64 */ @@ -66,6 +70,22 @@ struct loop_info64 { __u64 lo_init[2]; }; +/** + * struct loop_config - Complete configuration for a loop device. + * @fd: fd of the file to be used as a backing file for the loop device. + * @block_size: block size to use; ignored if 0. + * @info: struct loop_info64 to configure the loop device with. + * + * This structure is used with the LOOP_CONFIGURE ioctl, and can be used to + * atomically setup and configure all loop device parameters at once. + */ +struct loop_config { + __u32 fd; + __u32 block_size; + struct loop_info64 info; + __u64 __reserved[8]; +}; + /* * Loop filter types */ @@ -96,6 +116,7 @@ struct loop_info64 { #define LOOP_SET_CAPACITY 0x4C07 #define LOOP_SET_DIRECT_IO 0x4C08 #define LOOP_SET_BLOCK_SIZE 0x4C09 +#define LOOP_CONFIGURE 0x4C0A /* /dev/loop-control interface */ #define LOOP_CTL_ADD 0x4C80 From bf6d4fcf969de4bc7913b6d1343340ab68a9f2b8 Mon Sep 17 00:00:00 2001 From: Martijn Coenen Date: Thu, 4 Jun 2020 22:25:20 +0200 Subject: [PATCH 491/592] BACKPORT: loop: Fix wrong masking of status flags In faf1d25440d6, loop_set_status() now assigns lo_status directly from the passed in lo_flags, but then fixes it up by masking out flags that can't be set by LOOP_SET_STATUS; unfortunately the mask was negated. Re-ran all ltp ioctl_loop tests, and they all passed. Pass run of the previously failing one: tst_test.c:1247: INFO: Timeout per run is 0h 05m 00s tst_device.c:88: INFO: Found free device 0 '/dev/loop0' ioctl_loop01.c:49: PASS: /sys/block/loop0/loop/partscan = 0 ioctl_loop01.c:50: PASS: /sys/block/loop0/loop/autoclear = 0 ioctl_loop01.c:51: PASS: /sys/block/loop0/loop/backing_file = '/tmp/ZRJ6H4/test.img' ioctl_loop01.c:65: PASS: get expected lo_flag 12 ioctl_loop01.c:67: PASS: /sys/block/loop0/loop/partscan = 1 ioctl_loop01.c:68: PASS: /sys/block/loop0/loop/autoclear = 1 ioctl_loop01.c:77: PASS: access /dev/loop0p1 succeeds ioctl_loop01.c:83: PASS: access /sys/block/loop0/loop0p1 succeeds Summary: passed 8 failed 0 skipped 0 warnings 0 Fixes: faf1d25440d6 ("loop: Clean up LOOP_SET_STATUS lo_flags handling") Reported-by: Naresh Kamboju Signed-off-by: Martijn Coenen Tested-by: Naresh Kamboju Signed-off-by: Jens Axboe Bug: 148607611 (cherry picked from commit 6ac92fb5cdff6e5708199f1d5d9d58011ccc76a0) Change-Id: I1f3b19b02b1f288ea86d5d2d634ab9177aea24ed --- drivers/block/loop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 2a520acbab38..71a25e3dec92 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -1232,7 +1232,7 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info) goto exit; /* Mask out flags that can't be set using LOOP_SET_STATUS. */ - lo->lo_flags &= ~LOOP_SET_STATUS_SETTABLE_FLAGS; + lo->lo_flags &= LOOP_SET_STATUS_SETTABLE_FLAGS; /* For those flags, use the previous values instead */ lo->lo_flags |= prev_lo_flags & ~LOOP_SET_STATUS_SETTABLE_FLAGS; /* For flags that can't be cleared, use previous values too */ From 275ec132c7539d7f01703aa9387a29f37d76c26f Mon Sep 17 00:00:00 2001 From: Avaneesh Kumar Dwivedi Date: Mon, 3 Aug 2020 20:30:59 +0530 Subject: [PATCH 492/592] ARM: dts: msm: Include qcs610 changes for qcs410 also QCS410 is derivative of QCS610 hence include the same changes that are needed for QCS610 for QCS410 also. Change-Id: I586463a89d3180a0afbbc12968a07489a433f10b Signed-off-by: Avaneesh Kumar Dwivedi --- arch/arm64/boot/dts/qcom/qcs410-iot.dts | 4 - arch/arm64/boot/dts/qcom/qcs410-iot.dtsi | 227 +---------------------- arch/arm64/boot/dts/qcom/qcs610-iot.dts | 1 - arch/arm64/boot/dts/qcom/qcs610-iot.dtsi | 1 + arch/arm64/boot/dts/qcom/qcs610-ipc.dts | 5 - arch/arm64/boot/dts/qcom/qcs610-ipc.dtsi | 23 +-- 6 files changed, 4 insertions(+), 257 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/qcs410-iot.dts b/arch/arm64/boot/dts/qcom/qcs410-iot.dts index 2fe709638dbc..3c640e55c721 100644 --- a/arch/arm64/boot/dts/qcom/qcs410-iot.dts +++ b/arch/arm64/boot/dts/qcom/qcs410-iot.dts @@ -14,7 +14,6 @@ #include "qcs410.dtsi" #include "qcs410-iot.dtsi" -#include "sm6150-audio-overlay.dtsi" / { model = "Qualcomm Technologies, Inc. QCS410 IOT"; @@ -22,6 +21,3 @@ qcom,board-id = <32 0>; }; -&sm6150_snd { - /delete-property/ fsa4480-i2c-handle; -}; diff --git a/arch/arm64/boot/dts/qcom/qcs410-iot.dtsi b/arch/arm64/boot/dts/qcom/qcs410-iot.dtsi index 374d1f73eff9..3dc3f2141b17 100644 --- a/arch/arm64/boot/dts/qcom/qcs410-iot.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs410-iot.dtsi @@ -10,235 +10,10 @@ * GNU General Public License for more details. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "qcs610-camera-sensor-idp.dtsi" +#include "qcs610-iot.dtsi" / { model = "Qualcomm Technologies, Inc. QCS410 IOT"; compatible = "qcom,qcs410-iot", "qcom,qcs410", "qcom,iot"; }; -&qupv3_se3_i2c { - status = "ok"; - #include "smb1390.dtsi" -}; - -&qupv3_se0_2uart { - status = "ok"; -}; - -&qupv3_se7_4uart { - status = "ok"; -}; - -&pm6150l_gpios { - key_vol_up { - key_vol_up_default: key_vol_up_default { - pins = "gpio2"; - function = "normal"; - input-enable; - bias-pull-up; - power-source = <0>; - }; - }; - - irled { - irled_pwm: irled_pwm_default { - pins = "gpio6"; - function = "func1"; - qcom,drive-strength = <2>; - power-source = <0>; - bias-disable; - output-low; - }; - }; -}; - -&soc { - gpio_keys { - compatible = "gpio-keys"; - label = "gpio-keys"; - - pinctrl-names = "default"; - pinctrl-0 = <&key_vol_up_default>; - - vol_up { - label = "volume_up"; - gpios = <&pm6150l_gpios 2 GPIO_ACTIVE_LOW>; - linux,input-type = <1>; - linux,code = ; - linux,can-disable; - debounce-interval = <15>; - gpio-key,wakeup; - }; - }; - - mtp_batterydata: qcom,battery-data { - qcom,batt-id-range-pct = <15>; - #include "qg-batterydata-alium-3600mah.dtsi" - #include "qg-batterydata-mlp356477-2800mah.dtsi" - }; -}; - -&pm6150l_wled { - qcom,string-cfg= <3>; - qcom,leds-per-string = <7>; - status = "ok"; -}; - -&pm6150l_lcdb { - status = "ok"; -}; - -&pm6150l_pwm_1 { - status = "okay"; -}; - -&pm6150_qg { - qcom,battery-data = <&mtp_batterydata>; - qcom,qg-iterm-ma = <100>; - qcom,hold-soc-while-full; - qcom,linearize-soc; - qcom,cl-feedback-on; -}; - -&pm6150_charger { - io-channels = <&pm6150_vadc ADC_USB_IN_V_16>, - <&pm6150_vadc ADC_USB_IN_I>, - <&pm6150_vadc ADC_CHG_TEMP>, - <&pm6150_vadc ADC_DIE_TEMP>, - <&pm6150_vadc ADC_AMUX_THM4_PU2>, - <&pm6150_vadc ADC_SBUx>, - <&pm6150_vadc ADC_VPH_PWR>; - io-channel-names = "usb_in_voltage", - "usb_in_current", - "chg_temp", - "die_temp", - "conn_temp", - "sbux_res", - "vph_voltage"; - qcom,battery-data = <&mtp_batterydata>; - qcom,auto-recharge-soc = <98>; - qcom,step-charging-enable; - qcom,sw-jeita-enable; - qcom,fcc-stepping-enable; - qcom,suspend-input-on-debug-batt; - qcom,sec-charger-config = <3>; - qcom,thermal-mitigation = <4200000 3500000 3000000 - 2500000 2000000 1500000 1000000 500000>; - dpdm-supply = <&qusb_phy0>; - qcom,charger-temp-max = <800>; - qcom,smb-temp-max = <800>; -}; - -&smb1390 { - /delete-property/ interrupts; - interrupts = <0x0 0xc2 0x0 IRQ_TYPE_LEVEL_LOW>; - pinctrl-names = "default"; - pinctrl-0 = <&smb_stat_default>; - status = "ok"; -}; - -&smb1390_charger { - /delete-property/ compatible; - compatible = "qcom,smb1390-charger-psy"; - io-channels = <&pm6150_vadc ADC_AMUX_THM3>; - io-channel-names = "cp_die_temp"; - status = "ok"; -}; - -&sdhc_1 { - vdd-supply = <&pm6150l_l11>; - qcom,vdd-voltage-level = <2950000 2950000>; - qcom,vdd-current-level = <0 570000>; - - vdd-io-supply = <&pm6150_l12>; - qcom,vdd-io-always-on; - qcom,vdd-io-lpm-sup; - qcom,vdd-io-voltage-level = <1800000 1800000>; - qcom,vdd-io-current-level = <0 325000>; - - pinctrl-names = "active", "sleep"; - pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on &sdc1_rclk_on>; - pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off &sdc1_rclk_off>; - - status = "ok"; -}; - -&sdhc_2 { - vdd-supply = <&pm6150l_l9>; - qcom,vdd-voltage-level = <2950000 2950000>; - qcom,vdd-current-level = <0 800000>; - - vdd-io-supply = <&pm6150l_l6>; - qcom,vdd-io-voltage-level = <1800000 3100000>; - qcom,vdd-io-current-level = <0 22000>; - - pinctrl-names = "active", "sleep"; - pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on>; - pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &sdc2_cd_off>; - - cd-gpios = <&tlmm 99 GPIO_ACTIVE_LOW>; - - status = "ok"; -}; - -&pil_camera_mem { - reg = <0 0x8f800000 0 0x500000>; -}; - -&pil_modem_mem { - reg = <0 0x8fd00000 0 0x3100000>; -}; - -&pil_video_mem { - reg = <0 0x92e00000 0 0x500000>; -}; - -&wlan_msa_mem { - reg = <0 0x93300000 0 0x200000>; -}; - -&pil_cdsp_mem { - reg = <0 0x93500000 0 0x1e00000>; -}; - -&pil_adsp_mem { - reg = <0 0x95300000 0 0x1e00000>; -}; - -&pil_ipa_fw_mem { - reg = <0 0x97100000 0 0x10000>; -}; - -&pil_ipa_gsi_mem { - reg = <0 0x97110000 0 0x5000>; -}; - -&pil_gpu_mem { - reg = <0 0x97115000 0 0x2000>; -}; - -&L16A { - regulator-max-microvolt = <3304000>; -}; - -&L19A { - regulator-max-microvolt = <3304000>; -}; - -&L4C { - regulator-max-microvolt = <2912000>; -}; - -&L5C { - regulator-max-microvolt = <2912000>; -}; diff --git a/arch/arm64/boot/dts/qcom/qcs610-iot.dts b/arch/arm64/boot/dts/qcom/qcs610-iot.dts index a0a6c723d172..9d79b8ceea0a 100644 --- a/arch/arm64/boot/dts/qcom/qcs610-iot.dts +++ b/arch/arm64/boot/dts/qcom/qcs610-iot.dts @@ -13,7 +13,6 @@ /dts-v1/; #include "qcs610.dtsi" #include "qcs610-iot.dtsi" -#include "sm6150-audio-overlay.dtsi" / { model = "Qualcomm Technologies, Inc. QCS610 IOT"; diff --git a/arch/arm64/boot/dts/qcom/qcs610-iot.dtsi b/arch/arm64/boot/dts/qcom/qcs610-iot.dtsi index c65dae42e904..6bf996060d60 100644 --- a/arch/arm64/boot/dts/qcom/qcs610-iot.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs610-iot.dtsi @@ -25,6 +25,7 @@ #include "sm6150-sde-pll.dtsi" #include "sm6150-sde-display.dtsi" #include "qcs610-camera-sensor-idp.dtsi" +#include "sm6150-audio-overlay.dtsi" / { model = "Qualcomm Technologies, Inc. QCS610 IOT"; diff --git a/arch/arm64/boot/dts/qcom/qcs610-ipc.dts b/arch/arm64/boot/dts/qcom/qcs610-ipc.dts index aa9b6439e0b3..cb0b1a23bfa6 100644 --- a/arch/arm64/boot/dts/qcom/qcs610-ipc.dts +++ b/arch/arm64/boot/dts/qcom/qcs610-ipc.dts @@ -13,7 +13,6 @@ /dts-v1/; #include "qcs610.dtsi" -#include "qcs610-iot.dtsi" #include "qcs610-ipc.dtsi" / { @@ -21,7 +20,3 @@ compatible = "qcom,qcs610-iot", "qcom,qcs610", "qcom,iot"; qcom,board-id = <32 1>; }; - -&sm6150_snd { - /delete-property/ fsa4480-i2c-handle; -}; diff --git a/arch/arm64/boot/dts/qcom/qcs610-ipc.dtsi b/arch/arm64/boot/dts/qcom/qcs610-ipc.dtsi index 87c198d211ec..9340e5cb4d18 100644 --- a/arch/arm64/boot/dts/qcom/qcs610-ipc.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs610-ipc.dtsi @@ -10,8 +10,8 @@ * GNU General Public License for more details. */ -#include "sm6150-audio-overlay.dtsi" -#include "sm6150-camera-sensor-idp.dtsi" +#include "qcs610-iot.dtsi" + / { model = "Qualcomm Technologies, Inc. QCS610 IPC"; compatible = "qcom,qcs610-iot", "qcom,qcs610", "qcom,iot"; @@ -73,25 +73,6 @@ qcom,batteryless-platform; }; -&eeprom_rear { - cam_vana-supply = <&pm6150l_l4>; - rgltr-min-voltage = <1800000 2900000 1200000 0 2800000>; - rgltr-max-voltage = <1800000 2900000 1200000 0 2800000>; -}; - -&cam_cci { - qcom,cam-sensor@0 { - cam_vana-supply = <&pm6150l_l4>; - rgltr-min-voltage = <1800000 2900000 1200000 0>; - rgltr-max-voltage = <1800000 2900000 1200000 0>; - }; -}; - - -&led_flash_front { - status = "disabled"; -}; - &tlmm { led_red_default: led_red_default { mux { From 2167f16cd3164948b70c5670c774265ddee90e6d Mon Sep 17 00:00:00 2001 From: Om Parkash Date: Tue, 23 Jun 2020 14:03:29 +0530 Subject: [PATCH 493/592] jpeg: Add DMA driver implementation Add code to fill register settings and IRQ handler code for JPEG DMA. Change-Id: I67eba471e3205e94d3e8de5e9bab4be8c352fb6a Signed-off-by: Om Parkash --- .../camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c | 198 +++++++++----- .../camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h | 4 +- .../cam_jpeg_dma_hw_info_ver_4_2_0.h | 53 ++++ .../jpeg_hw/jpeg_dma_hw/jpeg_dma_core.c | 242 +++++++++++++++++- .../jpeg_hw/jpeg_dma_hw/jpeg_dma_core.h | 41 ++- .../jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c | 17 +- .../jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c | 4 +- .../jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c | 4 +- 8 files changed, 471 insertions(+), 92 deletions(-) create mode 100644 drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/cam_jpeg_dma_hw_info_ver_4_2_0.h diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c index ae26f61d717a..0b5855a9c28f 100644 --- a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c +++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c @@ -46,6 +46,112 @@ static struct cam_jpeg_hw_mgr g_jpeg_hw_mgr; static int32_t cam_jpeg_hw_mgr_cb(uint32_t irq_status, int32_t result_size, void *data); static int cam_jpeg_mgr_process_cmd(void *priv, void *data); +static int cam_jpeg_insert_cdm_change_base( + struct cam_hw_config_args *config_args, + struct cam_jpeg_hw_ctx_data *ctx_data, + struct cam_jpeg_hw_mgr *hw_mgr); + +static int cam_jpeg_process_next_hw_update(void *priv, void *data) +{ + int rc; + int i = 0; + struct cam_jpeg_hw_mgr *hw_mgr = priv; + struct cam_hw_update_entry *cmd; + struct cam_cdm_bl_request *cdm_cmd; + struct cam_hw_config_args *config_args = NULL; + struct cam_jpeg_hw_ctx_data *ctx_data = NULL; + uint32_t dev_type; + struct cam_jpeg_hw_cfg_req *p_cfg_req = NULL; + uint32_t cdm_cfg_to_insert = 0; + + if (!data || !priv) { + CAM_ERR(CAM_JPEG, "Invalid data"); + return -EINVAL; + } + + ctx_data = (struct cam_jpeg_hw_ctx_data *)data; + dev_type = ctx_data->jpeg_dev_acquire_info.dev_type; + p_cfg_req = hw_mgr->dev_hw_cfg_args[dev_type][0]; + config_args = (struct cam_hw_config_args *)&p_cfg_req->hw_cfg_args; + + if (!hw_mgr->devices[dev_type][0]->hw_ops.reset) { + CAM_ERR(CAM_JPEG, "op reset null "); + rc = -EFAULT; + goto end_error; + } + rc = hw_mgr->devices[dev_type][0]->hw_ops.reset( + hw_mgr->devices[dev_type][0]->hw_priv, + NULL, 0); + if (rc) { + CAM_ERR(CAM_JPEG, "jpeg hw reset failed %d", rc); + goto end_error; + } + + cdm_cmd = ctx_data->cdm_cmd; + cdm_cmd->type = CAM_CDM_BL_CMD_TYPE_MEM_HANDLE; + cdm_cmd->flag = false; + cdm_cmd->userdata = NULL; + cdm_cmd->cookie = 0; + cdm_cmd->cmd_arrary_count = 0; + + /* insert cdm chage base cmd */ + rc = cam_jpeg_insert_cdm_change_base(config_args, + ctx_data, hw_mgr); + if (rc) { + CAM_ERR(CAM_JPEG, "insert change base failed %d", rc); + goto end_error; + } + + /* insert next cdm payload at index */ + /* for enc or dma 1st pass at index 1 */ + /* for dma 2nd pass at index 2, for 3rd at 4 */ + if (p_cfg_req->num_hw_entry_processed == 0) + cdm_cfg_to_insert = CAM_JPEG_CFG; + else + cdm_cfg_to_insert = p_cfg_req->num_hw_entry_processed + 2; + + CAM_DBG(CAM_JPEG, "processed %d total %d using cfg entry %d for %pK", + p_cfg_req->num_hw_entry_processed, + config_args->num_hw_update_entries, + cdm_cfg_to_insert, + p_cfg_req); + + cmd = (config_args->hw_update_entries + cdm_cfg_to_insert); + cdm_cmd->cmd[cdm_cmd->cmd_arrary_count].bl_addr.mem_handle = + cmd->handle; + cdm_cmd->cmd[cdm_cmd->cmd_arrary_count].offset = + cmd->offset; + cdm_cmd->cmd[cdm_cmd->cmd_arrary_count].len = + cmd->len; + CAM_DBG(CAM_JPEG, "i %d entry h %d o %d l %d", + i, cmd->handle, cmd->offset, cmd->len); + cdm_cmd->cmd_arrary_count++; + + rc = cam_cdm_submit_bls( + hw_mgr->cdm_info[dev_type][0].cdm_handle, + cdm_cmd); + if (rc) { + CAM_ERR(CAM_JPEG, "Failed to apply the configs %d", rc); + goto end_error; + } + + if (!hw_mgr->devices[dev_type][0]->hw_ops.start) { + CAM_ERR(CAM_JPEG, "op start null "); + rc = -EINVAL; + goto end_error; + } + rc = hw_mgr->devices[dev_type][0]->hw_ops.start( + hw_mgr->devices[dev_type][0]->hw_priv, NULL, 0); + if (rc) { + CAM_ERR(CAM_JPEG, "Failed to apply the configs %d", + rc); + goto end_error; + } + + return 0; +end_error: + return rc; +} static int cam_jpeg_mgr_process_irq(void *priv, void *data) { @@ -93,6 +199,21 @@ static int cam_jpeg_mgr_process_irq(void *priv, void *data) return -EINVAL; } + p_cfg_req->num_hw_entry_processed++; + CAM_DBG(CAM_JPEG, "hw entry processed %d", + p_cfg_req->num_hw_entry_processed); + + if ((task_data->result_size > 0) && + (p_cfg_req->num_hw_entry_processed < + p_cfg_req->hw_cfg_args.num_hw_update_entries - 2)) { + /* start processing next entry before marking device free */ + rc = cam_jpeg_process_next_hw_update(priv, ctx_data); + if (!rc) { + mutex_unlock(&g_jpeg_hw_mgr.hw_mgr_mutex); + return 0; + } + } + irq_cb.jpeg_hw_mgr_cb = cam_jpeg_hw_mgr_cb; irq_cb.data = NULL; irq_cb.b_set_cb = false; @@ -159,7 +280,9 @@ static int cam_jpeg_mgr_process_irq(void *priv, void *data) if ((p_cfg_req->hw_cfg_args.hw_update_entries[CAM_JPEG_PARAM].offset / sizeof(uint32_t)) >= cmd_buf_len) { - CAM_ERR(CAM_JPEG, "Not enough buf"); + CAM_ERR(CAM_JPEG, "Invalid offset: %u cmd buf len: %zu", + p_cfg_req->hw_cfg_args.hw_update_entries[ + CAM_JPEG_PARAM].offset, cmd_buf_len); return -EINVAL; } @@ -288,7 +411,9 @@ static int cam_jpeg_insert_cdm_change_base( if (config_args->hw_update_entries[CAM_JPEG_CHBASE].offset >= ch_base_len) { - CAM_ERR(CAM_JPEG, "Not enough buf"); + CAM_ERR(CAM_JPEG, "Not enough buf offset %d len %d", + config_args->hw_update_entries[CAM_JPEG_CHBASE].offset, + ch_base_len); return -EINVAL; } CAM_DBG(CAM_JPEG, "iova %pK len %zu offset %d", @@ -327,8 +452,6 @@ static int cam_jpeg_mgr_process_cmd(void *priv, void *data) int rc; int i = 0; struct cam_jpeg_hw_mgr *hw_mgr = priv; - struct cam_hw_update_entry *cmd; - struct cam_cdm_bl_request *cdm_cmd; struct cam_hw_config_args *config_args = NULL; struct cam_jpeg_hw_ctx_data *ctx_data = NULL; uintptr_t request_id = 0; @@ -430,68 +553,14 @@ static int cam_jpeg_mgr_process_cmd(void *priv, void *data) goto end_callcb; } - if (!hw_mgr->devices[dev_type][0]->hw_ops.reset) { - CAM_ERR(CAM_JPEG, "op reset null "); - rc = -EFAULT; - goto end_callcb; - } - rc = hw_mgr->devices[dev_type][0]->hw_ops.reset( - hw_mgr->devices[dev_type][0]->hw_priv, - NULL, 0); + /* insert one of the cdm payloads */ + rc = cam_jpeg_process_next_hw_update(priv, ctx_data); if (rc) { - CAM_ERR(CAM_JPEG, "jpeg hw reset failed %d", rc); + CAM_ERR(CAM_JPEG, "next hw update failed %d", rc); goto end_callcb; } - cdm_cmd = ctx_data->cdm_cmd; - cdm_cmd->type = CAM_CDM_BL_CMD_TYPE_MEM_HANDLE; - cdm_cmd->flag = false; - cdm_cmd->userdata = NULL; - cdm_cmd->cookie = 0; - cdm_cmd->cmd_arrary_count = 0; - rc = cam_jpeg_insert_cdm_change_base(config_args, - ctx_data, hw_mgr); - if (rc) { - CAM_ERR(CAM_JPEG, "insert change base failed %d", rc); - goto end_callcb; - } - - CAM_DBG(CAM_JPEG, "num hw up %d", config_args->num_hw_update_entries); - for (i = CAM_JPEG_CFG; i < (config_args->num_hw_update_entries - 1); - i++) { - cmd = (config_args->hw_update_entries + i); - cdm_cmd->cmd[cdm_cmd->cmd_arrary_count].bl_addr.mem_handle - = cmd->handle; - cdm_cmd->cmd[cdm_cmd->cmd_arrary_count].offset = - cmd->offset; - cdm_cmd->cmd[cdm_cmd->cmd_arrary_count].len = - cmd->len; - CAM_DBG(CAM_JPEG, "i %d entry h %d o %d l %d", - i, cmd->handle, cmd->offset, cmd->len); - cdm_cmd->cmd_arrary_count++; - } - - rc = cam_cdm_submit_bls( - hw_mgr->cdm_info[dev_type][0].cdm_handle, cdm_cmd); - if (rc) { - CAM_ERR(CAM_JPEG, "Failed to apply the configs %d", rc); - goto rel_cpu_buf; - } - - if (!hw_mgr->devices[dev_type][0]->hw_ops.start) { - CAM_ERR(CAM_JPEG, "op start null "); - rc = -EINVAL; - goto rel_cpu_buf; - } - rc = hw_mgr->devices[dev_type][0]->hw_ops.start( - hw_mgr->devices[dev_type][0]->hw_priv, - NULL, 0); - if (rc) { - CAM_ERR(CAM_JPEG, "Failed to start hw %d", - rc); - goto rel_cpu_buf; - } cam_common_util_get_curr_timestamp(&p_cfg_req->submit_timestamp); if (cam_mem_put_cpu_buf( config_args->hw_update_entries[CAM_JPEG_CHBASE].handle)) @@ -501,11 +570,6 @@ static int cam_jpeg_mgr_process_cmd(void *priv, void *data) mutex_unlock(&hw_mgr->hw_mgr_mutex); return rc; -rel_cpu_buf: - if (cam_mem_put_cpu_buf( - config_args->hw_update_entries[CAM_JPEG_CHBASE].handle)) - CAM_WARN(CAM_JPEG, "unable to put info for cmd buf: 0x%x", - config_args->hw_update_entries[CAM_JPEG_CHBASE].handle); end_callcb: mutex_unlock(&hw_mgr->hw_mgr_mutex); if (p_cfg_req) { @@ -578,6 +642,7 @@ static int cam_jpeg_mgr_config_hw(void *hw_mgr_priv, void *config_hw_args) request_id = (uintptr_t)config_args->priv; p_cfg_req->req_id = request_id; + p_cfg_req->num_hw_entry_processed = 0; hw_update_entries = config_args->hw_update_entries; CAM_DBG(CAM_JPEG, "ctx_data = %pK req_id = %lld %zd", ctx_data, request_id, (uintptr_t)config_args->priv); @@ -797,6 +862,7 @@ static int cam_jpeg_mgr_prepare_hw_update(void *hw_mgr_priv, i, io_cfg_ptr[i].direction, io_cfg_ptr[i].fence); } + CAM_DBG(CAM_JPEG, "received num cmd buf %d", packet->num_cmd_buf); j = prepare_args->num_hw_update_entries; rc = cam_packet_util_get_kmd_buffer(packet, &kmd_buf); diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h index 2dc11dfa0746..3f317524611f 100644 --- a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h +++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -83,6 +83,7 @@ struct cam_jpeg_hw_cdm_info_t { * @dev_type: Dev type for cfg request * @req_id: Request Id * @submit_timestamp: Timestamp of submitting request + * @num_hw_entry_processed: Cdm payloads already processed */ struct cam_jpeg_hw_cfg_req { struct list_head list; @@ -90,6 +91,7 @@ struct cam_jpeg_hw_cfg_req { uint32_t dev_type; uintptr_t req_id; struct timeval submit_timestamp; + uint32_t num_hw_entry_processed; }; /** diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/cam_jpeg_dma_hw_info_ver_4_2_0.h b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/cam_jpeg_dma_hw_info_ver_4_2_0.h new file mode 100644 index 000000000000..ff8997bd4615 --- /dev/null +++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/cam_jpeg_dma_hw_info_ver_4_2_0.h @@ -0,0 +1,53 @@ +/* Copyright (c) 2020 The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef CAM_JPEG_DMA_HW_INFO_VER_4_2_0_H +#define CAM_JPEG_DMA_HW_INFO_VER_4_2_0_H + +#define CAM_JPEGDMA_HW_IRQ_STATUS_SESSION_DONE (1 << 0) +#define CAM_JPEGDMA_HW_IRQ_STATUS_RD_BUF_DONE (1 << 1) +#define CAM_JPEGDMA_HW_IRQ_STATUS_WR_BUF_DONE (1 << 5) +#define CAM_JPEGDMA_HW_IRQ_STATUS_AXI_HALT (1 << 9) +#define CAM_JPEGDMA_HW_IRQ_STATUS_RST_DONE (1 << 10) + +#define CAM_JPEGDMA_HW_MASK_COMP_FRAMEDONE \ + CAM_JPEGDMA_HW_IRQ_STATUS_SESSION_DONE +#define CAM_JPEGDMA_HW_MASK_COMP_RESET_ACK \ + CAM_JPEGDMA_HW_IRQ_STATUS_RST_DONE + +static struct cam_jpeg_dma_device_hw_info cam_jpeg_dma_hw_info = { + .reg_offset = { + .hw_version = 0x0, + .int_clr = 0x14, + .int_status = 0x10, + .int_mask = 0x0C, + .hw_cmd = 0x1C, + .reset_cmd = 0x08, + .encode_size = 0x180, + }, + .reg_val = { + .int_clr_clearall = 0xFFFFFFFF, + .int_mask_disable_all = 0x00000000, + .int_mask_enable_all = 0xFFFFFFFF, + .hw_cmd_start = 0x00000001, + .reset_cmd = 0x32083, + .hw_cmd_stop = 0x00000004, + }, + .int_status = { + .framedone = CAM_JPEGDMA_HW_MASK_COMP_FRAMEDONE, + .resetdone = CAM_JPEGDMA_HW_MASK_COMP_RESET_ACK, + .iserror = 0x0, + .stopdone = CAM_JPEGDMA_HW_IRQ_STATUS_AXI_HALT, + } +}; + +#endif /* CAM_JPEG_DMA_HW_INFO_VER_4_2_0_H */ diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.c b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.c index 037a39e5eb12..169a027d95ff 100644 --- a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.c +++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -31,6 +31,15 @@ #include "cam_cpas_api.h" #include "cam_debug_util.h" +#define CAM_JPEG_HW_IRQ_IS_FRAME_DONE(jpeg_irq_status, hi) \ + ((jpeg_irq_status) & (hi)->int_status.framedone) +#define CAM_JPEG_HW_IRQ_IS_RESET_ACK(jpeg_irq_status, hi) \ + ((jpeg_irq_status) & (hi)->int_status.resetdone) +#define CAM_JPEG_HW_IRQ_IS_STOP_DONE(jpeg_irq_status, hi) \ + ((jpeg_irq_status) & (hi)->int_status.stopdone) + +#define CAM_JPEG_DMA_RESET_TIMEOUT msecs_to_jiffies(500) + int cam_jpeg_dma_init_hw(void *device_priv, void *init_hw_args, uint32_t arg_size) { @@ -131,7 +140,7 @@ int cam_jpeg_dma_deinit_hw(void *device_priv, rc = cam_jpeg_dma_disable_soc_resources(soc_info); if (rc) - CAM_ERR(CAM_JPEG, "soc enable failed %d", rc); + CAM_ERR(CAM_JPEG, "soc disable failed %d", rc); rc = cam_cpas_stop(core_info->cpas_handle); if (rc) @@ -142,6 +151,226 @@ int cam_jpeg_dma_deinit_hw(void *device_priv, return 0; } +irqreturn_t cam_jpeg_dma_irq(int irq_num, void *data) +{ + struct cam_hw_info *jpeg_dma_dev = data; + struct cam_jpeg_dma_device_core_info *core_info = NULL; + uint32_t irq_status = 0; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_jpeg_dma_device_hw_info *hw_info = NULL; + void __iomem *mem_base; + + if (!jpeg_dma_dev) { + CAM_ERR(CAM_JPEG, "Invalid args"); + return IRQ_HANDLED; + } + soc_info = &jpeg_dma_dev->soc_info; + core_info = (struct cam_jpeg_dma_device_core_info *) + jpeg_dma_dev->core_info; + hw_info = core_info->jpeg_dma_hw_info; + mem_base = soc_info->reg_map[0].mem_base; + + irq_status = cam_io_r_mb(mem_base + + core_info->jpeg_dma_hw_info->reg_offset.int_status); + cam_io_w_mb(irq_status, + soc_info->reg_map[0].mem_base + + core_info->jpeg_dma_hw_info->reg_offset.int_clr); + CAM_DBG(CAM_JPEG, "irq_num %d irq_status = %x , core_state %d", + irq_num, irq_status, core_info->core_state); + if (CAM_JPEG_HW_IRQ_IS_FRAME_DONE(irq_status, hw_info)) { + spin_lock(&jpeg_dma_dev->hw_lock); + if (core_info->core_state == CAM_JPEG_DMA_CORE_READY) { + core_info->result_size = 1; + CAM_DBG(CAM_JPEG, "result_size %d", + core_info->result_size); + core_info->core_state = + CAM_JPEG_DMA_CORE_RESETTING_ON_DONE; + cam_io_w_mb(hw_info->reg_val.reset_cmd, + mem_base + hw_info->reg_offset.reset_cmd); + } else { + CAM_WARN(CAM_JPEG, "unexpected frame done "); + core_info->core_state = CAM_JPEG_DMA_CORE_NOT_READY; + } + spin_unlock(&jpeg_dma_dev->hw_lock); + } + + if (CAM_JPEG_HW_IRQ_IS_RESET_ACK(irq_status, hw_info)) { + spin_lock(&jpeg_dma_dev->hw_lock); + if (core_info->core_state == CAM_JPEG_DMA_CORE_RESETTING) { + core_info->core_state = CAM_JPEG_DMA_CORE_READY; + core_info->result_size = -1; + complete(&jpeg_dma_dev->hw_complete); + } else if (core_info->core_state == + CAM_JPEG_DMA_CORE_RESETTING_ON_DONE) { + if (core_info->irq_cb.jpeg_hw_mgr_cb) { + core_info->irq_cb.jpeg_hw_mgr_cb(irq_status, + core_info->result_size, + core_info->irq_cb.data); + } else { + CAM_WARN(CAM_JPEG, "unexpected frame done"); + } + core_info->result_size = -1; + core_info->core_state = CAM_JPEG_DMA_CORE_NOT_READY; + } else { + CAM_ERR(CAM_JPEG, "unexpected reset irq"); + } + spin_unlock(&jpeg_dma_dev->hw_lock); + } + if (CAM_JPEG_HW_IRQ_IS_STOP_DONE(irq_status, hw_info)) { + spin_lock(&jpeg_dma_dev->hw_lock); + if (core_info->core_state == CAM_JPEG_DMA_CORE_ABORTING) { + core_info->core_state = CAM_JPEG_DMA_CORE_NOT_READY; + complete(&jpeg_dma_dev->hw_complete); + if (core_info->irq_cb.jpeg_hw_mgr_cb) { + core_info->irq_cb.jpeg_hw_mgr_cb(irq_status, + -1, + core_info->irq_cb.data); + } + } else { + CAM_ERR(CAM_JPEG, "unexpected abort irq"); + } + spin_unlock(&jpeg_dma_dev->hw_lock); + } + + return IRQ_HANDLED; +} + +int cam_jpeg_dma_reset_hw(void *data, + void *start_args, uint32_t arg_size) +{ + struct cam_hw_info *jpeg_dma_dev = data; + struct cam_jpeg_dma_device_core_info *core_info = NULL; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_jpeg_dma_device_hw_info *hw_info = NULL; + void __iomem *mem_base; + unsigned long rem_jiffies; + + if (!jpeg_dma_dev) { + CAM_ERR(CAM_JPEG, "Invalid args"); + return -EINVAL; + } + /* maskdisable.clrirq.maskenable.resetcmd */ + soc_info = &jpeg_dma_dev->soc_info; + core_info = (struct cam_jpeg_dma_device_core_info *) + jpeg_dma_dev->core_info; + hw_info = core_info->jpeg_dma_hw_info; + mem_base = soc_info->reg_map[0].mem_base; + + mutex_lock(&core_info->core_mutex); + spin_lock(&jpeg_dma_dev->hw_lock); + if (core_info->core_state == CAM_JPEG_DMA_CORE_RESETTING) { + CAM_ERR(CAM_JPEG, "dma alrady resetting"); + spin_unlock(&jpeg_dma_dev->hw_lock); + mutex_unlock(&core_info->core_mutex); + return 0; + } + + reinit_completion(&jpeg_dma_dev->hw_complete); + + core_info->core_state = CAM_JPEG_DMA_CORE_RESETTING; + spin_unlock(&jpeg_dma_dev->hw_lock); + + cam_io_w_mb(hw_info->reg_val.int_mask_disable_all, + mem_base + hw_info->reg_offset.int_mask); + cam_io_w_mb(hw_info->reg_val.int_clr_clearall, + mem_base + hw_info->reg_offset.int_clr); + cam_io_w_mb(hw_info->reg_val.int_mask_enable_all, + mem_base + hw_info->reg_offset.int_mask); + cam_io_w_mb(hw_info->reg_val.reset_cmd, + mem_base + hw_info->reg_offset.reset_cmd); + + rem_jiffies = wait_for_completion_timeout(&jpeg_dma_dev->hw_complete, + CAM_JPEG_DMA_RESET_TIMEOUT); + if (!rem_jiffies) { + CAM_ERR(CAM_JPEG, "dma error Reset Timeout"); + core_info->core_state = CAM_JPEG_DMA_CORE_NOT_READY; + } + + mutex_unlock(&core_info->core_mutex); + return 0; +} + +int cam_jpeg_dma_start_hw(void *data, + void *start_args, uint32_t arg_size) +{ + struct cam_hw_info *jpeg_dma_dev = data; + struct cam_jpeg_dma_device_core_info *core_info = NULL; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_jpeg_dma_device_hw_info *hw_info = NULL; + void __iomem *mem_base; + + if (!jpeg_dma_dev) { + CAM_ERR(CAM_JPEG, "Invalid args"); + return -EINVAL; + } + + soc_info = &jpeg_dma_dev->soc_info; + core_info = (struct cam_jpeg_dma_device_core_info *) + jpeg_dma_dev->core_info; + hw_info = core_info->jpeg_dma_hw_info; + mem_base = soc_info->reg_map[0].mem_base; + + if (core_info->core_state != CAM_JPEG_DMA_CORE_READY) { + CAM_ERR(CAM_JPEG, "Error not ready"); + return -EINVAL; + } + + CAM_DBG(CAM_JPEG, "Starting DMA"); + cam_io_w_mb(0x00000601, + mem_base + hw_info->reg_offset.int_mask); + cam_io_w_mb(hw_info->reg_val.hw_cmd_start, + mem_base + hw_info->reg_offset.hw_cmd); + + return 0; +} + +int cam_jpeg_dma_stop_hw(void *data, + void *stop_args, uint32_t arg_size) +{ + struct cam_hw_info *jpeg_dma_dev = data; + struct cam_jpeg_dma_device_core_info *core_info = NULL; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_jpeg_dma_device_hw_info *hw_info = NULL; + void __iomem *mem_base; + unsigned long rem_jiffies; + + if (!jpeg_dma_dev) { + CAM_ERR(CAM_JPEG, "Invalid args"); + return -EINVAL; + } + soc_info = &jpeg_dma_dev->soc_info; + core_info = (struct cam_jpeg_dma_device_core_info *) + jpeg_dma_dev->core_info; + hw_info = core_info->jpeg_dma_hw_info; + mem_base = soc_info->reg_map[0].mem_base; + + mutex_lock(&core_info->core_mutex); + spin_lock(&jpeg_dma_dev->hw_lock); + if (core_info->core_state == CAM_JPEG_DMA_CORE_ABORTING) { + CAM_ERR(CAM_JPEG, "alrady stopping"); + spin_unlock(&jpeg_dma_dev->hw_lock); + mutex_unlock(&core_info->core_mutex); + return 0; + } + + reinit_completion(&jpeg_dma_dev->hw_complete); + core_info->core_state = CAM_JPEG_DMA_CORE_ABORTING; + spin_unlock(&jpeg_dma_dev->hw_lock); + + cam_io_w_mb(hw_info->reg_val.hw_cmd_stop, + mem_base + hw_info->reg_offset.hw_cmd); + + rem_jiffies = wait_for_completion_timeout(&jpeg_dma_dev->hw_complete, + CAM_JPEG_DMA_RESET_TIMEOUT); + if (!rem_jiffies) { + CAM_ERR(CAM_JPEG, "error Reset Timeout"); + core_info->core_state = CAM_JPEG_DMA_CORE_NOT_READY; + } + + mutex_unlock(&core_info->core_mutex); + return 0; +} + int cam_jpeg_dma_process_cmd(void *device_priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) { @@ -186,12 +415,7 @@ int cam_jpeg_dma_process_cmd(void *device_priv, uint32_t cmd_type, rc = -EINVAL; break; } - + if (rc) + CAM_ERR(CAM_JPEG, "error cmdtype %d rc = %d", cmd_type, rc); return rc; } - -irqreturn_t cam_jpeg_dma_irq(int irq_num, void *data) -{ - return IRQ_HANDLED; -} - diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.h b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.h index 8f5fd58698d2..737c2f217feb 100644 --- a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.h +++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2018,2020 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -21,14 +21,44 @@ #include "cam_jpeg_hw_intf.h" +struct cam_jpeg_dma_reg_offsets { + uint32_t hw_version; + uint32_t int_status; + uint32_t int_clr; + uint32_t int_mask; + uint32_t hw_cmd; + uint32_t reset_cmd; + uint32_t encode_size; +}; + +struct cam_jpeg_dma_regval { + uint32_t int_clr_clearall; + uint32_t int_mask_disable_all; + uint32_t int_mask_enable_all; + uint32_t hw_cmd_start; + uint32_t reset_cmd; + uint32_t hw_cmd_stop; +}; + +struct cam_jpeg_dma_int_status { + uint32_t framedone; + uint32_t resetdone; + uint32_t iserror; + uint32_t stopdone; +}; + struct cam_jpeg_dma_device_hw_info { - uint32_t reserved; + struct cam_jpeg_dma_reg_offsets reg_offset; + struct cam_jpeg_dma_regval reg_val; + struct cam_jpeg_dma_int_status int_status; }; enum cam_jpeg_dma_core_state { CAM_JPEG_DMA_CORE_NOT_READY, CAM_JPEG_DMA_CORE_READY, CAM_JPEG_DMA_CORE_RESETTING, + CAM_JPEG_DMA_CORE_ABORTING, + CAM_JPEG_DMA_CORE_RESETTING_ON_DONE, CAM_JPEG_DMA_CORE_STATE_MAX, }; @@ -39,12 +69,19 @@ struct cam_jpeg_dma_device_core_info { struct cam_jpeg_set_irq_cb irq_cb; int32_t ref_count; struct mutex core_mutex; + int32_t result_size; }; int cam_jpeg_dma_init_hw(void *device_priv, void *init_hw_args, uint32_t arg_size); int cam_jpeg_dma_deinit_hw(void *device_priv, void *init_hw_args, uint32_t arg_size); +int cam_jpeg_dma_start_hw(void *device_priv, + void *start_hw_args, uint32_t arg_size); +int cam_jpeg_dma_stop_hw(void *device_priv, + void *stop_hw_args, uint32_t arg_size); +int cam_jpeg_dma_reset_hw(void *device_priv, + void *reset_hw_args, uint32_t arg_size); int cam_jpeg_dma_process_cmd(void *device_priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size); irqreturn_t cam_jpeg_dma_irq(int irq_num, void *data); diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c index fd4fdab19fa7..f91eee863352 100644 --- a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c +++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2018,2020 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -25,11 +25,7 @@ #include "cam_jpeg_hw_mgr_intf.h" #include "cam_cpas_api.h" #include "cam_debug_util.h" - -static struct cam_jpeg_dma_device_hw_info cam_jpeg_dma_hw_info = { - .reserved = 0, -}; -EXPORT_SYMBOL(cam_jpeg_dma_hw_info); +#include "cam_jpeg_dma_hw_info_ver_4_2_0.h" static int cam_jpeg_dma_register_cpas(struct cam_hw_soc_info *soc_info, struct cam_jpeg_dma_device_core_info *core_info, @@ -142,6 +138,9 @@ static int cam_jpeg_dma_probe(struct platform_device *pdev) jpeg_dma_dev_intf->hw_priv = jpeg_dma_dev; jpeg_dma_dev_intf->hw_ops.init = cam_jpeg_dma_init_hw; jpeg_dma_dev_intf->hw_ops.deinit = cam_jpeg_dma_deinit_hw; + jpeg_dma_dev_intf->hw_ops.start = cam_jpeg_dma_start_hw; + jpeg_dma_dev_intf->hw_ops.stop = cam_jpeg_dma_stop_hw; + jpeg_dma_dev_intf->hw_ops.reset = cam_jpeg_dma_reset_hw; jpeg_dma_dev_intf->hw_ops.process_cmd = cam_jpeg_dma_process_cmd; jpeg_dma_dev_intf->hw_type = CAM_JPEG_DEV_DMA; @@ -186,13 +185,11 @@ static int cam_jpeg_dma_probe(struct platform_device *pdev) mutex_init(&jpeg_dma_dev->hw_mutex); spin_lock_init(&jpeg_dma_dev->hw_lock); init_completion(&jpeg_dma_dev->hw_complete); - - CAM_DBG(CAM_JPEG, " hwidx %d", jpeg_dma_dev_intf->hw_idx); - + CAM_DBG(CAM_JPEG, "JPEG-DMA component bound successfully"); return rc; error_reg_cpas: - rc = cam_soc_util_release_platform_resource(&jpeg_dma_dev->soc_info); + cam_soc_util_release_platform_resource(&jpeg_dma_dev->soc_info); error_init_soc: mutex_destroy(&core_info->core_mutex); error_match_dev: diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c index 54dd62c44f67..196742d06448 100644 --- a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c +++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -350,7 +350,7 @@ int cam_jpeg_enc_start_hw(void *data, return -EINVAL; } spin_unlock(&jpeg_enc_dev->hw_lock); - + CAM_DBG(CAM_JPEG, "Starting JPEG ENC"); cam_io_w_mb(hw_info->reg_val.hw_cmd_start, mem_base + hw_info->reg_offset.hw_cmd); diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c index d4daa6dde308..be703d6c3055 100644 --- a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c +++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2018,2020 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -185,7 +185,7 @@ static int cam_jpeg_enc_probe(struct platform_device *pdev) mutex_init(&jpeg_enc_dev->hw_mutex); spin_lock_init(&jpeg_enc_dev->hw_lock); init_completion(&jpeg_enc_dev->hw_complete); - + CAM_DBG(CAM_JPEG, "JPEG-Encoder component bound successfully"); return rc; error_reg_cpas: From 5cebd006c92326f85aabdba329560c6e2ee79315 Mon Sep 17 00:00:00 2001 From: Wyes Karny Date: Wed, 6 May 2020 21:15:02 +0530 Subject: [PATCH 494/592] msm: camera: reqmgr: reset slots after deactivating session After Deactivate request comes in link control we are deactivating the link and resetting every slots in the in_q. CRs-Fixed: 2685198 Change-Id: I3f152d6486ccfe81ec44ea27ed992aacf18342bc Signed-off-by: Wyes Karny Signed-off-by: UtsavBalar1231 --- .../msm/camera/cam_req_mgr/cam_req_mgr_core.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c index dfbc9b07e4a4..bb0f1fdde118 100644 --- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c @@ -3422,6 +3422,8 @@ int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control) struct cam_req_mgr_connected_device *dev = NULL; struct cam_req_mgr_link_evt_data evt_data; + struct cam_req_mgr_req_queue *in_q = NULL; + struct cam_req_mgr_slot *slot = NULL; if (!control) { CAM_ERR(CAM_CRM, "Control command is NULL"); @@ -3485,6 +3487,18 @@ int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control) if (dev->ops && dev->ops->process_evt) dev->ops->process_evt(&evt_data); } + in_q = link->req.in_q; + /* reset all slots */ + for (j = 0; j < in_q->num_slots; j++) { + slot = &in_q->slot[j]; + slot->req_id = -1; + slot->sync_mode = + CAM_REQ_MGR_SYNC_MODE_NO_SYNC; + slot->skip_idx = 1; + slot->status = CRM_SLOT_STATUS_NO_REQ; + } + in_q->wr_idx = 0; + in_q->rd_idx = 0; } else { CAM_ERR(CAM_CRM, "Invalid link control command"); rc = -EINVAL; From ecb0d3109c158fe1281f9507305b45d9a7839c93 Mon Sep 17 00:00:00 2001 From: Tejas Prajapati Date: Thu, 11 Jun 2020 10:16:57 +0530 Subject: [PATCH 495/592] msm: camera: reqmgr: increase the rd idx if no lower pd device For link with maximum pipeline delay of 1 e.g., TPG use case or sensors with pipeline delay of 1, if the request is not submitted before 2 consecutive triggers we do not get chance to increment rd idx, in the mean time the slot which was last applied will be reset and we will not be able to apply request even if new requests are scheduled. This will cause the camera to not apply any request further, hence increasing the rd idx if no lower pd devices are pending will fix the issue. Change-Id: Ib2eddc9c6a0ce5e73cf19873c6ce54169e29a6e1 Signed-off-by: Tejas Prajapati Signed-off-by: UtsavBalar1231 --- .../media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c index bb0f1fdde118..6fa26b2eb13f 100644 --- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c @@ -2295,6 +2295,8 @@ static int cam_req_mgr_process_trigger(void *priv, void *data) CAM_DBG(CAM_REQ, "No pending req to apply to lower pd devices"); rc = 0; + __cam_req_mgr_inc_idx(&in_q->rd_idx, + 1, in_q->num_slots); goto release_lock; } __cam_req_mgr_inc_idx(&in_q->rd_idx, 1, in_q->num_slots); From cdf1cb75a147c48f4d2def7fd0adebf2ed734384 Mon Sep 17 00:00:00 2001 From: Ayush Kumar Date: Thu, 9 Apr 2020 02:44:09 +0530 Subject: [PATCH 496/592] msm: camera: reqmgr: Skip apply for initial sync req on slave link This change is to stop slave link to apply initial sync request in the same frame duration in which master apply initial sync request. Slave link should wait for the master link to apply initial sync request first and then slave should apply initial sync request in the next frame. Change-Id: I8f1f54bbf674df1c578e6041eaa08869949728b3 Signed-off-by: Ayush Kumar Signed-off-by: UtsavBalar1231 --- .../msm/camera/cam_req_mgr/cam_req_mgr_core.c | 47 +++++++++++++++++-- 1 file changed, 43 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c index 6fa26b2eb13f..f8211f50f49a 100644 --- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c @@ -696,13 +696,19 @@ static int32_t __cam_req_mgr_find_slot_for_req( */ static int __cam_req_mgr_check_sync_for_mslave( struct cam_req_mgr_core_link *link, - struct cam_req_mgr_slot *slot) + struct cam_req_mgr_slot *slot, + uint64_t request_id) { struct cam_req_mgr_core_link *sync_link = NULL; struct cam_req_mgr_slot *sync_slot = NULL; + struct cam_req_mgr_slot *sync_rd_slot = NULL; int sync_slot_idx = 0, prev_idx, next_idx, rd_idx, sync_rd_idx, rc = 0; int64_t req_id = 0, sync_req_id = 0; int32_t sync_num_slots = 0; + uint64_t sync_frame_duration = 0; + int32_t sync_req_status = 0; + uint64_t sof_timestamp_delta = 0; + int sync_link_idx = 0; if (!link->sync_link) { CAM_ERR(CAM_CRM, "Sync link null"); @@ -713,6 +719,12 @@ static int __cam_req_mgr_check_sync_for_mslave( req_id = slot->req_id; sync_num_slots = sync_link->req.in_q->num_slots; sync_rd_idx = sync_link->req.in_q->rd_idx; + sync_rd_slot = &sync_link->req.in_q->slot[sync_rd_idx]; + + sof_timestamp_delta = + link->sof_timestamp >= sync_link->sof_timestamp + ? link->sof_timestamp - sync_link->sof_timestamp + : sync_link->sof_timestamp - link->sof_timestamp; CAM_DBG(CAM_CRM, "link_hdl %x req %lld frame_skip_flag %d open_req_cnt:%d initial_sync_req [%lld,%lld] is_master:%d", @@ -742,6 +754,10 @@ static int __cam_req_mgr_check_sync_for_mslave( return -EINVAL; } + if (sync_link->prev_sof_timestamp) + sync_frame_duration = sync_link->sof_timestamp - + sync_link->prev_sof_timestamp; + if (link->is_master) { rc = __cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx); if (rc) { @@ -763,7 +779,6 @@ static int __cam_req_mgr_check_sync_for_mslave( CAM_DBG(CAM_CRM, "Req: %lld [master] not ready on link: %x, rc=%d", req_id, link->link_hdl, rc); - link->sync_link_sof_skip = true; return rc; } @@ -830,10 +845,34 @@ static int __cam_req_mgr_check_sync_for_mslave( CAM_DBG(CAM_CRM, "Req: %lld [slave] not ready on link: %x, rc=%d", req_id, link->link_hdl, rc); - link->sync_link_sof_skip = true; return rc; } + sync_link_idx = __cam_req_mgr_find_slot_for_req( + sync_link->req.in_q, request_id); + if (sync_link_idx != -1) { + sync_req_status = + sync_link->req.in_q->slot[sync_link_idx].status; + if (sync_req_status != CRM_SLOT_STATUS_REQ_APPLIED) { + CAM_DBG(CAM_CRM, + "Skipping initial sync req %lld id %d as master not applied", + request_id, sync_link_idx); + return -EINVAL; + } + } else + sync_req_status = 0; + + if ((sync_link->initial_sync_req == req_id) && + (sync_req_status == CRM_SLOT_STATUS_REQ_APPLIED) && + (sof_timestamp_delta < (sync_frame_duration / 2)) && + (((sync_link_idx - sync_rd_idx + sync_num_slots) % + sync_num_slots) <= 1) && + (sync_rd_slot->status != + CRM_SLOT_STATUS_REQ_APPLIED)) { + CAM_DBG(CAM_CRM, "Skipping initial sync req for slave"); + return -EINVAL; + } + next_idx = link->req.in_q->rd_idx; rd_idx = sync_link->req.in_q->rd_idx; __cam_req_mgr_inc_idx(&next_idx, @@ -1215,7 +1254,7 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, } rc = __cam_req_mgr_check_sync_for_mslave( - link, slot); + link, slot, trigger_data->req_id); } else { rc = __cam_req_mgr_check_sync_req_is_ready( link, slot); From eb9304619b069a62650221a215d15031179cc4f7 Mon Sep 17 00:00:00 2001 From: Ayush Kumar Date: Fri, 5 Jun 2020 00:55:14 +0530 Subject: [PATCH 497/592] msm: camera: core: Change return type Return different error number when new requests and update packets are rejected due to bad request id. This allows userspace to differentiate this specific reason for failure. Change-Id: I0b1e7086351b9438fd72a6d824bc20c8213b5ea8 Signed-off-by: Ayush Kumar Signed-off-by: UtsavBalar1231 --- drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c | 2 +- .../media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c index 78d9a6637135..18c3230b61a5 100644 --- a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c +++ b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c @@ -3363,7 +3363,7 @@ static int __cam_isp_ctx_config_dev_in_top_state( CAM_INFO(CAM_ISP, "request %lld has been flushed, reject packet", packet->header.request_id); - rc = -EINVAL; + rc = -EBADR; goto free_cpu_buf; } diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c index f8211f50f49a..1778a7a3d478 100644 --- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c @@ -3224,7 +3224,7 @@ int cam_req_mgr_schedule_request( CAM_INFO(CAM_CRM, "request %lld is flushed, last_flush_id to flush %u", sched_req->req_id, link->last_flush_id); - rc = -EINVAL; + rc = -EBADR; goto end; } From 9d4474be5a4d8b010884e83d12f54b396e26920e Mon Sep 17 00:00:00 2001 From: Shravan Nevatia Date: Fri, 20 Mar 2020 17:42:05 +0530 Subject: [PATCH 498/592] msm: camera: csiphy: Update phy settings for atoll Update the PHY (CPHY, DPHY, DPHY combo) sequences for csiphy v1.2.2 to align with HPG revision W. Change-Id: Ib25d958cacd1a9b0f51d6b749ba0d59a84def761 Signed-off-by: Shravan Nevatia Signed-off-by: UtsavBalar1231 --- .../include/cam_csiphy_1_2_2_hwreg.h | 166 +++++++++--------- 1 file changed, 79 insertions(+), 87 deletions(-) diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_2_hwreg.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_2_hwreg.h index 51ffc1872af4..0aa91d58767a 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_2_hwreg.h +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_2_hwreg.h @@ -19,10 +19,10 @@ struct csiphy_reg_parms_t csiphy_v1_2_2 = { .mipi_csiphy_interrupt_status0_addr = 0x8B0, .mipi_csiphy_interrupt_clear0_addr = 0x858, .mipi_csiphy_glbl_irq_cmd_addr = 0x828, - .csiphy_common_array_size = 7, + .csiphy_common_array_size = 6, .csiphy_reset_array_size = 5, - .csiphy_2ph_config_array_size = 22, - .csiphy_3ph_config_array_size = 38, + .csiphy_2ph_config_array_size = 23, + .csiphy_3ph_config_array_size = 30, .csiphy_2ph_clock_lane = 0x1, .csiphy_2ph_combo_ck_ln = 0x10, }; @@ -30,8 +30,7 @@ struct csiphy_reg_parms_t csiphy_v1_2_2 = { struct csiphy_reg_t csiphy_common_reg_1_2_2[] = { {0x0814, 0xd5, 0x00, CSIPHY_LANE_ENABLE}, {0x0818, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x081C, 0x02, 0x00, CSIPHY_2PH_REGS}, - {0x081C, 0x52, 0x00, CSIPHY_3PH_REGS}, + {0x081C, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x03, 0x01, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x02, 0x00, CSIPHY_2PH_REGS}, {0x0800, 0x0E, 0x00, CSIPHY_3PH_REGS}, @@ -65,34 +64,34 @@ csiphy_reg_t csiphy_2ph_v1_2_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0030, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0904, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0910, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0900, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0908, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0900, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0908, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0904, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x00C4, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x002C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0034, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0010, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x001C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0014, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0028, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0028, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x003C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0000, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0020, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0008, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x000c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x005C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0060, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0x00, 0x00, CSIPHY_DNP_PARAMS}, }, { {0x0730, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0C84, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0C90, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0C80, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0C88, 0x14, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C88, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0C84, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x07C4, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x072C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0734, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0710, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -108,78 +107,83 @@ csiphy_reg_t csiphy_2ph_v1_2_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0710, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0000, 0x00, 0x00, CSIPHY_DNP_PARAMS}, }, { {0x0230, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A10, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A00, 0x0B, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A08, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A00, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A08, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x02C4, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x022C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0234, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0210, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x021C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0214, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0228, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0228, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x023C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0200, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0204, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0220, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0208, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x020c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0210, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x025C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0260, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0x00, 0x00, CSIPHY_DNP_PARAMS}, }, { {0x0430, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B10, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0B00, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0B08, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B00, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B08, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x04C4, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x042C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0434, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0410, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x041C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0414, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0428, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0428, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x043C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0400, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0404, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0420, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0408, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x040c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x045C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0460, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0x00, 0x00, CSIPHY_DNP_PARAMS}, }, { {0x0630, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0C04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0C10, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0C00, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0C08, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C00, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C08, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0C04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x06C4, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x062C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0634, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0610, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x061C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0614, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0628, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0628, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x063C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0600, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0604, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0620, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0608, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x060c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0610, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0638, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x065C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0660, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0x00, 0x00, CSIPHY_DNP_PARAMS}, }, }; @@ -189,34 +193,34 @@ struct csiphy_reg_t {0x0030, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0904, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0910, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0900, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0908, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0900, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0908, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0904, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x00C4, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x002C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0034, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0010, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x001C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0014, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0028, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x003C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0000, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0020, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0008, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x000c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x005C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0060, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0000, 0x00, 0x00, CSIPHY_DNP_PARAMS}, }, { {0x0730, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0C84, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0C90, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0C80, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0C88, 0x14, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C88, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0C84, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x07C4, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x072C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0734, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0710, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -231,40 +235,42 @@ struct csiphy_reg_t {0x070c, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0710, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x075C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0760, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { {0x0230, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A10, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A00, 0x0B, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A08, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A00, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A08, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x02C4, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x022C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0234, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0210, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x021C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0214, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0228, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x023C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0200, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0204, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0220, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0208, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x020c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0210, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x025C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0260, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0000, 0x00, 0x00, CSIPHY_DNP_PARAMS}, }, { {0x0430, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B10, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0B00, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0B08, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B00, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B08, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x04C4, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x042C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0434, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0410, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -276,19 +282,20 @@ struct csiphy_reg_t {0x0404, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0420, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0408, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x040c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x045C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0460, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0x00, 0x00, CSIPHY_DNP_PARAMS}, }, { {0x0630, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0C04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0C10, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0C00, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0C08, 0x14, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C00, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C08, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0C04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x06C4, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x062C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0634, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0610, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -296,14 +303,16 @@ struct csiphy_reg_t {0x0614, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0628, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x063C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0600, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0600, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0604, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0620, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0608, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x060c, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0610, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0638, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x065C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0660, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, }, }; @@ -311,9 +320,6 @@ struct csiphy_reg_t csiphy_3ph_v1_2_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { { {0x015C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0990, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0994, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0998, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0990, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0994, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0998, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -339,25 +345,17 @@ csiphy_reg_t csiphy_3ph_v1_2_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x01CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0164, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x01DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x09C0, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x09C4, 0x7D, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x09C8, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0984, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0988, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0980, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x09B0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x09B4, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { {0x035C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A90, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A98, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A90, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A94, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A98, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A8C, 0xBF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A98, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A8C, 0xAF, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0368, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x036C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0304, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -379,21 +377,13 @@ csiphy_reg_t csiphy_3ph_v1_2_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x03CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0364, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x03DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0AC0, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0AC4, 0x7D, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0AC8, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A84, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0AB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0AB4, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { {0x055C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0B90, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0B94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0B98, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B90, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B94, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B98, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -419,12 +409,7 @@ csiphy_reg_t csiphy_3ph_v1_2_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x05CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0564, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x05DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0BC0, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0BC4, 0x7D, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0BC8, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B84, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0B88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0B80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0BB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0BB4, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -437,7 +422,7 @@ struct data_rate_settings_t data_rate_delta_table_1_2_2 = { { /* (2.5 * 10**3 * 2.28) rounded value*/ .bandwidth = 5700000000, - .data_rate_reg_array_size = 8, + .data_rate_reg_array_size = 6, .csiphy_data_rate_regs = { {0x144, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x344, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -445,14 +430,12 @@ struct data_rate_settings_t data_rate_delta_table_1_2_2 = { {0x984, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, {0xA84, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, {0xB84, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A98, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A8C, 0xBF, 0x00, CSIPHY_DEFAULT_PARAMS}, } }, { /* (3.5 * 10**3 * 2.28) rounded value */ .bandwidth = 7980000000, - .data_rate_reg_array_size = 8, + .data_rate_reg_array_size = 12, .csiphy_data_rate_regs = { {0x144, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x344, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -460,14 +443,18 @@ struct data_rate_settings_t data_rate_delta_table_1_2_2 = { {0x984, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, {0xA84, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, {0xB84, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A98, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A8C, 0xAF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0988, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0980, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, }, }, { /* (4.5 * 10**3 * 2.28) rounded value */ .bandwidth = 10260000000, - .data_rate_reg_array_size = 8, + .data_rate_reg_array_size = 12, .csiphy_data_rate_regs = { {0x144, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x344, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -475,8 +462,13 @@ struct data_rate_settings_t data_rate_delta_table_1_2_2 = { {0x984, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, {0xA84, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, {0xB84, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A98, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A8C, 0xAF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0988, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0980, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, } } From 33f2ed79c3858864a805277a064566c487659153 Mon Sep 17 00:00:00 2001 From: Siva Kumar Akkireddi Date: Thu, 18 Jun 2020 21:34:25 +0530 Subject: [PATCH 499/592] msm: mhi_dev: Fix memory leak mhi_dev_cache_host_cfg will be called during cold boot and also when processing mhi device reset command from host. Do not re-allocate the command, event and channel context cache memory if they were already allocated. Change-Id: I55826e05b3d83c9fcf3d4b23e26b91253130671e Signed-off-by: Siva Kumar Akkireddi Signed-off-by: UtsavBalar1231 --- drivers/platform/msm/mhi_dev/mhi.c | 73 +++++++++++++++++++++--------- 1 file changed, 52 insertions(+), 21 deletions(-) diff --git a/drivers/platform/msm/mhi_dev/mhi.c b/drivers/platform/msm/mhi_dev/mhi.c index f2336be13d8d..519d8393323c 100644 --- a/drivers/platform/msm/mhi_dev/mhi.c +++ b/drivers/platform/msm/mhi_dev/mhi.c @@ -2406,34 +2406,51 @@ static int mhi_dev_cache_host_cfg(struct mhi_dev *mhi) mhi->cfg.event_rings; mhi->ch_ctx_shadow.size = sizeof(struct mhi_dev_ch_ctx) * mhi->cfg.channels; - - mhi->cmd_ctx_cache = dma_alloc_coherent(&pdev->dev, - sizeof(struct mhi_dev_cmd_ctx), - &mhi->cmd_ctx_cache_dma_handle, - GFP_KERNEL); + /* + * This func mhi_dev_cache_host_cfg will be called when + * processing mhi device reset as well, do not allocate + * the command, event and channel context caches if they + * were already allocated during device boot, to avoid + * memory leak. + */ if (!mhi->cmd_ctx_cache) { - pr_err("no memory while allocating cmd ctx\n"); - return -ENOMEM; + mhi->cmd_ctx_cache = dma_alloc_coherent(&pdev->dev, + sizeof(struct mhi_dev_cmd_ctx), + &mhi->cmd_ctx_cache_dma_handle, + GFP_KERNEL); + if (!mhi->cmd_ctx_cache) { + pr_err("no memory while allocating cmd ctx\n"); + rc = -ENOMEM; + goto exit; + } } memset(mhi->cmd_ctx_cache, 0, sizeof(struct mhi_dev_cmd_ctx)); - mhi->ev_ctx_cache = dma_alloc_coherent(&pdev->dev, - sizeof(struct mhi_dev_ev_ctx) * - mhi->cfg.event_rings, - &mhi->ev_ctx_cache_dma_handle, - GFP_KERNEL); - if (!mhi->ev_ctx_cache) - return -ENOMEM; + if (!mhi->ev_ctx_cache) { + mhi->ev_ctx_cache = dma_alloc_coherent(&pdev->dev, + sizeof(struct mhi_dev_ev_ctx) * + mhi->cfg.event_rings, + &mhi->ev_ctx_cache_dma_handle, + GFP_KERNEL); + if (!mhi->ev_ctx_cache) { + rc = -ENOMEM; + goto exit; + } + } memset(mhi->ev_ctx_cache, 0, sizeof(struct mhi_dev_ev_ctx) * mhi->cfg.event_rings); - mhi->ch_ctx_cache = dma_alloc_coherent(&pdev->dev, - sizeof(struct mhi_dev_ch_ctx) * - mhi->cfg.channels, - &mhi->ch_ctx_cache_dma_handle, - GFP_KERNEL); - if (!mhi->ch_ctx_cache) - return -ENOMEM; + if (!mhi->ch_ctx_cache) { + mhi->ch_ctx_cache = dma_alloc_coherent(&pdev->dev, + sizeof(struct mhi_dev_ch_ctx) * + mhi->cfg.channels, + &mhi->ch_ctx_cache_dma_handle, + GFP_KERNEL); + if (!mhi->ch_ctx_cache) { + rc = -ENOMEM; + goto exit; + } + } memset(mhi->ch_ctx_cache, 0, sizeof(struct mhi_dev_ch_ctx) * mhi->cfg.channels); @@ -2469,6 +2486,20 @@ static int mhi_dev_cache_host_cfg(struct mhi_dev *mhi) return mhi_ring_start(&mhi->ring[0], (union mhi_dev_ring_ctx *)mhi->cmd_ctx_cache, mhi); + +exit: + if (mhi->cmd_ctx_cache) + dma_free_coherent(&pdev->dev, + sizeof(struct mhi_dev_cmd_ctx), + mhi->cmd_ctx_cache, + mhi->cmd_ctx_cache_dma_handle); + if (mhi->ev_ctx_cache) + dma_free_coherent(&pdev->dev, + sizeof(struct mhi_dev_ev_ctx) * + mhi->cfg.event_rings, + mhi->ev_ctx_cache, + mhi->ev_ctx_cache_dma_handle); + return rc; } void mhi_dev_pm_relax(void) From 455b230d63ef03176cd0f51f652524dc1fa264a6 Mon Sep 17 00:00:00 2001 From: Ayush Kumar Date: Fri, 17 Apr 2020 18:48:22 +0530 Subject: [PATCH 500/592] msm: camera: reqmgr: Stop slot reset on buf done This change is to stop slot reset on link in case of buf done. If slot is required for applying either next or previous request on sync link, then stop the slot reset for the link. Change-Id: I296e450de94e273d17b1a9bb0879d879a63414f4 Signed-off-by: Ayush Kumar Signed-off-by: UtsavBalar1231 --- .../msm/camera/cam_req_mgr/cam_req_mgr_core.c | 54 ++++++++++++++++--- 1 file changed, 48 insertions(+), 6 deletions(-) diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c index 1778a7a3d478..2969baaaceeb 100644 --- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c @@ -2257,6 +2257,42 @@ end: return rc; } +static void cam_req_mgr_process_reset_for_dual_link( + struct cam_req_mgr_core_link *link, + struct cam_req_mgr_trigger_notify *trigger_data) +{ + int32_t idx = -1; + int32_t sync_idx = -1; + struct cam_req_mgr_req_queue *in_q = NULL; + struct cam_req_mgr_req_queue *sync_in_q = NULL; + + in_q = link->req.in_q; + sync_in_q = link->sync_link->req.in_q; + + sync_idx = __cam_req_mgr_find_slot_for_req(sync_in_q, + trigger_data->req_id); + if (link->is_master) + __cam_req_mgr_dec_idx(&sync_idx, + (link->max_delay - link->sync_link->max_delay), + sync_in_q->num_slots); + else + __cam_req_mgr_inc_idx(&sync_idx, + (link->sync_link->max_delay - link->max_delay), + sync_in_q->num_slots); + if (sync_idx != -1 && + (sync_in_q->slot[sync_in_q->rd_idx].status == + CRM_SLOT_STATUS_REQ_APPLIED)) { + idx = __cam_req_mgr_find_slot_for_req(in_q, + trigger_data->req_id); + CAM_DBG(CAM_CRM, "Reset req: %lld idx: %d link_hdl: %x", + trigger_data->req_id, idx, + link->link_hdl); + if (idx == in_q->last_applied_idx) + in_q->last_applied_idx = -1; + __cam_req_mgr_reset_req_slot(link, idx); + } +} + /** * cam_req_mgr_process_trigger() * @@ -2295,12 +2331,18 @@ static int cam_req_mgr_process_trigger(void *priv, void *data) mutex_lock(&link->req.lock); if (trigger_data->trigger == CAM_TRIGGER_POINT_SOF) { - idx = __cam_req_mgr_find_slot_for_req(in_q, - trigger_data->req_id); - if (idx >= 0) { - if (idx == in_q->last_applied_idx) - in_q->last_applied_idx = -1; - __cam_req_mgr_reset_req_slot(link, idx); + if (link->sync_link && + (link->is_master || link->sync_link->is_master)) { + cam_req_mgr_process_reset_for_dual_link(link, + trigger_data); + } else { + idx = __cam_req_mgr_find_slot_for_req(in_q, + trigger_data->req_id); + if (idx >= 0) { + if (idx == in_q->last_applied_idx) + in_q->last_applied_idx = -1; + __cam_req_mgr_reset_req_slot(link, idx); + } } } From ca3a48c281e1dec5454ae336ddf5f334e67df7d3 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Mon, 11 Jun 2018 14:35:55 -0700 Subject: [PATCH 501/592] mm: Introduce kvcalloc() The kv*alloc()-family was missing kvcalloc(). Adding this allows for 2-argument multiplication conversions of kvzalloc(a * b, ...) into kvcalloc(a, b, ...). Signed-off-by: Kees Cook Signed-off-by: UtsavBalar1231 --- include/linux/mm.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/linux/mm.h b/include/linux/mm.h index 3ae0470c3f6c..5bb606bc22ac 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -571,6 +571,11 @@ static inline void *kvmalloc_array(size_t n, size_t size, gfp_t flags) return kvmalloc(n * size, flags); } +static inline void *kvcalloc(size_t n, size_t size, gfp_t flags) +{ + return kvmalloc_array(n, size, flags | __GFP_ZERO); +} + extern void kvfree(const void *addr); extern void kvfree_sensitive(const void *addr, size_t len); From 5153386ce34f743cf5eff962a561b07e47db6ee8 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Mon, 11 Mar 2019 23:31:10 -0700 Subject: [PATCH 502/592] BACKPORT: selinux: convert to kvmalloc The flex arrays were being used for constant sized arrays, so there's no benefit to using flex_arrays over something simpler. Link: http://lkml.kernel.org/r/20181217131929.11727-4-kent.overstreet@gmail.com Signed-off-by: Kent Overstreet Cc: Paul Moore Cc: Stephen Smalley Cc: Eric Paris Cc: Alexey Dobriyan Cc: Al Viro Cc: Dave Hansen Cc: Marcelo Ricardo Leitner Cc: Matthew Wilcox Cc: Neil Horman Cc: Pravin B Shelar Cc: Shaohua Li Cc: Vlad Yasevich Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Yaroslav Furman Signed-off-by: UtsavBalar1231 --- security/selinux/ss/avtab.c | 40 +++++----- security/selinux/ss/avtab.h | 4 +- security/selinux/ss/conditional.c | 6 +- security/selinux/ss/policydb.c | 122 ++++++++---------------------- security/selinux/ss/policydb.h | 12 +-- security/selinux/ss/services.c | 22 ++---- 6 files changed, 62 insertions(+), 144 deletions(-) diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c index a2c9148b0662..4bd3ffe5e5f8 100644 --- a/security/selinux/ss/avtab.c +++ b/security/selinux/ss/avtab.c @@ -93,12 +93,10 @@ avtab_insert_node(struct avtab *h, int hvalue, newnode->next = prev->next; prev->next = newnode; } else { - newnode->next = flex_array_get_ptr(h->htable, hvalue); - if (flex_array_put_ptr(h->htable, hvalue, newnode, - GFP_KERNEL|__GFP_ZERO)) { - kmem_cache_free(avtab_node_cachep, newnode); - return NULL; - } + struct avtab_node **n = &h->htable[hvalue]; + + newnode->next = *n; + *n = newnode; } h->nel++; @@ -111,11 +109,11 @@ static int avtab_insert(struct avtab *h, struct avtab_key *key, struct avtab_dat struct avtab_node *prev, *cur, *newnode; u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); - if (!h || !h->htable) + if (!h) return -EINVAL; hvalue = avtab_hash(key, h->mask); - for (prev = NULL, cur = flex_array_get_ptr(h->htable, hvalue); + for (prev = NULL, cur = h->htable[hvalue]; cur; prev = cur, cur = cur->next) { if (key->source_type == cur->key.source_type && @@ -156,10 +154,10 @@ avtab_insert_nonunique(struct avtab *h, struct avtab_key *key, struct avtab_datu struct avtab_node *prev, *cur; u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); - if (!h || !h->htable) + if (!h) return NULL; hvalue = avtab_hash(key, h->mask); - for (prev = NULL, cur = flex_array_get_ptr(h->htable, hvalue); + for (prev = NULL, cur = h->htable[hvalue]; cur; prev = cur, cur = cur->next) { if (key->source_type == cur->key.source_type && @@ -186,11 +184,11 @@ struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key) struct avtab_node *cur; u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); - if (!h || !h->htable) + if (!h) return NULL; hvalue = avtab_hash(key, h->mask); - for (cur = flex_array_get_ptr(h->htable, hvalue); cur; + for (cur = h->htable[hvalue]; cur; cur = cur->next) { if (key->source_type == cur->key.source_type && key->target_type == cur->key.target_type && @@ -222,11 +220,11 @@ avtab_search_node(struct avtab *h, struct avtab_key *key) struct avtab_node *cur; u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); - if (!h || !h->htable) + if (!h) return NULL; hvalue = avtab_hash(key, h->mask); - for (cur = flex_array_get_ptr(h->htable, hvalue); cur; + for (cur = h->htable[hvalue]; cur; cur = cur->next) { if (key->source_type == cur->key.source_type && key->target_type == cur->key.target_type && @@ -281,11 +279,11 @@ void avtab_destroy(struct avtab *h) int i; struct avtab_node *cur, *temp; - if (!h || !h->htable) + if (!h) return; for (i = 0; i < h->nslot; i++) { - cur = flex_array_get_ptr(h->htable, i); + cur = h->htable[i]; while (cur) { temp = cur; cur = cur->next; @@ -295,7 +293,7 @@ void avtab_destroy(struct avtab *h) kmem_cache_free(avtab_node_cachep, temp); } } - flex_array_free(h->htable); + kvfree(h->htable); h->htable = NULL; h->nslot = 0; h->mask = 0; @@ -303,6 +301,7 @@ void avtab_destroy(struct avtab *h) int avtab_init(struct avtab *h) { + kvfree(h->htable); h->htable = NULL; h->nel = 0; return 0; @@ -329,8 +328,7 @@ int avtab_alloc(struct avtab *h, u32 nrules) nslot = MAX_AVTAB_HASH_BUCKETS; mask = nslot - 1; - h->htable = flex_array_alloc(sizeof(struct avtab_node *), nslot, - GFP_KERNEL | __GFP_ZERO); + h->htable = kvcalloc(nslot, sizeof(void *), GFP_KERNEL); if (!h->htable) return -ENOMEM; @@ -353,7 +351,7 @@ void avtab_hash_eval(struct avtab *h, char *tag) max_chain_len = 0; chain2_len_sum = 0; for (i = 0; i < h->nslot; i++) { - cur = flex_array_get_ptr(h->htable, i); + cur = h->htable[i]; if (cur) { slots_used++; chain_len = 0; @@ -645,7 +643,7 @@ int avtab_write(struct policydb *p, struct avtab *a, void *fp) return rc; for (i = 0; i < a->nslot; i++) { - for (cur = flex_array_get_ptr(a->htable, i); cur; + for (cur = a->htable[i]; cur; cur = cur->next) { rc = avtab_write_item(p, cur, fp); if (rc) diff --git a/security/selinux/ss/avtab.h b/security/selinux/ss/avtab.h index 0d652fad5319..de16673b2314 100644 --- a/security/selinux/ss/avtab.h +++ b/security/selinux/ss/avtab.h @@ -24,7 +24,6 @@ #define _SS_AVTAB_H_ #include "security.h" -#include struct avtab_key { u16 source_type; /* source type */ @@ -84,11 +83,10 @@ struct avtab_node { }; struct avtab { - struct flex_array *htable; + struct avtab_node **htable; u32 nel; /* number of elements */ u32 nslot; /* number of hash slots */ u32 mask; /* mask to compute hash func */ - }; int avtab_init(struct avtab *); diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c index 771c96afe1d5..850956fe5703 100644 --- a/security/selinux/ss/conditional.c +++ b/security/selinux/ss/conditional.c @@ -195,7 +195,6 @@ int cond_index_bool(void *key, void *datum, void *datap) { struct policydb *p; struct cond_bool_datum *booldatum; - struct flex_array *fa; booldatum = datum; p = datap; @@ -203,10 +202,7 @@ int cond_index_bool(void *key, void *datum, void *datap) if (!booldatum->value || booldatum->value > p->p_bools.nprim) return -EINVAL; - fa = p->sym_val_to_name[SYM_BOOLS]; - if (flex_array_put_ptr(fa, booldatum->value - 1, key, - GFP_KERNEL | __GFP_ZERO)) - BUG(); + p->sym_val_to_name[SYM_BOOLS][booldatum->value - 1] = key; p->bool_val_to_struct[booldatum->value - 1] = booldatum; return 0; diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index 2472b2a66f70..a83bba47efe1 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c @@ -36,7 +36,6 @@ #include #include #include -#include #include "security.h" #include "policydb.h" @@ -346,17 +345,14 @@ static int common_index(void *key, void *datum, void *datap) { struct policydb *p; struct common_datum *comdatum; - struct flex_array *fa; comdatum = datum; p = datap; if (!comdatum->value || comdatum->value > p->p_commons.nprim) return -EINVAL; - fa = p->sym_val_to_name[SYM_COMMONS]; - if (flex_array_put_ptr(fa, comdatum->value - 1, key, - GFP_KERNEL | __GFP_ZERO)) - BUG(); + p->sym_val_to_name[SYM_COMMONS][comdatum->value - 1] = key; + return 0; } @@ -364,16 +360,13 @@ static int class_index(void *key, void *datum, void *datap) { struct policydb *p; struct class_datum *cladatum; - struct flex_array *fa; cladatum = datum; p = datap; if (!cladatum->value || cladatum->value > p->p_classes.nprim) return -EINVAL; - fa = p->sym_val_to_name[SYM_CLASSES]; - if (flex_array_put_ptr(fa, cladatum->value - 1, key, - GFP_KERNEL | __GFP_ZERO)) - BUG(); + + p->sym_val_to_name[SYM_CLASSES][cladatum->value - 1] = key; p->class_val_to_struct[cladatum->value - 1] = cladatum; return 0; } @@ -382,7 +375,6 @@ static int role_index(void *key, void *datum, void *datap) { struct policydb *p; struct role_datum *role; - struct flex_array *fa; role = datum; p = datap; @@ -391,10 +383,7 @@ static int role_index(void *key, void *datum, void *datap) || role->bounds > p->p_roles.nprim) return -EINVAL; - fa = p->sym_val_to_name[SYM_ROLES]; - if (flex_array_put_ptr(fa, role->value - 1, key, - GFP_KERNEL | __GFP_ZERO)) - BUG(); + p->sym_val_to_name[SYM_ROLES][role->value - 1] = key; p->role_val_to_struct[role->value - 1] = role; return 0; } @@ -403,7 +392,6 @@ static int type_index(void *key, void *datum, void *datap) { struct policydb *p; struct type_datum *typdatum; - struct flex_array *fa; typdatum = datum; p = datap; @@ -413,15 +401,8 @@ static int type_index(void *key, void *datum, void *datap) || typdatum->value > p->p_types.nprim || typdatum->bounds > p->p_types.nprim) return -EINVAL; - fa = p->sym_val_to_name[SYM_TYPES]; - if (flex_array_put_ptr(fa, typdatum->value - 1, key, - GFP_KERNEL | __GFP_ZERO)) - BUG(); - - fa = p->type_val_to_struct_array; - if (flex_array_put_ptr(fa, typdatum->value - 1, typdatum, - GFP_KERNEL | __GFP_ZERO)) - BUG(); + p->sym_val_to_name[SYM_TYPES][typdatum->value - 1] = key; + p->type_val_to_struct_array[typdatum->value - 1] = typdatum; } return 0; @@ -431,7 +412,6 @@ static int user_index(void *key, void *datum, void *datap) { struct policydb *p; struct user_datum *usrdatum; - struct flex_array *fa; usrdatum = datum; p = datap; @@ -440,10 +420,7 @@ static int user_index(void *key, void *datum, void *datap) || usrdatum->bounds > p->p_users.nprim) return -EINVAL; - fa = p->sym_val_to_name[SYM_USERS]; - if (flex_array_put_ptr(fa, usrdatum->value - 1, key, - GFP_KERNEL | __GFP_ZERO)) - BUG(); + p->sym_val_to_name[SYM_USERS][usrdatum->value - 1] = key; p->user_val_to_struct[usrdatum->value - 1] = usrdatum; return 0; } @@ -452,7 +429,6 @@ static int sens_index(void *key, void *datum, void *datap) { struct policydb *p; struct level_datum *levdatum; - struct flex_array *fa; levdatum = datum; p = datap; @@ -461,10 +437,8 @@ static int sens_index(void *key, void *datum, void *datap) if (!levdatum->level->sens || levdatum->level->sens > p->p_levels.nprim) return -EINVAL; - fa = p->sym_val_to_name[SYM_LEVELS]; - if (flex_array_put_ptr(fa, levdatum->level->sens - 1, key, - GFP_KERNEL | __GFP_ZERO)) - BUG(); + + p->sym_val_to_name[SYM_LEVELS][levdatum->level->sens - 1] = key; } return 0; @@ -474,7 +448,6 @@ static int cat_index(void *key, void *datum, void *datap) { struct policydb *p; struct cat_datum *catdatum; - struct flex_array *fa; catdatum = datum; p = datap; @@ -482,10 +455,8 @@ static int cat_index(void *key, void *datum, void *datap) if (!catdatum->isalias) { if (!catdatum->value || catdatum->value > p->p_cats.nprim) return -EINVAL; - fa = p->sym_val_to_name[SYM_CATS]; - if (flex_array_put_ptr(fa, catdatum->value - 1, key, - GFP_KERNEL | __GFP_ZERO)) - BUG(); + + p->sym_val_to_name[SYM_CATS][catdatum->value - 1] = key; } return 0; @@ -571,35 +542,23 @@ static int policydb_index(struct policydb *p) if (!p->user_val_to_struct) return -ENOMEM; - /* Yes, I want the sizeof the pointer, not the structure */ - p->type_val_to_struct_array = flex_array_alloc(sizeof(struct type_datum *), - p->p_types.nprim, - GFP_KERNEL | __GFP_ZERO); + p->type_val_to_struct_array = kvcalloc(p->p_types.nprim, + sizeof(*p->type_val_to_struct_array), + GFP_KERNEL); if (!p->type_val_to_struct_array) return -ENOMEM; - rc = flex_array_prealloc(p->type_val_to_struct_array, 0, - p->p_types.nprim, GFP_KERNEL | __GFP_ZERO); - if (rc) - goto out; - rc = cond_init_bool_indexes(p); if (rc) goto out; for (i = 0; i < SYM_NUM; i++) { - p->sym_val_to_name[i] = flex_array_alloc(sizeof(char *), - p->symtab[i].nprim, - GFP_KERNEL | __GFP_ZERO); + p->sym_val_to_name[i] = kvcalloc(p->symtab[i].nprim, + sizeof(char *), + GFP_KERNEL); if (!p->sym_val_to_name[i]) return -ENOMEM; - rc = flex_array_prealloc(p->sym_val_to_name[i], - 0, p->symtab[i].nprim, - GFP_KERNEL | __GFP_ZERO); - if (rc) - goto out; - rc = hashtab_map(p->symtab[i].table, index_f[i], p); if (rc) goto out; @@ -813,16 +772,13 @@ void policydb_destroy(struct policydb *p) hashtab_destroy(p->symtab[i].table); } - for (i = 0; i < SYM_NUM; i++) { - if (p->sym_val_to_name[i]) - flex_array_free(p->sym_val_to_name[i]); - } + for (i = 0; i < SYM_NUM; i++) + kvfree(p->sym_val_to_name[i]); kfree(p->class_val_to_struct); kfree(p->role_val_to_struct); kfree(p->user_val_to_struct); - if (p->type_val_to_struct_array) - flex_array_free(p->type_val_to_struct_array); + kvfree(p->type_val_to_struct_array); avtab_destroy(&p->te_avtab); @@ -875,17 +831,9 @@ void policydb_destroy(struct policydb *p) hashtab_map(p->range_tr, range_tr_destroy, NULL); hashtab_destroy(p->range_tr); - if (p->type_attr_map_array) { - for (i = 0; i < p->p_types.nprim; i++) { - struct ebitmap *e; - - e = flex_array_get(p->type_attr_map_array, i); - if (!e) - continue; - ebitmap_destroy(e); - } - flex_array_free(p->type_attr_map_array); - } + for (i = 0; i < p->p_types.nprim; i++) + ebitmap_destroy(&p->type_attr_map_array[i]); + kvfree(p->type_attr_map_array); ebitmap_destroy(&p->filename_trans_ttypes); ebitmap_destroy(&p->policycaps); @@ -1779,8 +1727,7 @@ static int type_bounds_sanity_check(void *key, void *datum, void *datap) return -EINVAL; } - upper = flex_array_get_ptr(p->type_val_to_struct_array, - upper->bounds - 1); + upper = p->type_val_to_struct_array[upper->bounds - 1]; BUG_ON(!upper); if (upper->attribute) { @@ -2556,23 +2503,15 @@ int policydb_read(struct policydb *p, void *fp) if (rc) goto bad; - rc = -ENOMEM; - p->type_attr_map_array = flex_array_alloc(sizeof(struct ebitmap), - p->p_types.nprim, - GFP_KERNEL | __GFP_ZERO); + p->type_attr_map_array = kvcalloc(p->p_types.nprim, + sizeof(*p->type_attr_map_array), + GFP_KERNEL); if (!p->type_attr_map_array) goto bad; - /* preallocate so we don't have to worry about the put ever failing */ - rc = flex_array_prealloc(p->type_attr_map_array, 0, p->p_types.nprim, - GFP_KERNEL | __GFP_ZERO); - if (rc) - goto bad; - for (i = 0; i < p->p_types.nprim; i++) { - struct ebitmap *e = flex_array_get(p->type_attr_map_array, i); + struct ebitmap *e = &p->type_attr_map_array[i]; - BUG_ON(!e); ebitmap_init(e); if (p->policyvers >= POLICYDB_VERSION_AVTAB) { rc = ebitmap_read(e, fp); @@ -3567,9 +3506,8 @@ int policydb_write(struct policydb *p, void *fp) return rc; for (i = 0; i < p->p_types.nprim; i++) { - struct ebitmap *e = flex_array_get(p->type_attr_map_array, i); + struct ebitmap *e = &p->type_attr_map_array[i]; - BUG_ON(!e); rc = ebitmap_write(e, fp); if (rc) return rc; diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h index dbb0ed57ed8b..caa20320e574 100644 --- a/security/selinux/ss/policydb.h +++ b/security/selinux/ss/policydb.h @@ -24,8 +24,6 @@ #ifndef _SS_POLICYDB_H_ #define _SS_POLICYDB_H_ -#include - #include "symtab.h" #include "avtab.h" #include "sidtab.h" @@ -252,13 +250,13 @@ struct policydb { #define p_cats symtab[SYM_CATS] /* symbol names indexed by (value - 1) */ - struct flex_array *sym_val_to_name[SYM_NUM]; + char **sym_val_to_name[SYM_NUM]; /* class, role, and user attributes indexed by (value - 1) */ struct class_datum **class_val_to_struct; struct role_datum **role_val_to_struct; struct user_datum **user_val_to_struct; - struct flex_array *type_val_to_struct_array; + struct type_datum **type_val_to_struct_array; /* type enforcement access vectors and transitions */ struct avtab te_avtab; @@ -295,7 +293,7 @@ struct policydb { struct hashtab *range_tr; /* type -> attribute reverse mapping */ - struct flex_array *type_attr_map_array; + struct ebitmap *type_attr_map_array; struct ebitmap policycaps; @@ -371,9 +369,7 @@ static inline int put_entry(const void *buf, size_t bytes, int num, struct polic static inline char *sym_name(struct policydb *p, unsigned int sym_num, unsigned int element_nr) { - struct flex_array *fa = p->sym_val_to_name[sym_num]; - - return flex_array_get_ptr(fa, element_nr); + return p->sym_val_to_name[sym_num][element_nr]; } extern u16 string_to_security_class(struct policydb *p, const char *name); diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 289a9f5672a4..c4954df5911a 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -50,7 +50,6 @@ #include #include #include -#include #include #include @@ -546,15 +545,13 @@ static void type_attribute_bounds_av(struct policydb *policydb, struct type_datum *target; u32 masked = 0; - source = flex_array_get_ptr(policydb->type_val_to_struct_array, - scontext->type - 1); + source = policydb->type_val_to_struct_array[scontext->type - 1]; BUG_ON(!source); if (!source->bounds) return; - target = flex_array_get_ptr(policydb->type_val_to_struct_array, - tcontext->type - 1); + target = policydb->type_val_to_struct_array[tcontext->type - 1]; BUG_ON(!target); memset(&lo_avd, 0, sizeof(lo_avd)); @@ -654,11 +651,9 @@ static void context_struct_compute_av(struct policydb *policydb, */ avkey.target_class = tclass; avkey.specified = AVTAB_AV | AVTAB_XPERMS; - sattr = flex_array_get(policydb->type_attr_map_array, - scontext->type - 1); + sattr = &policydb->type_attr_map_array[scontext->type - 1]; BUG_ON(!sattr); - tattr = flex_array_get(policydb->type_attr_map_array, - tcontext->type - 1); + tattr = &policydb->type_attr_map_array[tcontext->type - 1]; BUG_ON(!tattr); ebitmap_for_each_positive_bit(sattr, snode, i) { ebitmap_for_each_positive_bit(tattr, tnode, j) { @@ -901,8 +896,7 @@ int security_bounded_transition(struct selinux_state *state, index = new_context->type; while (true) { - type = flex_array_get_ptr(policydb->type_val_to_struct_array, - index - 1); + type = policydb->type_val_to_struct_array[index - 1]; BUG_ON(!type); /* not bounded anymore */ @@ -1065,11 +1059,9 @@ void security_compute_xperms_decision(struct selinux_state *state, avkey.target_class = tclass; avkey.specified = AVTAB_XPERMS; - sattr = flex_array_get(policydb->type_attr_map_array, - scontext->type - 1); + sattr = &policydb->type_attr_map_array[scontext->type - 1]; BUG_ON(!sattr); - tattr = flex_array_get(policydb->type_attr_map_array, - tcontext->type - 1); + tattr = &policydb->type_attr_map_array[tcontext->type - 1]; BUG_ON(!tattr); ebitmap_for_each_positive_bit(sattr, snode, i) { ebitmap_for_each_positive_bit(tattr, tnode, j) { From 8c4616b718da5b7199faed81fd1835c6207fe9a7 Mon Sep 17 00:00:00 2001 From: Ondrej Mosnacek Date: Fri, 25 Jan 2019 11:06:51 +0100 Subject: [PATCH 503/592] selinux: log invalid contexts in AVCs In case a file has an invalid context set, in an AVC record generated upon access to such file, the target context is always reported as unlabeled. This patch adds new optional fields to the AVC record (srawcon and trawcon) that report the actual context string if it differs from the one reported in scontext/tcontext. This is useful for diagnosing SELinux denials involving invalid contexts. To trigger an AVC that illustrates this situation: # setenforce 0 # touch /tmp/testfile # setfattr -n security.selinux -v system_u:object_r:banana_t:s0 /tmp/testfile # runcon system_u:system_r:sshd_t:s0 cat /tmp/testfile AVC before: type=AVC msg=audit(1547801083.248:11): avc: denied { open } for pid=1149 comm="cat" path="/tmp/testfile" dev="tmpfs" ino=6608 scontext=system_u:system_r:sshd_t:s0 tcontext=system_u:object_r:unlabeled_t:s15:c0.c1023 tclass=file permissive=1 AVC after: type=AVC msg=audit(1547801083.248:11): avc: denied { open } for pid=1149 comm="cat" path="/tmp/testfile" dev="tmpfs" ino=6608 scontext=system_u:system_r:sshd_t:s0 tcontext=system_u:object_r:unlabeled_t:s15:c0.c1023 tclass=file permissive=1 trawcon=system_u:object_r:banana_t:s0 Note that it is also possible to encounter this situation with the 'scontext' field - e.g. when a new policy is loaded while a process is running, whose context is not valid in the new policy. Link: https://bugzilla.redhat.com/show_bug.cgi?id=1135683 Cc: Daniel Walsh Signed-off-by: Ondrej Mosnacek Reviewed-by: Stephen Smalley Signed-off-by: Paul Moore Signed-off-by: Yaroslav Furman Signed-off-by: UtsavBalar1231 --- security/selinux/avc.c | 15 ++++++++++++ security/selinux/include/security.h | 3 +++ security/selinux/ss/services.c | 37 +++++++++++++++++++++++++---- 3 files changed, 50 insertions(+), 5 deletions(-) diff --git a/security/selinux/avc.c b/security/selinux/avc.c index 58959b793297..6097d856e3eb 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -760,6 +760,21 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a) audit_log_format(ab, " permissive=%u", ad->selinux_audit_data->result ? 0 : 1); } + + /* in case of invalid context report also the actual context string */ + rc = security_sid_to_context_inval(sad->state, sad->ssid, &scontext, + &scontext_len); + if (!rc && scontext) { + audit_log_format(ab, " srawcon=%s", scontext); + kfree(scontext); + } + + rc = security_sid_to_context_inval(sad->state, sad->tsid, &scontext, + &scontext_len); + if (!rc && scontext) { + audit_log_format(ab, " trawcon=%s", scontext); + kfree(scontext); + } } /* This is the slow part of avc audit with big stack footprint */ diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index cf7cc432f90b..37a60e332182 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -262,6 +262,9 @@ int security_sid_to_context(struct selinux_state *state, u32 sid, int security_sid_to_context_force(struct selinux_state *state, u32 sid, char **scontext, u32 *scontext_len); +int security_sid_to_context_inval(struct selinux_state *state, + u32 sid, char **scontext, u32 *scontext_len); + int security_context_to_sid(struct selinux_state *state, const char *scontext, u32 scontext_len, u32 *out_sid, gfp_t gfp); diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index c4954df5911a..08dbfe32df77 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -1284,7 +1284,8 @@ const char *security_get_initial_sid_context(u32 sid) static int security_sid_to_context_core(struct selinux_state *state, u32 sid, char **scontext, - u32 *scontext_len, int force) + u32 *scontext_len, int force, + int only_invalid) { struct policydb *policydb; struct sidtab *sidtab; @@ -1329,8 +1330,14 @@ static int security_sid_to_context_core(struct selinux_state *state, rc = -EINVAL; goto out_unlock; } - rc = context_struct_to_string(policydb, context, scontext, - scontext_len); + if (only_invalid && !context->len) { + scontext = NULL; + scontext_len = 0; + rc = 0; + } else { + rc = context_struct_to_string(policydb, context, scontext, + scontext_len); + } out_unlock: read_unlock(&state->ss->policy_rwlock); out: @@ -1352,14 +1359,34 @@ int security_sid_to_context(struct selinux_state *state, u32 sid, char **scontext, u32 *scontext_len) { return security_sid_to_context_core(state, sid, scontext, - scontext_len, 0); + scontext_len, 0, 0); } int security_sid_to_context_force(struct selinux_state *state, u32 sid, char **scontext, u32 *scontext_len) { return security_sid_to_context_core(state, sid, scontext, - scontext_len, 1); + scontext_len, 1, 0); +} + +/** + * security_sid_to_context_inval - Obtain a context for a given SID if it + * is invalid. + * @sid: security identifier, SID + * @scontext: security context + * @scontext_len: length in bytes + * + * Write the string representation of the context associated with @sid + * into a dynamically allocated string of the correct size, but only if the + * context is invalid in the current policy. Set @scontext to point to + * this string (or NULL if the context is valid) and set @scontext_len to + * the length of the string (or 0 if the context is valid). + */ +int security_sid_to_context_inval(struct selinux_state *state, u32 sid, + char **scontext, u32 *scontext_len) +{ + return security_sid_to_context_core(state, sid, scontext, + scontext_len, 1, 1); } /* From d03d5b92b1ad19b59d90b8d31e881d3085b89230 Mon Sep 17 00:00:00 2001 From: Ondrej Mosnacek Date: Mon, 25 Mar 2019 09:11:15 +0100 Subject: [PATCH 504/592] selinux: remove useless assignments The code incorrectly assigned directly to the variables instead of the values they point to. Since the values are already set to NULL/0 at the beginning of the function, we can simply remove these useless assignments. Reported-by: Hariprasad Kelam Fixes: fede148324c3 ("selinux: log invalid contexts in AVCs") Signed-off-by: Ondrej Mosnacek [PM: removed a bad comment that was causing compiler warnings] Signed-off-by: Paul Moore Signed-off-by: UtsavBalar1231 --- security/selinux/ss/services.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 08dbfe32df77..08685548abb6 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -1330,14 +1330,11 @@ static int security_sid_to_context_core(struct selinux_state *state, rc = -EINVAL; goto out_unlock; } - if (only_invalid && !context->len) { - scontext = NULL; - scontext_len = 0; + if (only_invalid && !context->len) rc = 0; - } else { + else rc = context_struct_to_string(policydb, context, scontext, scontext_len); - } out_unlock: read_unlock(&state->ss->policy_rwlock); out: From 4ed38208fd326feebd62e003f09f07016da85751 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Tue, 9 Apr 2019 07:48:18 -0700 Subject: [PATCH 505/592] rcu: Make kfree_rcu() ignore NULL pointers This commit makes the kfree_rcu() macro's semantics be consistent with the likes of kfree() by adding a check for NULL pointers, so that kfree_rcu(NULL, ...) is a no-op. Reported-by: Andriy Shevchenko Reported-by: Christoph Hellwig Signed-off-by: Paul E. McKenney Reviewed-by: Andriy Shevchenko Signed-off-by: Yaroslav Furman Signed-off-by: UtsavBalar1231 --- include/linux/rcupdate.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index 8d570190e9b4..cad3693d41c4 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h @@ -847,7 +847,7 @@ static inline notrace void rcu_read_unlock_sched_notrace(void) /** * kfree_rcu() - kfree an object after a grace period. * @ptr: pointer to kfree - * @rcu_head: the name of the struct rcu_head within the type of @ptr. + * @rhf: the name of the struct rcu_head within the type of @ptr. * * Many rcu callbacks functions just call kfree() on the base structure. * These functions are trivial, but their size adds up, and furthermore @@ -870,9 +870,13 @@ static inline notrace void rcu_read_unlock_sched_notrace(void) * The BUILD_BUG_ON check must not involve any function calls, hence the * checks are done in macros here. */ -#define kfree_rcu(ptr, rcu_head) \ - __kfree_rcu(&((ptr)->rcu_head), offsetof(typeof(*(ptr)), rcu_head)) - +#define kfree_rcu(ptr, rhf) \ +do { \ + typeof (ptr) ___p = (ptr); \ + \ + if (___p) \ + __kfree_rcu(&((___p)->rhf), offsetof(typeof(*(ptr)), rhf)); \ +} while (0) /* * Place this after a lock-acquisition primitive to guarantee that From 11f368cfeffdf26d70c3bc4a0b9b60153c6925c8 Mon Sep 17 00:00:00 2001 From: Ondrej Mosnacek Date: Tue, 26 Nov 2019 14:57:00 +0100 Subject: [PATCH 506/592] BACKPORT: selinux: cache the SID -> context string translation Translating a context struct to string can be quite slow, especially if the context has a lot of category bits set. This can cause quite noticeable performance impact in situations where the translation needs to be done repeatedly. A common example is a UNIX datagram socket with the SO_PASSSEC option enabled, which is used e.g. by systemd-journald when receiving log messages via datagram socket. This scenario can be reproduced with: cat /dev/urandom | base64 | logger & timeout 30s perf record -p $(pidof systemd-journald) -a -g kill %1 perf report -g none --pretty raw | grep security_secid_to_secctx Before the caching introduced by this patch, computing the context string (security_secid_to_secctx() function) takes up ~65% of systemd-journald's CPU time (assuming a context with 1024 categories set and Fedora x86_64 release kernel configs). After this patch (assuming near-perfect cache hit ratio) this overhead is reduced to just ~2%. This patch addresses the issue by caching a certain number (compile-time configurable) of recently used context strings to speed up repeated translations of the same context, while using only a small amount of memory. The cache is integrated into the existing sidtab table by adding a field to each entry, which when not NULL contains an RCU-protected pointer to a cache entry containing the cached string. The cache entries are kept in a linked list sorted according to how recently they were used. On a cache miss when the cache is full, the least recently used entry is removed to make space for the new entry. The patch migrates security_sid_to_context_core() to use the cache (also a few other functions where it was possible without too much fuss, but these mostly use the translation for logging in case of error, which is rare). Link: https://bugzilla.redhat.com/show_bug.cgi?id=1733259 Cc: Michal Sekletar Signed-off-by: Ondrej Mosnacek Reviewed-by: Stephen Smalley Tested-by: Stephen Smalley Reviewed-by: Paul E. McKenney [PM: lots of merge fixups due to collisions with other sidtab patches] Signed-off-by: Paul Moore Signed-off-by: Yaroslav Furman Signed-off-by: UtsavBalar1231 --- security/selinux/Kconfig | 11 +++ security/selinux/ss/services.c | 138 ++++++++++++++++---------- security/selinux/ss/sidtab.c | 175 +++++++++++++++++++++++++++------ security/selinux/ss/sidtab.h | 58 +++++++++-- 4 files changed, 288 insertions(+), 94 deletions(-) diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig index 8297e48a283d..dbf78ea7a17b 100644 --- a/security/selinux/Kconfig +++ b/security/selinux/Kconfig @@ -111,3 +111,14 @@ config SECURITY_SELINUX_SIDTAB_HASH_BITS collisions may be viewed at /sys/fs/selinux/ss/sidtab_hash_stats. If chain lengths are high (e.g. > 20) then selecting a higher value here will ensure that lookups times are short and stable. + +config SECURITY_SELINUX_SID2STR_CACHE_SIZE + int "NSA SELinux SID to context string translation cache size" + depends on SECURITY_SELINUX + default 256 + help + This option defines the size of the internal SID -> context string + cache, which improves the performance of context to string + conversion. Setting this option to 0 disables the cache completely. + + If unsure, keep the default value. diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 08685548abb6..c0fa912bd925 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -94,6 +94,12 @@ static int context_struct_to_string(struct policydb *policydb, char **scontext, u32 *scontext_len); +static int sidtab_entry_to_string(struct policydb *policydb, + struct sidtab *sidtab, + struct sidtab_entry *entry, + char **scontext, + u32 *scontext_len); + static void context_struct_compute_av(struct policydb *policydb, struct context *scontext, struct context *tcontext, @@ -721,20 +727,21 @@ static void context_struct_compute_av(struct policydb *policydb, } static int security_validtrans_handle_fail(struct selinux_state *state, - struct context *ocontext, - struct context *ncontext, - struct context *tcontext, + struct sidtab_entry *oentry, + struct sidtab_entry *nentry, + struct sidtab_entry *tentry, u16 tclass) { struct policydb *p = &state->ss->policydb; + struct sidtab *sidtab = state->ss->sidtab; char *o = NULL, *n = NULL, *t = NULL; u32 olen, nlen, tlen; - if (context_struct_to_string(p, ocontext, &o, &olen)) + if (sidtab_entry_to_string(p, sidtab, oentry, &o, &olen)) goto out; - if (context_struct_to_string(p, ncontext, &n, &nlen)) + if (sidtab_entry_to_string(p, sidtab, nentry, &n, &nlen)) goto out; - if (context_struct_to_string(p, tcontext, &t, &tlen)) + if (sidtab_entry_to_string(p, sidtab, tentry, &t, &tlen)) goto out; audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR, "op=security_validate_transition seresult=denied" @@ -756,9 +763,9 @@ static int security_compute_validatetrans(struct selinux_state *state, { struct policydb *policydb; struct sidtab *sidtab; - struct context *ocontext; - struct context *ncontext; - struct context *tcontext; + struct sidtab_entry *oentry; + struct sidtab_entry *nentry; + struct sidtab_entry *tentry; struct class_datum *tclass_datum; struct constraint_node *constraint; u16 tclass; @@ -784,24 +791,24 @@ static int security_compute_validatetrans(struct selinux_state *state, } tclass_datum = policydb->class_val_to_struct[tclass - 1]; - ocontext = sidtab_search(sidtab, oldsid); - if (!ocontext) { + oentry = sidtab_search_entry(sidtab, oldsid); + if (!oentry) { pr_err("SELinux: %s: unrecognized SID %d\n", __func__, oldsid); rc = -EINVAL; goto out; } - ncontext = sidtab_search(sidtab, newsid); - if (!ncontext) { + nentry = sidtab_search_entry(sidtab, newsid); + if (!nentry) { pr_err("SELinux: %s: unrecognized SID %d\n", __func__, newsid); rc = -EINVAL; goto out; } - tcontext = sidtab_search(sidtab, tasksid); - if (!tcontext) { + tentry = sidtab_search_entry(sidtab, tasksid); + if (!tentry) { pr_err("SELinux: %s: unrecognized SID %d\n", __func__, tasksid); rc = -EINVAL; @@ -810,15 +817,16 @@ static int security_compute_validatetrans(struct selinux_state *state, constraint = tclass_datum->validatetrans; while (constraint) { - if (!constraint_expr_eval(policydb, ocontext, ncontext, - tcontext, constraint->expr)) { + if (!constraint_expr_eval(policydb, &oentry->context, + &nentry->context, &tentry->context, + constraint->expr)) { if (user) rc = -EPERM; else rc = security_validtrans_handle_fail(state, - ocontext, - ncontext, - tcontext, + oentry, + nentry, + tentry, tclass); goto out; } @@ -860,7 +868,7 @@ int security_bounded_transition(struct selinux_state *state, { struct policydb *policydb; struct sidtab *sidtab; - struct context *old_context, *new_context; + struct sidtab_entry *old_entry, *new_entry; struct type_datum *type; int index; int rc; @@ -874,16 +882,16 @@ int security_bounded_transition(struct selinux_state *state, sidtab = state->ss->sidtab; rc = -EINVAL; - old_context = sidtab_search(sidtab, old_sid); - if (!old_context) { + old_entry = sidtab_search_entry(sidtab, old_sid); + if (!old_entry) { pr_err("SELinux: %s: unrecognized SID %u\n", __func__, old_sid); goto out; } rc = -EINVAL; - new_context = sidtab_search(sidtab, new_sid); - if (!new_context) { + new_entry = sidtab_search_entry(sidtab, new_sid); + if (!new_entry) { pr_err("SELinux: %s: unrecognized SID %u\n", __func__, new_sid); goto out; @@ -891,10 +899,10 @@ int security_bounded_transition(struct selinux_state *state, rc = 0; /* type/domain unchanged */ - if (old_context->type == new_context->type) + if (old_entry->context.type == new_entry->context.type) goto out; - index = new_context->type; + index = new_entry->context.type; while (true) { type = policydb->type_val_to_struct_array[index - 1]; BUG_ON(!type); @@ -906,7 +914,7 @@ int security_bounded_transition(struct selinux_state *state, /* @newsid is bounded by @oldsid */ rc = 0; - if (type->bounds == old_context->type) + if (type->bounds == old_entry->context.type) break; index = type->bounds; @@ -917,10 +925,10 @@ int security_bounded_transition(struct selinux_state *state, char *new_name = NULL; u32 length; - if (!context_struct_to_string(policydb, old_context, - &old_name, &length) && - !context_struct_to_string(policydb, new_context, - &new_name, &length)) { + if (!sidtab_entry_to_string(policydb, sidtab, old_entry, + &old_name, &length) && + !sidtab_entry_to_string(policydb, sidtab, new_entry, + &new_name, &length)) { audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR, "op=security_bounded_transition " @@ -1262,6 +1270,23 @@ static int context_struct_to_string(struct policydb *p, return 0; } +static int sidtab_entry_to_string(struct policydb *p, + struct sidtab *sidtab, + struct sidtab_entry *entry, + char **scontext, u32 *scontext_len) +{ + int rc = sidtab_sid2str_get(sidtab, entry, scontext, scontext_len); + + if (rc != -ENOENT) + return rc; + + rc = context_struct_to_string(p, &entry->context, scontext, + scontext_len); + if (!rc && scontext) + sidtab_sid2str_put(sidtab, entry, *scontext, *scontext_len); + return rc; +} + #include "initial_sid_to_string.h" int security_sidtab_hash_stats(struct selinux_state *state, char *page) @@ -1289,7 +1314,7 @@ static int security_sid_to_context_core(struct selinux_state *state, { struct policydb *policydb; struct sidtab *sidtab; - struct context *context; + struct sidtab_entry *entry; int rc = 0; if (scontext) @@ -1320,21 +1345,23 @@ static int security_sid_to_context_core(struct selinux_state *state, read_lock(&state->ss->policy_rwlock); policydb = &state->ss->policydb; sidtab = state->ss->sidtab; + if (force) - context = sidtab_search_force(sidtab, sid); + entry = sidtab_search_entry_force(sidtab, sid); else - context = sidtab_search(sidtab, sid); - if (!context) { + entry = sidtab_search_entry(sidtab, sid); + if (!entry) { pr_err("SELinux: %s: unrecognized SID %d\n", __func__, sid); rc = -EINVAL; goto out_unlock; } - if (only_invalid && !context->len) - rc = 0; - else - rc = context_struct_to_string(policydb, context, scontext, - scontext_len); + if (only_invalid && !entry->context.len) + goto out_unlock; + + rc = sidtab_entry_to_string(policydb, sidtab, entry, scontext, + scontext_len); + out_unlock: read_unlock(&state->ss->policy_rwlock); out: @@ -1628,18 +1655,19 @@ int security_context_to_sid_force(struct selinux_state *state, static int compute_sid_handle_invalid_context( struct selinux_state *state, - struct context *scontext, - struct context *tcontext, + struct sidtab_entry *sentry, + struct sidtab_entry *tentry, u16 tclass, struct context *newcontext) { struct policydb *policydb = &state->ss->policydb; + struct sidtab *sidtab = state->ss->sidtab; char *s = NULL, *t = NULL, *n = NULL; u32 slen, tlen, nlen; - if (context_struct_to_string(policydb, scontext, &s, &slen)) + if (sidtab_entry_to_string(policydb, sidtab, sentry, &s, &slen)) goto out; - if (context_struct_to_string(policydb, tcontext, &t, &tlen)) + if (sidtab_entry_to_string(policydb, sidtab, tentry, &t, &tlen)) goto out; if (context_struct_to_string(policydb, newcontext, &n, &nlen)) goto out; @@ -1696,7 +1724,8 @@ static int security_compute_sid(struct selinux_state *state, struct policydb *policydb; struct sidtab *sidtab; struct class_datum *cladatum = NULL; - struct context *scontext = NULL, *tcontext = NULL, newcontext; + struct context *scontext, *tcontext, newcontext; + struct sidtab_entry *sentry, *tentry; struct role_trans *roletr = NULL; struct avtab_key avkey; struct avtab_datum *avdatum; @@ -1733,21 +1762,24 @@ static int security_compute_sid(struct selinux_state *state, policydb = &state->ss->policydb; sidtab = state->ss->sidtab; - scontext = sidtab_search(sidtab, ssid); - if (!scontext) { + sentry = sidtab_search_entry(sidtab, ssid); + if (!sentry) { pr_err("SELinux: %s: unrecognized SID %d\n", __func__, ssid); rc = -EINVAL; goto out_unlock; } - tcontext = sidtab_search(sidtab, tsid); - if (!tcontext) { + tentry = sidtab_search_entry(sidtab, tsid); + if (!tentry) { pr_err("SELinux: %s: unrecognized SID %d\n", __func__, tsid); rc = -EINVAL; goto out_unlock; } + scontext = &sentry->context; + tcontext = &tentry->context; + if (tclass && tclass <= policydb->p_classes.nprim) cladatum = policydb->class_val_to_struct[tclass - 1]; @@ -1848,10 +1880,8 @@ static int security_compute_sid(struct selinux_state *state, /* Check the validity of the context. */ if (!policydb_context_isvalid(policydb, &newcontext)) { - rc = compute_sid_handle_invalid_context(state, scontext, - tcontext, - tclass, - &newcontext); + rc = compute_sid_handle_invalid_context(state, sentry, tentry, + tclass, &newcontext); if (rc) goto out_unlock; } diff --git a/security/selinux/ss/sidtab.c b/security/selinux/ss/sidtab.c index d9d8599e8e63..a308ce1e6a13 100644 --- a/security/selinux/ss/sidtab.c +++ b/security/selinux/ss/sidtab.c @@ -9,6 +9,8 @@ */ #include #include +#include +#include #include #include #include @@ -17,6 +19,14 @@ #include "security.h" #include "sidtab.h" +struct sidtab_str_cache { + struct rcu_head rcu_member; + struct list_head lru_member; + struct sidtab_entry *parent; + u32 len; + char str[]; +}; + #define index_to_sid(index) (index + SECINITSID_NUM + 1) #define sid_to_index(sid) (sid - (SECINITSID_NUM + 1)) @@ -34,12 +44,19 @@ int sidtab_init(struct sidtab *s) hash_init(s->context_to_sid); spin_lock_init(&s->lock); + +#if CONFIG_SECURITY_SELINUX_SID2STR_CACHE_SIZE > 0 + s->cache_free_slots = CONFIG_SECURITY_SELINUX_SID2STR_CACHE_SIZE; + INIT_LIST_HEAD(&s->cache_lru_list); + spin_lock_init(&s->cache_lock); +#endif + return 0; } static u32 context_to_sid(struct sidtab *s, struct context *context) { - struct sidtab_entry_leaf *entry; + struct sidtab_entry *entry; u32 sid = 0; rcu_read_lock(); @@ -56,19 +73,22 @@ static u32 context_to_sid(struct sidtab *s, struct context *context) int sidtab_set_initial(struct sidtab *s, u32 sid, struct context *context) { - struct sidtab_isid_entry *entry; + struct sidtab_isid_entry *isid; int rc; if (sid == 0 || sid > SECINITSID_NUM) return -EINVAL; - entry = &s->isids[sid - 1]; + isid = &s->isids[sid - 1]; - rc = context_cpy(&entry->leaf.context, context); + rc = context_cpy(&isid->entry.context, context); if (rc) return rc; - entry->set = 1; +#if CONFIG_SECURITY_SELINUX_SID2STR_CACHE_SIZE > 0 + isid->entry.cache = NULL; +#endif + isid->set = 1; /* * Multiple initial sids may map to the same context. Check that this @@ -77,8 +97,8 @@ int sidtab_set_initial(struct sidtab *s, u32 sid, struct context *context) * collision. */ if (!context_to_sid(s, context)) { - entry->leaf.sid = sid; - hash_add(s->context_to_sid, &entry->leaf.list, context->hash); + isid->entry.sid = sid; + hash_add(s->context_to_sid, &isid->entry.list, context->hash); } return 0; @@ -92,7 +112,7 @@ int sidtab_hash_stats(struct sidtab *sidtab, char *page) int entries = 0; int max_chain_len = 0; int cur_bucket = 0; - struct sidtab_entry_leaf *entry; + struct sidtab_entry *entry; rcu_read_lock(); hash_for_each_rcu(sidtab->context_to_sid, i, entry, list) { @@ -151,8 +171,8 @@ static int sidtab_alloc_roots(struct sidtab *s, u32 level) return 0; } -static struct sidtab_entry_leaf *sidtab_do_lookup(struct sidtab *s, u32 index, - int alloc) +static struct sidtab_entry *sidtab_do_lookup(struct sidtab *s, u32 index, + int alloc) { union sidtab_entry_inner *entry; u32 level, capacity_shift, leaf_index = index / SIDTAB_LEAF_ENTRIES; @@ -192,7 +212,7 @@ static struct sidtab_entry_leaf *sidtab_do_lookup(struct sidtab *s, u32 index, return &entry->ptr_leaf->entries[index % SIDTAB_LEAF_ENTRIES]; } -static struct context *sidtab_lookup(struct sidtab *s, u32 index) +static struct sidtab_entry *sidtab_lookup(struct sidtab *s, u32 index) { /* read entries only after reading count */ u32 count = smp_load_acquire(&s->count); @@ -200,36 +220,37 @@ static struct context *sidtab_lookup(struct sidtab *s, u32 index) if (index >= count) return NULL; - return &sidtab_do_lookup(s, index, 0)->context; + return sidtab_do_lookup(s, index, 0); } -static struct context *sidtab_lookup_initial(struct sidtab *s, u32 sid) +static struct sidtab_entry *sidtab_lookup_initial(struct sidtab *s, u32 sid) { - return s->isids[sid - 1].set ? &s->isids[sid - 1].leaf.context : NULL; + return s->isids[sid - 1].set ? &s->isids[sid - 1].entry : NULL; } -static struct context *sidtab_search_core(struct sidtab *s, u32 sid, int force) +static struct sidtab_entry *sidtab_search_core(struct sidtab *s, u32 sid, + int force) { - struct context *context; - if (sid != 0) { + struct sidtab_entry *entry; + if (sid > SECINITSID_NUM) - context = sidtab_lookup(s, sid_to_index(sid)); + entry = sidtab_lookup(s, sid_to_index(sid)); else - context = sidtab_lookup_initial(s, sid); - if (context && (!context->len || force)) - return context; + entry = sidtab_lookup_initial(s, sid); + if (entry && (!entry->context.len || force)) + return entry; } return sidtab_lookup_initial(s, SECINITSID_UNLABELED); } -struct context *sidtab_search(struct sidtab *s, u32 sid) +struct sidtab_entry *sidtab_search_entry(struct sidtab *s, u32 sid) { return sidtab_search_core(s, sid, 0); } -struct context *sidtab_search_force(struct sidtab *s, u32 sid) +struct sidtab_entry *sidtab_search_entry_force(struct sidtab *s, u32 sid) { return sidtab_search_core(s, sid, 1); } @@ -240,7 +261,7 @@ int sidtab_context_to_sid(struct sidtab *s, struct context *context, unsigned long flags; u32 count; struct sidtab_convert_params *convert; - struct sidtab_entry_leaf *dst, *dst_convert; + struct sidtab_entry *dst, *dst_convert; int rc; *sid = context_to_sid(s, context); @@ -289,7 +310,7 @@ int sidtab_context_to_sid(struct sidtab *s, struct context *context, } rc = convert->func(context, &dst_convert->context, - convert->args); + convert->args); if (rc) { context_destroy(&dst->context); goto out_unlock; @@ -298,7 +319,7 @@ int sidtab_context_to_sid(struct sidtab *s, struct context *context, convert->target->count = count + 1; hash_add_rcu(convert->target->context_to_sid, - &dst_convert->list, dst_convert->context.hash); + &dst_convert->list, dst_convert->context.hash); } if (context->len) @@ -319,7 +340,7 @@ out_unlock: static void sidtab_convert_hashtable(struct sidtab *s, u32 count) { - struct sidtab_entry_leaf *entry; + struct sidtab_entry *entry; u32 i; for (i = 0; i < count; i++) { @@ -327,7 +348,7 @@ static void sidtab_convert_hashtable(struct sidtab *s, u32 count) entry->sid = index_to_sid(i); hash_add_rcu(s->context_to_sid, &entry->list, - entry->context.hash); + entry->context.hash); } } @@ -376,7 +397,6 @@ static int sidtab_convert_tree(union sidtab_entry_inner *edst, } cond_resched(); } - return 0; } @@ -439,6 +459,14 @@ int sidtab_convert(struct sidtab *s, struct sidtab_convert_params *params) return 0; } +static void sidtab_destroy_entry(struct sidtab_entry *entry) +{ + context_destroy(&entry->context); +#if CONFIG_SECURITY_SELINUX_SID2STR_CACHE_SIZE > 0 + kfree(rcu_dereference_raw(entry->cache)); +#endif +} + static void sidtab_destroy_tree(union sidtab_entry_inner entry, u32 level) { u32 i; @@ -459,7 +487,7 @@ static void sidtab_destroy_tree(union sidtab_entry_inner entry, u32 level) return; for (i = 0; i < SIDTAB_LEAF_ENTRIES; i++) - context_destroy(&node->entries[i].context); + sidtab_destroy_entry(&node->entries[i]); kfree(node); } } @@ -470,7 +498,7 @@ void sidtab_destroy(struct sidtab *s) for (i = 0; i < SECINITSID_NUM; i++) if (s->isids[i].set) - context_destroy(&s->isids[i].leaf.context); + sidtab_destroy_entry(&s->isids[i].entry); level = SIDTAB_MAX_LEVEL; while (level && !s->roots[level].ptr_inner) @@ -483,3 +511,88 @@ void sidtab_destroy(struct sidtab *s) * to be cleaned up here. */ } + +#if CONFIG_SECURITY_SELINUX_SID2STR_CACHE_SIZE > 0 + +void sidtab_sid2str_put(struct sidtab *s, struct sidtab_entry *entry, + const char *str, u32 str_len) +{ + struct sidtab_str_cache *cache, *victim = NULL; + + /* do not cache invalid contexts */ + if (entry->context.len) + return; + + /* + * Skip the put operation when in non-task context to avoid the need + * to disable interrupts while holding s->cache_lock. + */ + if (!in_task()) + return; + + spin_lock(&s->cache_lock); + + cache = rcu_dereference_protected(entry->cache, + lockdep_is_held(&s->cache_lock)); + if (cache) { + /* entry in cache - just bump to the head of LRU list */ + list_move(&cache->lru_member, &s->cache_lru_list); + goto out_unlock; + } + + cache = kmalloc(sizeof(struct sidtab_str_cache) + str_len, GFP_ATOMIC); + if (!cache) + goto out_unlock; + + if (s->cache_free_slots == 0) { + /* pop a cache entry from the tail and free it */ + victim = container_of(s->cache_lru_list.prev, + struct sidtab_str_cache, lru_member); + list_del(&victim->lru_member); + rcu_assign_pointer(victim->parent->cache, NULL); + } else { + s->cache_free_slots--; + } + cache->parent = entry; + cache->len = str_len; + memcpy(cache->str, str, str_len); + list_add(&cache->lru_member, &s->cache_lru_list); + + rcu_assign_pointer(entry->cache, cache); + +out_unlock: + spin_unlock(&s->cache_lock); + kfree_rcu(victim, rcu_member); +} + +int sidtab_sid2str_get(struct sidtab *s, struct sidtab_entry *entry, + char **out, u32 *out_len) +{ + struct sidtab_str_cache *cache; + int rc = 0; + + if (entry->context.len) + return -ENOENT; /* do not cache invalid contexts */ + + rcu_read_lock(); + + cache = rcu_dereference(entry->cache); + if (!cache) { + rc = -ENOENT; + } else { + *out_len = cache->len; + if (out) { + *out = kmemdup(cache->str, cache->len, GFP_ATOMIC); + if (!*out) + rc = -ENOMEM; + } + } + + rcu_read_unlock(); + + if (!rc && out) + sidtab_sid2str_put(s, entry, *out, *out_len); + return rc; +} + +#endif /* CONFIG_SECURITY_SELINUX_SID2STR_CACHE_SIZE > 0 */ diff --git a/security/selinux/ss/sidtab.h b/security/selinux/ss/sidtab.h index 8564ec0f3599..7702ca8fae8f 100644 --- a/security/selinux/ss/sidtab.h +++ b/security/selinux/ss/sidtab.h @@ -18,15 +18,15 @@ #include "context.h" #include "flask.h" -struct sidtab_entry_leaf { +struct sidtab_entry { u32 sid; struct context context; +#if CONFIG_SECURITY_SELINUX_SID2STR_CACHE_SIZE > 0 + struct sidtab_str_cache __rcu *cache; +#endif struct hlist_node list; }; -struct sidtab_node_inner; -struct sidtab_node_leaf; - union sidtab_entry_inner { struct sidtab_node_inner *ptr_inner; struct sidtab_node_leaf *ptr_leaf; @@ -42,7 +42,7 @@ union sidtab_entry_inner { (SIDTAB_NODE_ALLOC_SHIFT - size_to_shift(sizeof(union sidtab_entry_inner))) #define SIDTAB_INNER_ENTRIES ((size_t)1 << SIDTAB_INNER_SHIFT) #define SIDTAB_LEAF_ENTRIES \ - (SIDTAB_NODE_ALLOC_SIZE / sizeof(struct sidtab_entry_leaf)) + (SIDTAB_NODE_ALLOC_SIZE / sizeof(struct sidtab_entry)) #define SIDTAB_MAX_BITS 32 #define SIDTAB_MAX U32_MAX @@ -52,7 +52,7 @@ union sidtab_entry_inner { SIDTAB_INNER_SHIFT) struct sidtab_node_leaf { - struct sidtab_entry_leaf entries[SIDTAB_LEAF_ENTRIES]; + struct sidtab_entry entries[SIDTAB_LEAF_ENTRIES]; }; struct sidtab_node_inner { @@ -61,7 +61,7 @@ struct sidtab_node_inner { struct sidtab_isid_entry { int set; - struct sidtab_entry_leaf leaf; + struct sidtab_entry entry; }; struct sidtab_convert_params { @@ -88,6 +88,13 @@ struct sidtab { struct sidtab_convert_params *convert; spinlock_t lock; +#if CONFIG_SECURITY_SELINUX_SID2STR_CACHE_SIZE > 0 + /* SID -> context string cache */ + u32 cache_free_slots; + struct list_head cache_lru_list; + spinlock_t cache_lock; +#endif + /* index == SID - 1 (no entry for SECSID_NULL) */ struct sidtab_isid_entry isids[SECINITSID_NUM]; @@ -97,8 +104,22 @@ struct sidtab { int sidtab_init(struct sidtab *s); int sidtab_set_initial(struct sidtab *s, u32 sid, struct context *context); -struct context *sidtab_search(struct sidtab *s, u32 sid); -struct context *sidtab_search_force(struct sidtab *s, u32 sid); +struct sidtab_entry *sidtab_search_entry(struct sidtab *s, u32 sid); +struct sidtab_entry *sidtab_search_entry_force(struct sidtab *s, u32 sid); + +static inline struct context *sidtab_search(struct sidtab *s, u32 sid) +{ + struct sidtab_entry *entry = sidtab_search_entry(s, sid); + + return entry ? &entry->context : NULL; +} + +static inline struct context *sidtab_search_force(struct sidtab *s, u32 sid) +{ + struct sidtab_entry *entry = sidtab_search_entry_force(s, sid); + + return entry ? &entry->context : NULL; +} int sidtab_convert(struct sidtab *s, struct sidtab_convert_params *params); @@ -108,6 +129,25 @@ void sidtab_destroy(struct sidtab *s); int sidtab_hash_stats(struct sidtab *sidtab, char *page); +#if CONFIG_SECURITY_SELINUX_SID2STR_CACHE_SIZE > 0 +void sidtab_sid2str_put(struct sidtab *s, struct sidtab_entry *entry, + const char *str, u32 str_len); +int sidtab_sid2str_get(struct sidtab *s, struct sidtab_entry *entry, + char **out, u32 *out_len); +#else +static inline void sidtab_sid2str_put(struct sidtab *s, + struct sidtab_entry *entry, + const char *str, u32 str_len) +{ +} +static inline int sidtab_sid2str_get(struct sidtab *s, + struct sidtab_entry *entry, + char **out, u32 *out_len) +{ + return -ENOENT; +} +#endif /* CONFIG_SECURITY_SELINUX_SID2STR_CACHE_SIZE > 0 */ + #endif /* _SS_SIDTAB_H_ */ From dd3597e71e1e6d084f2c74e6125492bc9956d135 Mon Sep 17 00:00:00 2001 From: Ondrej Mosnacek Date: Mon, 3 Feb 2020 09:50:23 +0100 Subject: [PATCH 507/592] selinux: fix sidtab string cache locking Avoiding taking a lock in an IRQ context is not enough to prevent deadlocks, as discovered by syzbot: === WARNING: SOFTIRQ-safe -> SOFTIRQ-unsafe lock order detected 5.5.0-syzkaller #0 Not tainted ----------------------------------------------------- syz-executor.0/8927 [HC0[0]:SC0[2]:HE1:SE0] is trying to acquire: ffff888027c94098 (&(&s->cache_lock)->rlock){+.+.}, at: spin_lock include/linux/spinlock.h:338 [inline] ffff888027c94098 (&(&s->cache_lock)->rlock){+.+.}, at: sidtab_sid2str_put.part.0+0x36/0x880 security/selinux/ss/sidtab.c:533 and this task is already holding: ffffffff898639b0 (&(&nf_conntrack_locks[i])->rlock){+.-.}, at: spin_lock include/linux/spinlock.h:338 [inline] ffffffff898639b0 (&(&nf_conntrack_locks[i])->rlock){+.-.}, at: nf_conntrack_lock+0x17/0x70 net/netfilter/nf_conntrack_core.c:91 which would create a new lock dependency: (&(&nf_conntrack_locks[i])->rlock){+.-.} -> (&(&s->cache_lock)->rlock){+.+.} but this new dependency connects a SOFTIRQ-irq-safe lock: (&(&nf_conntrack_locks[i])->rlock){+.-.} [...] other info that might help us debug this: Possible interrupt unsafe locking scenario: CPU0 CPU1 ---- ---- lock(&(&s->cache_lock)->rlock); local_irq_disable(); lock(&(&nf_conntrack_locks[i])->rlock); lock(&(&s->cache_lock)->rlock); lock(&(&nf_conntrack_locks[i])->rlock); *** DEADLOCK *** [...] === Fix this by simply locking with irqsave/irqrestore and stop giving up on !in_task(). It makes the locking a bit slower, but it shouldn't make a big difference in real workloads. Under the scenario from [1] (only cache hits) it only increased the runtime overhead from the security_secid_to_secctx() function from ~2% to ~3% (it was ~5-65% before introducing the cache). [1] https://bugzilla.redhat.com/show_bug.cgi?id=1733259 Fixes: d97bd23c2d7d ("selinux: cache the SID -> context string translation") Reported-by: syzbot+61cba5033e2072d61806@syzkaller.appspotmail.com Signed-off-by: Ondrej Mosnacek Acked-by: Stephen Smalley Signed-off-by: Paul Moore Signed-off-by: UtsavBalar1231 --- security/selinux/ss/sidtab.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/security/selinux/ss/sidtab.c b/security/selinux/ss/sidtab.c index a308ce1e6a13..f511ffccb131 100644 --- a/security/selinux/ss/sidtab.c +++ b/security/selinux/ss/sidtab.c @@ -518,19 +518,13 @@ void sidtab_sid2str_put(struct sidtab *s, struct sidtab_entry *entry, const char *str, u32 str_len) { struct sidtab_str_cache *cache, *victim = NULL; + unsigned long flags; /* do not cache invalid contexts */ if (entry->context.len) return; - /* - * Skip the put operation when in non-task context to avoid the need - * to disable interrupts while holding s->cache_lock. - */ - if (!in_task()) - return; - - spin_lock(&s->cache_lock); + spin_lock_irqsave(&s->cache_lock, flags); cache = rcu_dereference_protected(entry->cache, lockdep_is_held(&s->cache_lock)); @@ -561,7 +555,7 @@ void sidtab_sid2str_put(struct sidtab *s, struct sidtab_entry *entry, rcu_assign_pointer(entry->cache, cache); out_unlock: - spin_unlock(&s->cache_lock); + spin_unlock_irqrestore(&s->cache_lock, flags); kfree_rcu(victim, rcu_member); } From d13bce8908ca5006e5d80d96b77101369393f98b Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Mon, 23 Dec 2019 16:38:36 -0500 Subject: [PATCH 508/592] selinux: ensure the policy has been loaded before reading the sidtab stats Check to make sure we have loaded a policy before we query the sidtab's hash stats. Failure to do so could result in a kernel panic/oops due to a dereferenced NULL pointer. Fixes: 66f8e2f03c02 ("selinux: sidtab reverse lookup hash table") Reported-by: kernel test robot Signed-off-by: Paul Moore Signed-off-by: UtsavBalar1231 --- security/selinux/ss/services.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index c0fa912bd925..38f9f27e8908 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -1293,6 +1293,12 @@ int security_sidtab_hash_stats(struct selinux_state *state, char *page) { int rc; + if (!state->initialized) { + pr_err("SELinux: %s: called before initial load_policy\n", + __func__); + return -EINVAL; + } + read_lock(&state->ss->policy_rwlock); rc = sidtab_hash_stats(state->ss->sidtab, page); read_unlock(&state->ss->policy_rwlock); From 7a268a00489bda779e9e89274f6411eb2b843ff5 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Tue, 24 Dec 2019 20:45:52 +0800 Subject: [PATCH 509/592] selinux: remove set but not used variable 'sidtab' security/selinux/ss/services.c: In function security_port_sid: security/selinux/ss/services.c:2346:17: warning: variable sidtab set but not used [-Wunused-but-set-variable] security/selinux/ss/services.c: In function security_ib_endport_sid: security/selinux/ss/services.c:2435:17: warning: variable sidtab set but not used [-Wunused-but-set-variable] security/selinux/ss/services.c: In function security_netif_sid: security/selinux/ss/services.c:2480:17: warning: variable sidtab set but not used [-Wunused-but-set-variable] security/selinux/ss/services.c: In function security_fs_use: security/selinux/ss/services.c:2831:17: warning: variable sidtab set but not used [-Wunused-but-set-variable] Since commit 66f8e2f03c02 ("selinux: sidtab reverse lookup hash table") 'sidtab' is not used any more, so remove it. Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: Paul Moore Signed-off-by: Yaroslav Furman Signed-off-by: UtsavBalar1231 --- security/selinux/ss/services.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 38f9f27e8908..615b8fccd396 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -2356,14 +2356,12 @@ int security_port_sid(struct selinux_state *state, u8 protocol, u16 port, u32 *out_sid) { struct policydb *policydb; - struct sidtab *sidtab; struct ocontext *c; int rc = 0; read_lock(&state->ss->policy_rwlock); policydb = &state->ss->policydb; - sidtab = state->ss->sidtab; c = policydb->ocontexts[OCON_PORT]; while (c) { @@ -2445,14 +2443,12 @@ int security_ib_endport_sid(struct selinux_state *state, const char *dev_name, u8 port_num, u32 *out_sid) { struct policydb *policydb; - struct sidtab *sidtab; struct ocontext *c; int rc = 0; read_lock(&state->ss->policy_rwlock); policydb = &state->ss->policydb; - sidtab = state->ss->sidtab; c = policydb->ocontexts[OCON_IBENDPORT]; while (c) { @@ -2490,14 +2486,12 @@ int security_netif_sid(struct selinux_state *state, char *name, u32 *if_sid) { struct policydb *policydb; - struct sidtab *sidtab; int rc = 0; struct ocontext *c; read_lock(&state->ss->policy_rwlock); policydb = &state->ss->policydb; - sidtab = state->ss->sidtab; c = policydb->ocontexts[OCON_NETIF]; while (c) { @@ -2841,7 +2835,6 @@ int security_genfs_sid(struct selinux_state *state, int security_fs_use(struct selinux_state *state, struct super_block *sb) { struct policydb *policydb; - struct sidtab *sidtab; int rc = 0; struct ocontext *c; struct superblock_security_struct *sbsec = sb->s_security; @@ -2850,7 +2843,6 @@ int security_fs_use(struct selinux_state *state, struct super_block *sb) read_lock(&state->ss->policy_rwlock); policydb = &state->ss->policydb; - sidtab = state->ss->sidtab; c = policydb->ocontexts[OCON_FSUSE]; while (c) { From 0efb1c69075a3905bc7deb9be36355ad69fe5742 Mon Sep 17 00:00:00 2001 From: Stephen Smalley Date: Fri, 13 Dec 2019 15:28:38 -0500 Subject: [PATCH 510/592] selinux: randomize layout of key structures Randomize the layout of key selinux data structures. Initially this is applied to the selinux_state, selinux_ss, policydb, and task_security_struct data structures. NB To test/use this mechanism, one must install the necessary build-time dependencies, e.g. gcc-plugin-devel on Fedora, and enable CONFIG_GCC_PLUGIN_RANDSTRUCT in the kernel configuration. Signed-off-by: Stephen Smalley Reviewed-by: Kees Cook [PM: double semi-colon fixed] Signed-off-by: Paul Moore Signed-off-by: Yaroslav Furman Signed-off-by: UtsavBalar1231 --- security/selinux/include/objsec.h | 2 +- security/selinux/include/security.h | 2 +- security/selinux/ss/policydb.h | 2 +- security/selinux/ss/services.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index 2ac6edc1d131..d2747e459e98 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h @@ -37,7 +37,7 @@ struct task_security_struct { u32 create_sid; /* fscreate SID */ u32 keycreate_sid; /* keycreate SID */ u32 sockcreate_sid; /* fscreate SID */ -}; +} __randomize_layout; /* * get the subjective security ID of the current task diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 37a60e332182..7bf2c7adec2d 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -106,7 +106,7 @@ struct selinux_state { bool android_netlink_route; struct selinux_avc *avc; struct selinux_ss *ss; -}; +} __randomize_layout; void selinux_ss_init(struct selinux_ss **ss); void selinux_avc_init(struct selinux_avc **avc); diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h index caa20320e574..4fab84f1a5e5 100644 --- a/security/selinux/ss/policydb.h +++ b/security/selinux/ss/policydb.h @@ -309,7 +309,7 @@ struct policydb { u16 process_class; u32 process_trans_perms; -}; +} __randomize_layout; extern void policydb_destroy(struct policydb *p); extern int policydb_load_isids(struct policydb *p, struct sidtab *s); diff --git a/security/selinux/ss/services.h b/security/selinux/ss/services.h index fc40640a9725..c5896f39e8f6 100644 --- a/security/selinux/ss/services.h +++ b/security/selinux/ss/services.h @@ -31,7 +31,7 @@ struct selinux_ss { struct selinux_map map; struct page *status_page; struct mutex status_lock; -}; +} __randomize_layout; void services_compute_xperms_drivers(struct extended_perms *xperms, struct avtab_node *node); From 034255d1f2acb91abcc0bc017465347a2962e4f3 Mon Sep 17 00:00:00 2001 From: Danny Lin Date: Sun, 9 Aug 2020 22:20:08 -0700 Subject: [PATCH 511/592] qcacld-3.0: Fix regulatory domain country names Clang warns: ../drivers/staging/qcacld-3.0/core/cds/src/cds_regdomain.c:284:43: warning: suspicious concatenation of string literals in an array initialization; did you mean to separate the elements with a comma? [-Wstring-concatenation] {CTRY_TURKS_AND_CAICOS, FCC3_WORLD, "TC" "TURKS AND CAICOS"}, ^ , ../drivers/staging/qcacld-3.0/core/cds/src/cds_regdomain.c:284:38: note: place parentheses around the string literal to silence warning {CTRY_TURKS_AND_CAICOS, FCC3_WORLD, "TC" "TURKS AND CAICOS"}, ^ ../drivers/staging/qcacld-3.0/core/cds/src/cds_regdomain.c:296:45: warning: suspicious concatenation of string literals in an array initialization; did you mean to separate the elements with a comma? [-Wstring-concatenation] {CTRY_WALLIS_AND_FUTUNA, ETSI1_WORLD, "WF" "WALLIS"}, ^ , ../drivers/staging/qcacld-3.0/core/cds/src/cds_regdomain.c:296:40: note: place parentheses around the string literal to silence warning {CTRY_WALLIS_AND_FUTUNA, ETSI1_WORLD, "WF" "WALLIS"}, ^ Signed-off-by: Danny Lin Signed-off-by: UtsavBalar1231 --- drivers/staging/qcacld-3.0/core/cds/src/cds_regdomain.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/qcacld-3.0/core/cds/src/cds_regdomain.c b/drivers/staging/qcacld-3.0/core/cds/src/cds_regdomain.c index f8f55d2a4c8c..b66e62b8c740 100644 --- a/drivers/staging/qcacld-3.0/core/cds/src/cds_regdomain.c +++ b/drivers/staging/qcacld-3.0/core/cds/src/cds_regdomain.c @@ -281,7 +281,7 @@ static const struct country_code_to_reg_dmn g_all_countries[] = { {CTRY_TRINIDAD_Y_TOBAGO, FCC3_WORLD, "TT", "TRINIDAD AND TOBAGO"}, {CTRY_TUNISIA, ETSI3_WORLD, "TN", "TUNISIA"}, {CTRY_TURKEY, ETSI1_WORLD, "TR", "TURKEY"}, - {CTRY_TURKS_AND_CAICOS, FCC3_WORLD, "TC" "TURKS AND CAICOS"}, + {CTRY_TURKS_AND_CAICOS, FCC3_WORLD, "TC", "TURKS AND CAICOS"}, {CTRY_UGANDA, FCC3_WORLD, "UG", "UGANDA"}, {CTRY_UKRAINE, ETSI9_WORLD, "UA", "UKRAINE"}, {CTRY_UAE, FCC3_WORLD, "AE", "UNITED ARAB EMIRATES"}, @@ -293,7 +293,7 @@ static const struct country_code_to_reg_dmn g_all_countries[] = { {CTRY_VENEZUELA, FCC2_ETSIC, "VE", "VENEZUELA"}, {CTRY_VIET_NAM, FCC3_WORLD, "VN", "VIETNAM"}, {CTRY_VIRGIN_ISLANDS, FCC3_FCCA, "VI", "VIRGIN ISLANDS"}, - {CTRY_WALLIS_AND_FUTUNA, ETSI1_WORLD, "WF" "WALLIS"}, + {CTRY_WALLIS_AND_FUTUNA, ETSI1_WORLD, "WF", "WALLIS"}, {CTRY_YEMEN, NULL1_WORLD, "YE", "YEMEN"}, {CTRY_ZIMBABWE, ETSI1_WORLD, "ZW", "ZIMBABWE"}, {CTRY_JAPAN15, MKK5_MKKC, "JP", "JAPAN"}, From e66aba9ff2312f6bcdc4645d57470ff3833ef5ca Mon Sep 17 00:00:00 2001 From: Danny Lin Date: Tue, 11 Aug 2020 22:20:08 -0700 Subject: [PATCH 512/592] qcacmn: Fix suspicious string concatenation warning in fwlog Clang warns: drivers/staging/qcacld-3.0/../qca-wifi-host-cmn/utils/fwlog/dbglog_host.c:745:3: error: suspicious concatenation of string literals in an array initialization; did you mean to separate the elements with a comma? [-Werror,-Wstring-concatenation] "BEACON_EVENT_SWBA_SEND_FAILED", ^ ../drivers/staging/qcacld-3.0/../qca-wifi-host-cmn/utils/fwlog/dbglog_host.c:744:3: note: place parentheses around the string literal to silence warning {"" /* BEACON */ ^ 1 error generated. Signed-off-by: Danny Lin Signed-off-by: UtsavBalar1231 --- drivers/staging/qca-wifi-host-cmn/utils/fwlog/dbglog_host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/qca-wifi-host-cmn/utils/fwlog/dbglog_host.c b/drivers/staging/qca-wifi-host-cmn/utils/fwlog/dbglog_host.c index ea3c6fc4f75b..d0debea6fff2 100644 --- a/drivers/staging/qca-wifi-host-cmn/utils/fwlog/dbglog_host.c +++ b/drivers/staging/qca-wifi-host-cmn/utils/fwlog/dbglog_host.c @@ -741,7 +741,7 @@ char *DBG_MSG_ARR[WLAN_MODULE_ID_MAX][MAX_DBG_MSGS] = { }, {"" /* HOST */ }, - {"" /* BEACON */ + { /* BEACON */ "BEACON_EVENT_SWBA_SEND_FAILED", "BEACON_EVENT_EARLY_RX_BMISS_STATUS", "BEACON_EVENT_EARLY_RX_SLEEP_SLOP", From eb4bea09e81ee9f878a94e75fdf3be6c571d189c Mon Sep 17 00:00:00 2001 From: Danny Lin Date: Fri, 7 Aug 2020 18:03:18 -0700 Subject: [PATCH 513/592] clk: qcom: clk-cpu-osm: Allow overriding CPU frequency tables in DT Sometimes, it may be desirable to use CPU frequency tables different from the ones in the hardware's OSM LUTs. This commit adds support for overriding each CPU's frequency table with a list of allowed frequencies defined in the OSM driver's DT node. Signed-off-by: Danny Lin Signed-off-by: UtsavBalar1231 --- .../devicetree/bindings/arm/msm/qcom,osm.txt | 57 +++++++++++++++++++ drivers/clk/qcom/clk-cpu-osm.c | 47 ++++++++++++++- 2 files changed, 103 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/arm/msm/qcom,osm.txt b/Documentation/devicetree/bindings/arm/msm/qcom,osm.txt index eec96f18ee31..d8dd4c2f128a 100644 --- a/Documentation/devicetree/bindings/arm/msm/qcom,osm.txt +++ b/Documentation/devicetree/bindings/arm/msm/qcom,osm.txt @@ -36,6 +36,13 @@ Properties: Definition: List of phandles to devices that the OPP tables with the L3 frequency and voltage mappings are loaded for. +- qcom,cpufreq-table-XX + Usage: optional + Value type: + Definition: List of frequencies (in kHz) to expose in CPU XX's cpufreq table. + All frequencies present in hardware will be exposed if this list + is not present. + Example: clock_cpucc: qcom,cpucc { compatible = "qcom,clk-cpu-osm"; @@ -49,4 +56,54 @@ Example: l3-devs = <&phandle0 &phandle1 &phandle2>; #clock-cells = <1>; + qcom,cpufreq-table-0 = + < 300000>, + < 403200>, + < 480000>, + < 576000>, + < 672000>, + < 768000>, + < 864000>, + < 979200>, + <1075200>, + <1171200>, + <1267200>; + + qcom,cpufreq-table-4 = + < 576000>, + < 672000>, + < 768000>, + < 864000>, + < 960000>, + <1056000>, + <1152000>, + <1248000>, + <1344000>, + <1420800>, + <1497600>, + <1593600>, + <1689600>, + <1785600>, + <1862400>, + <1939200>, + <2016000>; + + qcom,cpufreq-table-7 = + < 691200>, + < 768000>, + < 864000>, + < 940800>, + <1017600>, + <1113600>, + <1190400>, + <1286400>, + <1363200>, + <1459200>, + <1536000>, + <1632000>, + <1728000>, + <1824000>, + <1900800>, + <1977600>, + <2054400>; }; diff --git a/drivers/clk/qcom/clk-cpu-osm.c b/drivers/clk/qcom/clk-cpu-osm.c index ef6cbe663ddf..180de2df3fb6 100644 --- a/drivers/clk/qcom/clk-cpu-osm.c +++ b/drivers/clk/qcom/clk-cpu-osm.c @@ -68,6 +68,7 @@ struct osm_entry { }; struct clk_osm { + struct device *dev; struct clk_hw hw; struct osm_entry osm_table[OSM_TABLE_SIZE]; struct dentry *debugfs; @@ -643,13 +644,30 @@ static unsigned int osm_cpufreq_get(unsigned int cpu) return policy->freq_table[index].frequency; } +static bool osm_dt_find_freq(u32 *of_table, int of_len, long frequency) +{ + int i; + + if (!of_table) + return true; + + for (i = 0; i < of_len; i++) { + if (frequency == of_table[i]) + return true; + } + + return false; +} + static int osm_cpufreq_cpu_init(struct cpufreq_policy *policy) { struct cpufreq_frequency_table *table; struct clk_osm *c, *parent; struct clk_hw *p_hw; - int ret; + int ret, of_len; unsigned int i; + u32 *of_table = NULL; + char tbl_name[] = "qcom,cpufreq-table-##"; c = osm_configure_policy(policy); if (!c) { @@ -666,6 +684,26 @@ static int osm_cpufreq_cpu_init(struct cpufreq_policy *policy) parent = to_clk_osm(p_hw); c->vbase = parent->vbase; + snprintf(tbl_name, sizeof(tbl_name), "qcom,cpufreq-table-%d", policy->cpu); + if (of_find_property(parent->dev->of_node, tbl_name, &of_len) && of_len > 0) { + of_len /= sizeof(*of_table); + + of_table = kcalloc(of_len, sizeof(*of_table), GFP_KERNEL); + if (!of_table) { + pr_err("failed to allocate DT frequency table memory for CPU%d\n", + policy->cpu); + return -ENOMEM; + } + + ret = of_property_read_u32_array(parent->dev->of_node, tbl_name, + of_table, of_len); + if (ret) { + pr_err("failed to read DT frequency table for CPU%d, err=%d\n", + policy->cpu, ret); + return ret; + } + } + table = kcalloc(parent->osm_table_size + 1, sizeof(*table), GFP_KERNEL); if (!table) return -ENOMEM; @@ -686,6 +724,10 @@ static int osm_cpufreq_cpu_init(struct cpufreq_policy *policy) table[i].frequency = (XO_RATE * lval) / 1000; table[i].driver_data = table[i].frequency; + /* Ignore frequency if not present in DT table */ + if (!osm_dt_find_freq(of_table, of_len, table[i].frequency)) + table[i].frequency = CPUFREQ_ENTRY_INVALID; + if (core_count == SINGLE_CORE_COUNT) table[i].frequency = CPUFREQ_ENTRY_INVALID; @@ -715,9 +757,11 @@ static int osm_cpufreq_cpu_init(struct cpufreq_policy *policy) cpumask_copy(policy->cpus, &c->related_cpus); + kfree(of_table); return 0; err: + kfree(of_table); kfree(table); return ret; } @@ -946,6 +990,7 @@ static int clk_osm_read_lut(struct platform_device *pdev, struct clk_osm *c) { u32 data, src, lval, i, j = c->osm_table_size; + c->dev = &pdev->dev; for (i = 0; i < c->osm_table_size; i++) { data = clk_osm_read_reg(c, FREQ_REG + i * OSM_REG_SIZE); src = ((data & GENMASK(31, 30)) >> 30); From 046bc4205ec2076b6a8b315065720fb78ec0e583 Mon Sep 17 00:00:00 2001 From: Danny Lin Date: Fri, 7 Aug 2020 18:16:47 -0700 Subject: [PATCH 514/592] arm64: dts: sm8150: Add full CPU frequency tables These contain all possible hardware frequencies for sm8150-v1, sm8150-v2, and sm8150p, so no behavior is changed. Signed-off-by: Danny Lin Signed-off-by: UtsavBalar1231 --- arch/arm64/boot/dts/qcom/sm8150-v2.dtsi | 64 +++++++++++++++++++++++++ arch/arm64/boot/dts/qcom/sm8150.dtsi | 50 +++++++++++++++++++ 2 files changed, 114 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm8150-v2.dtsi b/arch/arm64/boot/dts/qcom/sm8150-v2.dtsi index d9da79994ba1..60b5b968a509 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-v2.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-v2.dtsi @@ -29,6 +29,70 @@ /delete-node/ suspendable-ddr-bw-opp-table; }; +&clock_cpucc { + qcom,cpufreq-table-0 = + < 300000>, + < 403200>, + < 499200>, + < 576000>, + < 672000>, + < 768000>, + < 844800>, + < 940800>, + <1036800>, + <1113600>, + <1209600>, + <1305600>, + <1382400>, + <1478400>, + <1555200>, + <1632000>, + <1708800>, + <1785600>; + + qcom,cpufreq-table-4 = + < 710400>, + < 825600>, + < 940800>, + <1056000>, + <1171200>, + <1286400>, + <1401600>, + <1497600>, + <1612800>, + <1708800>, + <1804800>, + <1920000>, + <2016000>, + <2131200>, + <2227200>, + <2323200>, + <2419200>; + + qcom,cpufreq-table-7 = + < 825600>, + < 940800>, + <1056000>, + <1171200>, + <1286400>, + <1401600>, + <1497600>, + <1612800>, + <1708800>, + <1804800>, + <1920000>, + <2016000>, + <2131200>, + <2227200>, + <2323200>, + <2419200>, + <2534400>, + <2649600>, + <2745600>, + <2841600>, + <2956800>; +}; + &mdss_mdp { qcom,fullsize-va-map; qcom,sde-min-core-ib-kbps = <0>; diff --git a/arch/arm64/boot/dts/qcom/sm8150.dtsi b/arch/arm64/boot/dts/qcom/sm8150.dtsi index 800f8a26abb7..0ca17d3a3af9 100644 --- a/arch/arm64/boot/dts/qcom/sm8150.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150.dtsi @@ -1544,6 +1544,56 @@ &cpu7_cpu_l3_lat>; #clock-cells = <1>; + qcom,cpufreq-table-0 = + < 300000>, + < 403200>, + < 480000>, + < 576000>, + < 672000>, + < 768000>, + < 864000>, + < 979200>, + <1075200>, + <1171200>, + <1267200>; + + qcom,cpufreq-table-4 = + < 576000>, + < 672000>, + < 768000>, + < 864000>, + < 960000>, + <1056000>, + <1152000>, + <1248000>, + <1344000>, + <1420800>, + <1497600>, + <1593600>, + <1689600>, + <1785600>, + <1862400>, + <1939200>, + <2016000>; + + qcom,cpufreq-table-7 = + < 691200>, + < 768000>, + < 864000>, + < 940800>, + <1017600>, + <1113600>, + <1190400>, + <1286400>, + <1363200>, + <1459200>, + <1536000>, + <1632000>, + <1728000>, + <1824000>, + <1900800>, + <1977600>, + <2054400>; }; clock_debugcc: qcom,cc-debug { From 86155e5d849ad60b9e73731c2f3db1e234eeec0e Mon Sep 17 00:00:00 2001 From: UtsavBalar1231 Date: Sat, 8 Aug 2020 10:26:20 +0530 Subject: [PATCH 515/592] ARM64: dts: ea8076: re-organize documentation Signed-off-by: UtsavBalar1231 --- .../dts/qcom/dsi-panel-ss-fhd-ea8076-cmd.dtsi | 36 ++++++--- .../dsi-panel-ss-fhd-ea8076-global-cmd.dtsi | 81 ++++++++++++------- 2 files changed, 78 insertions(+), 39 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-ss-fhd-ea8076-cmd.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-ss-fhd-ea8076-cmd.dtsi index b408d5f100b4..37270d7e99a8 100644 --- a/arch/arm64/boot/dts/qcom/dsi-panel-ss-fhd-ea8076-cmd.dtsi +++ b/arch/arm64/boot/dts/qcom/dsi-panel-ss-fhd-ea8076-cmd.dtsi @@ -59,7 +59,7 @@ qcom,mdss-dsi-panel-blackness-level = <3230>; qcom,mdss-dsi-panel-fod-dimlayer-enabled; - qcom,dispparam-enabled; + qcom,dispparam-enabled; qcom,mdss-panel-on-dimming-delay = <90>; qcom,mdss-dsi-panel-dc-threshold = <610>; /* IRQF_ONESHOT | IRQF_TRIGGER_FALLING */ @@ -116,31 +116,36 @@ qcom,mdss-dsi-panel-clockrate = <1100000000>; qcom,mdss-dsi-panel-jitter = <0x5 0x1>; qcom,mdss-dsi-on-command = [ + /* Sleep Out */ 05 01 00 00 0A 00 02 11 00 39 00 00 00 00 00 03 F0 5A 5A + /* TE OUT(Vsync On) */ 39 00 00 00 00 00 02 35 00 + /* DBV Smooth Transition */ 39 00 00 00 00 00 03 B7 01 4B - /* Dimming Speed Setting */ + /* Edge Dimming Speed Setting */ 39 01 00 00 00 00 03 F0 A5 A5 + /* Page Address Set */ 39 01 00 00 00 00 05 2B 00 00 09 23 - /* ESD Setting */ 39 00 00 00 00 00 03 F0 5A 5A 39 00 00 00 00 00 03 FC 5A 5A /* Set DDIC internal HFP */ 39 00 00 00 00 00 02 B0 23 39 00 00 00 00 00 02 D1 0F - /* OFC Setting */ - 39 00 00 00 00 00 0C E9 11 55 A6 75 A3 B9 A1 4A 00 1A B8 /* Err_FG Setting */ 39 00 00 00 00 00 07 E1 00 00 02 02 42 02 39 00 00 00 00 00 07 E2 00 00 00 00 00 00 39 00 00 00 00 00 02 B0 0C 39 00 00 00 00 00 02 E1 19 + /* OFC Setting */ + 39 00 00 00 00 00 0C E9 11 55 A6 75 A3 B9 A1 4A 00 1A B8 39 00 00 00 00 00 03 F0 A5 A5 39 01 00 00 00 00 03 FC A5 A5 + /* Brightness Control */ 39 00 00 00 00 00 02 53 20 39 00 00 00 00 00 03 51 00 00 39 01 00 00 43 00 02 55 00 + /* Display On */ 05 01 00 00 00 00 02 29 00]; qcom,mdss-dsi-off-command = [ 05 01 00 00 00 00 02 28 00 @@ -149,6 +154,7 @@ qcom,mdss-dsi-off-command-state = "dsi_lp_mode"; qcom,mdss-dsi-doze-hbm-command = [ + /* AOD ON Sequence (Normal To AOD HBM) */ 39 00 00 00 00 00 03 F0 5A 5A 39 00 00 00 00 00 02 D4 8B 39 00 00 00 00 00 02 B0 A5 @@ -158,6 +164,7 @@ 39 01 00 00 01 00 02 53 22 39 01 00 00 00 00 03 F0 A5 A5]; qcom,mdss-dsi-doze-lbm-command = [ + /* AOD ON Sequence (Normal To AOD LBM) */ 39 00 00 00 00 00 03 F0 5A 5A 39 00 00 00 00 00 02 D4 8B 39 00 00 00 00 00 02 B0 A5 @@ -167,6 +174,7 @@ 39 01 00 00 00 00 02 53 23 39 01 00 00 00 00 03 F0 A5 A5]; qcom,mdss-dsi-nolp-command = [ + /* AOD OFF Sequence (AOD To Normal) */ 05 01 00 00 10 00 02 28 00 39 01 00 00 00 00 02 53 20 05 01 00 00 00 00 02 29 00]; @@ -261,26 +269,36 @@ qcom,mdss-dsi-panel-clockrate = <1210000000>; qcom,mdss-dsi-panel-jitter = <0x8 0x1>; qcom,mdss-dsi-on-command = [ + /* Sleep Out */ 05 01 00 00 0A 00 02 11 00 39 00 00 00 00 00 03 F0 5A 5A + /* TE OUT(Vsync On) */ 39 00 00 00 00 00 02 35 00 - 39 00 00 00 00 00 03 B7 01 5A //smooth transition + /* DBV Smooth Transition */ + 39 00 00 00 00 00 03 B7 01 4B + /* Edge Dimming Speed Setting */ 39 01 00 00 00 00 03 F0 A5 A5 + /* Page Address Set */ 39 01 00 00 00 00 05 2B 00 00 09 23 - 39 00 00 00 00 00 03 F0 5A 5A /* esd */ + 39 00 00 00 00 00 03 F0 5A 5A 39 00 00 00 00 00 03 FC 5A 5A - 39 00 00 00 00 00 02 B0 23 //osc + /* Set DDIC internal HFP */ + 39 00 00 00 00 00 02 B0 23 39 00 00 00 00 00 02 D1 0F - 39 00 00 00 00 00 0C E9 11 55 A6 75 A3 B9 A1 4A 00 1A B8 + /* Err_FG Setting */ 39 00 00 00 00 00 07 E1 00 00 02 02 42 02 39 00 00 00 00 00 07 E2 00 00 00 00 00 00 39 00 00 00 00 00 02 B0 0C 39 00 00 00 00 00 02 E1 19 + /* OFC Setting */ + 39 00 00 00 00 00 0C E9 11 55 A6 75 A3 B9 A1 4A 00 1A B8 39 00 00 00 00 00 03 F0 A5 A5 39 01 00 00 00 00 03 FC A5 A5 + /* Brightness Control */ 39 00 00 00 00 00 02 53 20 39 00 00 00 00 00 03 51 00 00 39 01 00 00 43 00 02 55 00 + /* Display On */ 05 01 00 00 00 00 02 29 00]; qcom,mdss-dsi-off-command = [ 05 01 00 00 00 00 02 28 00 diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-ss-fhd-ea8076-global-cmd.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-ss-fhd-ea8076-global-cmd.dtsi index 42b397e85d50..8013263c2fec 100644 --- a/arch/arm64/boot/dts/qcom/dsi-panel-ss-fhd-ea8076-global-cmd.dtsi +++ b/arch/arm64/boot/dts/qcom/dsi-panel-ss-fhd-ea8076-global-cmd.dtsi @@ -116,32 +116,37 @@ qcom,mdss-dsi-panel-clockrate = <1103000000>; qcom,mdss-dsi-panel-jitter = <0x5 0x1>; qcom,mdss-dsi-on-command = [ - 05 01 00 00 0A 00 02 11 00 - 39 00 00 00 00 00 03 F0 5A 5A - 39 00 00 00 00 00 02 35 00 - 39 00 00 00 00 00 03 B7 01 4B - /* Dimming Speed Setting */ - 39 01 00 00 00 00 03 F0 A5 A5 - 39 01 00 00 00 00 05 2B 00 00 09 23 - /* ESD Setting */ - 39 00 00 00 00 00 03 F0 5A 5A - 39 00 00 00 00 00 03 FC 5A 5A - /* Set DDIC internal HFP */ - 39 00 00 00 00 00 02 B0 23 - 39 00 00 00 00 00 02 D1 11 - /* OFC Setting */ - 39 00 00 00 00 00 0C E9 11 55 A6 75 A3 B9 A1 4A 00 1A B8 - /* Err_FG Setting */ - 39 00 00 00 00 00 07 E1 00 00 02 02 42 02 - 39 00 00 00 00 00 07 E2 00 00 00 00 00 00 - 39 00 00 00 00 00 02 B0 0C - 39 00 00 00 00 00 02 E1 19 - 39 00 00 00 00 00 03 F0 A5 A5 - 39 01 00 00 00 00 03 FC A5 A5 - 39 00 00 00 00 00 02 53 20 - 39 00 00 00 00 00 03 51 00 00 - 39 01 00 00 43 00 02 55 00 - 05 01 00 00 00 00 02 29 00]; + /* Sleep Out */ + 05 01 00 00 0A 00 02 11 00 + 39 00 00 00 00 00 03 F0 5A 5A + /* TE OUT(Vsync On) */ + 39 00 00 00 00 00 02 35 00 + /* DBV Smooth Transition */ + 39 00 00 00 00 00 03 B7 01 4B + /* Edge Dimming Speed Setting */ + 39 01 00 00 00 00 03 F0 A5 A5 + /* Page Address Set */ + 39 01 00 00 00 00 05 2B 00 00 09 23 + 39 00 00 00 00 00 03 F0 5A 5A + 39 00 00 00 00 00 03 FC 5A 5A + /* Set DDIC internal HFP */ + 39 00 00 00 00 00 02 B0 23 + 39 00 00 00 00 00 02 D1 0F + /* Err_FG Setting */ + 39 00 00 00 00 00 07 E1 00 00 02 02 42 02 + 39 00 00 00 00 00 07 E2 00 00 00 00 00 00 + 39 00 00 00 00 00 02 B0 0C + 39 00 00 00 00 00 02 E1 19 + /* OFC Setting */ + 39 00 00 00 00 00 0C E9 11 55 A6 75 A3 B9 A1 4A 00 1A B8 + 39 00 00 00 00 00 03 F0 A5 A5 + 39 01 00 00 00 00 03 FC A5 A5 + /* Brightness Control */ + 39 00 00 00 00 00 02 53 20 + 39 00 00 00 00 00 03 51 00 00 + 39 01 00 00 43 00 02 55 00 + /* Display On */ + 05 01 00 00 00 00 02 29 00]; qcom,mdss-dsi-off-command = [ 05 01 00 00 00 00 02 28 00 05 01 00 00 78 00 02 10 00]; @@ -149,6 +154,7 @@ qcom,mdss-dsi-off-command-state = "dsi_lp_mode"; qcom,mdss-dsi-doze-hbm-command = [ + /* AOD ON Sequence (Normal To AOD HBM) */ 39 00 00 00 00 00 03 F0 5A 5A 39 00 00 00 00 00 02 D4 8B 39 00 00 00 00 00 02 B0 A5 @@ -158,6 +164,7 @@ 39 01 00 00 01 00 02 53 22 39 01 00 00 00 00 03 F0 A5 A5]; qcom,mdss-dsi-doze-lbm-command = [ + /* AOD ON Sequence (Normal To AOD LBM) */ 39 00 00 00 00 00 03 F0 5A 5A 39 00 00 00 00 00 02 D4 8B 39 00 00 00 00 00 02 B0 A5 @@ -167,6 +174,7 @@ 39 01 00 00 00 00 02 53 23 39 01 00 00 00 00 03 F0 A5 A5]; qcom,mdss-dsi-nolp-command = [ + /* AOD OFF Sequence (AOD To Normal) */ 05 01 00 00 10 00 02 28 00 39 01 00 00 00 00 02 53 20 05 01 00 00 00 00 02 29 00]; @@ -261,26 +269,36 @@ qcom,mdss-dsi-panel-clockrate = <1210000000>; qcom,mdss-dsi-panel-jitter = <0x8 0x1>; qcom,mdss-dsi-on-command = [ + /* Sleep Out */ 05 01 00 00 0A 00 02 11 00 39 00 00 00 00 00 03 F0 5A 5A + /* TE OUT(Vsync On) */ 39 00 00 00 00 00 02 35 00 - 39 00 00 00 00 00 03 B7 01 5A //smooth transtion + /* DBV Smooth Transition */ + 39 00 00 00 00 00 03 B7 01 4B + /* Edge Dimming Speed Setting */ 39 01 00 00 00 00 03 F0 A5 A5 + /* Page Address Set */ 39 01 00 00 00 00 05 2B 00 00 09 23 - 39 00 00 00 00 00 03 F0 5A 5A /* esd */ + 39 00 00 00 00 00 03 F0 5A 5A 39 00 00 00 00 00 03 FC 5A 5A - 39 00 00 00 00 00 02 B0 23 //osc + /* Set DDIC internal HFP */ + 39 00 00 00 00 00 02 B0 23 39 00 00 00 00 00 02 D1 0F - 39 00 00 00 00 00 0C E9 11 55 A6 75 A3 B9 A1 4A 00 1A B8 + /* Err_FG Setting */ 39 00 00 00 00 00 07 E1 00 00 02 02 42 02 39 00 00 00 00 00 07 E2 00 00 00 00 00 00 39 00 00 00 00 00 02 B0 0C 39 00 00 00 00 00 02 E1 19 + /* OFC Setting */ + 39 00 00 00 00 00 0C E9 11 55 A6 75 A3 B9 A1 4A 00 1A B8 39 00 00 00 00 00 03 F0 A5 A5 39 01 00 00 00 00 03 FC A5 A5 + /* Brightness Control */ 39 00 00 00 00 00 02 53 20 39 00 00 00 00 00 03 51 00 00 39 01 00 00 43 00 02 55 00 + /* Display On */ 05 01 00 00 00 00 02 29 00]; qcom,mdss-dsi-off-command = [ 05 01 00 00 00 00 02 28 00 @@ -289,6 +307,7 @@ qcom,mdss-dsi-off-command-state = "dsi_lp_mode"; qcom,mdss-dsi-doze-hbm-command = [ + /* AOD ON Sequence (Normal To AOD HBM) */ 39 00 00 00 00 00 03 F0 5A 5A 39 00 00 00 00 00 02 D4 8B 39 00 00 00 00 00 02 B0 A5 @@ -298,6 +317,7 @@ 39 01 00 00 01 00 02 53 22 39 01 00 00 00 00 03 F0 A5 A5]; qcom,mdss-dsi-doze-lbm-command = [ + /* AOD ON Sequence (Normal To AOD LBM) */ 39 00 00 00 00 00 03 F0 5A 5A 39 00 00 00 00 00 02 D4 8B 39 00 00 00 00 00 02 B0 A5 @@ -307,6 +327,7 @@ 39 01 00 00 00 00 02 53 23 39 01 00 00 00 00 03 F0 A5 A5]; qcom,mdss-dsi-nolp-command = [ + /* AOD OFF Sequence (AOD To Normal) */ 05 01 00 00 10 00 02 28 00 39 01 00 00 00 00 02 53 20 05 01 00 00 00 00 02 29 00]; From ef7e6705875c39db8024120920de8538a9b7aee2 Mon Sep 17 00:00:00 2001 From: Yaroslav Furman Date: Sat, 11 Apr 2020 02:11:00 +0300 Subject: [PATCH 516/592] drivers: gt9886: mark IRQ as performance critical Speed up touchscreen processing. Signed-off-by: Yaroslav Furman Signed-off-by: UtsavBalar1231 --- drivers/input/touchscreen/goodix_driver_gt9886/goodix_ts_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/touchscreen/goodix_driver_gt9886/goodix_ts_core.c b/drivers/input/touchscreen/goodix_driver_gt9886/goodix_ts_core.c index 0f6cc980d75a..d8d6a74517e3 100644 --- a/drivers/input/touchscreen/goodix_driver_gt9886/goodix_ts_core.c +++ b/drivers/input/touchscreen/goodix_driver_gt9886/goodix_ts_core.c @@ -969,7 +969,7 @@ int goodix_ts_irq_setup(struct goodix_ts_core *core_data) r = devm_request_threaded_irq(&core_data->pdev->dev, core_data->irq, NULL, goodix_ts_threadirq_func, - ts_bdata->irq_flags | IRQF_ONESHOT, + ts_bdata->irq_flags | IRQF_ONESHOT | IRQF_PERF_CRITICAL, GOODIX_CORE_DRIVER_NAME, core_data); if (r < 0) From fa02e7984b5fb400f5a0e705b2d8a1af9fe62271 Mon Sep 17 00:00:00 2001 From: Yaroslav Furman Date: Sun, 2 Aug 2020 01:20:14 +0300 Subject: [PATCH 517/592] proc/base: add static branch hints in __set_oom_adj This function is executed very frequently, let's optimize it a bit. Signed-off-by: Yaroslav Furman Signed-off-by: UtsavBalar1231 --- fs/proc/base.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/proc/base.c b/fs/proc/base.c index 6e0e64bd11a0..a54bb37af414 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -1027,7 +1027,7 @@ static int __set_oom_adj(struct file *file, int oom_adj, bool legacy) return -ESRCH; mutex_lock(&oom_adj_mutex); - if (legacy) { + if (unlikely(legacy)) { if (oom_adj < task->signal->oom_score_adj && !capable(CAP_SYS_RESOURCE)) { err = -EACCES; @@ -1066,7 +1066,7 @@ static int __set_oom_adj(struct file *file, int oom_adj, bool legacy) } task->signal->oom_score_adj = oom_adj; - if (!legacy && has_capability_noaudit(current, CAP_SYS_RESOURCE)) + if (likely(!legacy) && has_capability_noaudit(current, CAP_SYS_RESOURCE)) task->signal->oom_score_adj_min = (short)oom_adj; trace_oom_score_adj_update(task); @@ -1085,7 +1085,7 @@ static int __set_oom_adj(struct file *file, int oom_adj, bool legacy) task_lock(p); if (!p->vfork_done && process_shares_mm(p, mm)) { p->signal->oom_score_adj = oom_adj; - if (!legacy && has_capability_noaudit(current, CAP_SYS_RESOURCE)) + if (likely(!legacy) && has_capability_noaudit(current, CAP_SYS_RESOURCE)) p->signal->oom_score_adj_min = (short)oom_adj; } task_unlock(p); From 5e53904ac9eba3f9684ad23854d5756c3f344a38 Mon Sep 17 00:00:00 2001 From: Yaroslav Furman Date: Sun, 2 Aug 2020 01:29:11 +0300 Subject: [PATCH 518/592] Revert "mm/slab_common: Align all caches' objects to hardware cachelines" Perf improvement is unmeasurable. This reverts commit bb089de8996fa69eaef598a6e5779cf1e8416d19. Signed-off-by: Yaroslav Furman Signed-off-by: UtsavBalar1231 --- mm/slab_common.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/mm/slab_common.c b/mm/slab_common.c index b873a85bbea1..7fe72acfa501 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c @@ -462,9 +462,6 @@ kmem_cache_create(const char *name, size_t size, size_t align, */ flags &= CACHE_CREATE_MASK; - /* Embrace davem */ - flags |= SLAB_HWCACHE_ALIGN; - s = __kmem_cache_alias(name, size, align, flags, ctor); if (s) goto out_unlock; From 2b7cf1f9be64d0963db2177514c04c60ab4de6ba Mon Sep 17 00:00:00 2001 From: UtsavBalar1231 Date: Sun, 16 Aug 2020 22:33:11 +0530 Subject: [PATCH 519/592] Revert "goodix_driver_gt9886: use async probing and suspend/resume" hocus pocus your dt2w now works This reverts commit 9427a8e2f1a7de0baf6eb8db3b9765b64ce43b20. Signed-off-by: UtsavBalar1231 --- drivers/input/touchscreen/goodix_driver_gt9886/goodix_ts_core.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/input/touchscreen/goodix_driver_gt9886/goodix_ts_core.c b/drivers/input/touchscreen/goodix_driver_gt9886/goodix_ts_core.c index d8d6a74517e3..75816175d121 100644 --- a/drivers/input/touchscreen/goodix_driver_gt9886/goodix_ts_core.c +++ b/drivers/input/touchscreen/goodix_driver_gt9886/goodix_ts_core.c @@ -2190,7 +2190,6 @@ static int goodix_ts_probe(struct platform_device *pdev) } #endif - device_enable_async_suspend(&pdev->dev); out: backlight_unregister_notifier(&core_data->bl_notifier); ts_info("goodix_ts_probe OUT, r:%d", r); @@ -2231,7 +2230,6 @@ static struct platform_driver goodix_ts_driver = { #ifdef CONFIG_PM .pm = &dev_pm_ops, #endif - .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, .probe = goodix_ts_probe, .remove = goodix_ts_remove, From 115ae53eca9a563b553edb0a80725059f5e2e1ce Mon Sep 17 00:00:00 2001 From: UtsavBalar1231 Date: Sun, 16 Aug 2020 22:39:47 +0530 Subject: [PATCH 520/592] Revert "cpufreq: Only block min freq setting for booster processes" This reverts commit f67dd314b6db4b63eb169a588793225ad6573f1b. --- drivers/cpufreq/cpufreq.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 6bcbf1d36475..db33268b47fa 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -18,7 +18,6 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#include #include #include #include @@ -728,8 +727,7 @@ static ssize_t store_##file_name \ int ret, temp; \ struct cpufreq_policy new_policy; \ \ - if (&policy->object == &policy->min && \ - task_is_booster(current)) \ + if (&policy->object == &policy->min) \ return count; \ \ memcpy(&new_policy, policy, sizeof(*policy)); \ From 52f9eda9566ddba310301fea62bbaa7ae58eb5d1 Mon Sep 17 00:00:00 2001 From: UtsavBalar1231 Date: Sun, 16 Aug 2020 23:17:15 +0530 Subject: [PATCH 521/592] ARM64: configs: raphael: Disable IKHEADERS Signed-off-by: UtsavBalar1231 --- arch/arm64/configs/raphael_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/configs/raphael_defconfig b/arch/arm64/configs/raphael_defconfig index eea8b4c56f14..acf159685f4e 100644 --- a/arch/arm64/configs/raphael_defconfig +++ b/arch/arm64/configs/raphael_defconfig @@ -126,7 +126,7 @@ CONFIG_RCU_NOCB_CPU=y CONFIG_BUILD_BIN2C=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y -CONFIG_IKHEADERS=y +# CONFIG_IKHEADERS is not set CONFIG_LOG_BUF_SHIFT=17 # CONFIG_CONSOLE_FLUSH_ON_HOTPLUG is not set CONFIG_LOG_CPU_MAX_BUF_SHIFT=17 From b8ba38485cf8c8ff9a967f84b667b33ef32f0471 Mon Sep 17 00:00:00 2001 From: Sultan Alsawaf Date: Mon, 22 Apr 2019 11:13:55 -0700 Subject: [PATCH 522/592] cpu_input_boost: Introduce driver for event-based CPU boosting This is a simple CPU input boost driver that boosts all online CPUs for a fixed amount of time. Additionally, there is an API for other drivers to request a boost kick (or a max-boost kick), so boosting can be done on any custom event. This API is mainly intended for the framebuffer driver to send a boost kick whenever there is a new frame ready to be rendered to the display. This driver also boosts all online CPUs to their maximum frequencies when the display is powered on (this is the wake boost). Since this driver requires careful tuning for optimal performance, there are no user-exposed knobs to configure it. All necessary configuration is done via the supplied Kconfig options. This driver is designed for heterogeneous multi-processor systems with two CPU clusters. Signed-off-by: Sultan Alsawaf idkwhoiam322: adapt for 4.14 Signed-off-by: idkwhoiam322 Signed-off-by: celtare21 Signed-off-by: UtsavBalar1231 --- drivers/cpufreq/Kconfig | 62 +++++ drivers/cpufreq/Makefile | 3 + drivers/cpufreq/cpu_input_boost.c | 368 ++++++++++++++++++++++++++++++ include/linux/cpu_input_boost.h | 20 ++ 4 files changed, 453 insertions(+) create mode 100644 drivers/cpufreq/cpu_input_boost.c create mode 100644 include/linux/cpu_input_boost.h diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index db8c2890accd..39dce9651115 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -295,6 +295,68 @@ config CPU_FREQ_DEFAULT_PRIME_MIN If in doubt, say 0 to use the hardware's minimum frequency. +config CPU_INPUT_BOOST + bool "CPU Input Boost" + help + Boosts the CPU on touchscreen and touchpad input, and allows for + boosting on other custom events, mainly which is intended to be for + boosting when there is a new frame ready to be rendered to the + display. The boost frequencies for this driver should be set so that + frame drops are near-zero at the boosted frequencies and power + consumption is minimized at said frequency combination. + +if CPU_INPUT_BOOST + +config INPUT_BOOST_DURATION_MS + int "Input boost duration" + default "100" + help + Input boost duration in milliseconds. + +config WAKE_BOOST_DURATION_MS + int "Wake boost duration" + default "1000" + help + Wake boost duration in milliseconds. + +config INPUT_BOOST_FREQ_LP + int "Low-power cluster boost freq" + default "0" + help + Input boost frequency for the low-power CPU cluster. + +config INPUT_BOOST_FREQ_PERF + int "Performance cluster boost freq" + default "0" + help + Input boost frequency for the performance CPU cluster. + +config INPUT_BOOST_FREQ_PERFP + int "Prime cluster boost freq" + default "0" + help + Input boost frequency for the prime CPU cluster. + +config MAX_BOOST_FREQ_LP + int "Low-power cluster max-boost freq" + default "0" + help + Max-boost frequency for the low-power CPU cluster. + +config MAX_BOOST_FREQ_PERF + int "Performance cluster max-boost freq" + default "0" + help + Max-boost frequency for the performance CPU cluster. + +config MAX_BOOST_FREQ_PERFP + int "Prime cluster max-boost freq" + default "0" + help + Max-boost frequency for the prime CPU cluster. + +endif + comment "CPU frequency scaling drivers" config CPUFREQ_DT diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index 6d92de038fdc..c5abbf7aa58a 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -19,6 +19,9 @@ obj-$(CONFIG_CPU_FREQ_GOV_COMMON) += cpufreq_governor.o obj-$(CONFIG_CPU_FREQ_GOV_ATTR_SET) += cpufreq_governor_attr_set.o obj-$(CONFIG_CPU_BOOST) += cpu-boost.o +# CPU Input Boost +obj-$(CONFIG_CPU_INPUT_BOOST) += cpu_input_boost.o + obj-$(CONFIG_CPUFREQ_DT) += cpufreq-dt.o obj-$(CONFIG_CPUFREQ_DT_PLATDEV) += cpufreq-dt-platdev.o diff --git a/drivers/cpufreq/cpu_input_boost.c b/drivers/cpufreq/cpu_input_boost.c new file mode 100644 index 000000000000..c2816f62e687 --- /dev/null +++ b/drivers/cpufreq/cpu_input_boost.c @@ -0,0 +1,368 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018-2019 Sultan Alsawaf . + */ + +#define pr_fmt(fmt) "cpu_input_boost: " fmt + +#include +#include +#include +#include +#include +#include +#include + +/* The sched_param struct is located elsewhere in newer kernels */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0) +#include +#endif + +enum { + SCREEN_OFF, + INPUT_BOOST, + MAX_BOOST +}; + +struct boost_drv { + struct delayed_work input_unboost; + struct delayed_work max_unboost; + struct notifier_block cpu_notif; + struct notifier_block msm_drm_notif; + wait_queue_head_t boost_waitq; + atomic_long_t max_boost_expires; + unsigned long state; +}; + +static void input_unboost_worker(struct work_struct *work); +static void max_unboost_worker(struct work_struct *work); + +static struct boost_drv boost_drv_g __read_mostly = { + .input_unboost = __DELAYED_WORK_INITIALIZER(boost_drv_g.input_unboost, + input_unboost_worker, 0), + .max_unboost = __DELAYED_WORK_INITIALIZER(boost_drv_g.max_unboost, + max_unboost_worker, 0), + .boost_waitq = __WAIT_QUEUE_HEAD_INITIALIZER(boost_drv_g.boost_waitq) +}; + +static unsigned int get_input_boost_freq(struct cpufreq_policy *policy) +{ + unsigned int freq; + + if (cpumask_test_cpu(policy->cpu, cpu_lp_mask)) + freq = CONFIG_INPUT_BOOST_FREQ_LP; + else if (cpumask_test_cpu(policy->cpu, cpu_perf_mask)) + freq = CONFIG_INPUT_BOOST_FREQ_PERF; + else + freq = CONFIG_INPUT_BOOST_FREQ_PERFP; + return min(freq, policy->max); +} + +static unsigned int get_max_boost_freq(struct cpufreq_policy *policy) +{ + unsigned int freq; + + if (cpumask_test_cpu(policy->cpu, cpu_lp_mask)) + freq = CONFIG_MAX_BOOST_FREQ_LP; + else if (cpumask_test_cpu(policy->cpu, cpu_perf_mask)) + freq = CONFIG_MAX_BOOST_FREQ_PERF; + else + freq = CONFIG_MAX_BOOST_FREQ_PERFP; + return min(freq, policy->max); +} + +static void update_online_cpu_policy(void) +{ + unsigned int cpu; + + /* Only one CPU from each cluster needs to be updated */ + get_online_cpus(); + cpu = cpumask_first_and(cpu_lp_mask, cpu_online_mask); + cpufreq_update_policy(cpu); + cpu = cpumask_first_and(cpu_perf_mask, cpu_online_mask); + cpufreq_update_policy(cpu); + cpu = cpumask_first_and(cpu_perfp_mask, cpu_online_mask); + cpufreq_update_policy(cpu); + put_online_cpus(); +} + +static void __cpu_input_boost_kick(struct boost_drv *b) +{ + if (test_bit(SCREEN_OFF, &b->state)) + return; + + set_bit(INPUT_BOOST, &b->state); + if (!mod_delayed_work(system_unbound_wq, &b->input_unboost, + msecs_to_jiffies(CONFIG_INPUT_BOOST_DURATION_MS))) + wake_up(&b->boost_waitq); +} + +void cpu_input_boost_kick(void) +{ + struct boost_drv *b = &boost_drv_g; + + __cpu_input_boost_kick(b); +} + +static void __cpu_input_boost_kick_max(struct boost_drv *b, + unsigned int duration_ms) +{ + unsigned long boost_jiffies = msecs_to_jiffies(duration_ms); + unsigned long curr_expires, new_expires; + + if (test_bit(SCREEN_OFF, &b->state)) + return; + + do { + curr_expires = atomic_long_read(&b->max_boost_expires); + new_expires = jiffies + boost_jiffies; + + /* Skip this boost if there's a longer boost in effect */ + if (time_after(curr_expires, new_expires)) + return; + } while (atomic_long_cmpxchg(&b->max_boost_expires, curr_expires, + new_expires) != curr_expires); + + set_bit(MAX_BOOST, &b->state); + if (!mod_delayed_work(system_unbound_wq, &b->max_unboost, + boost_jiffies)) + wake_up(&b->boost_waitq); +} + +void cpu_input_boost_kick_max(unsigned int duration_ms) +{ + struct boost_drv *b = &boost_drv_g; + + __cpu_input_boost_kick_max(b, duration_ms); +} + +static void input_unboost_worker(struct work_struct *work) +{ + struct boost_drv *b = container_of(to_delayed_work(work), + typeof(*b), input_unboost); + + clear_bit(INPUT_BOOST, &b->state); + wake_up(&b->boost_waitq); +} + +static void max_unboost_worker(struct work_struct *work) +{ + struct boost_drv *b = container_of(to_delayed_work(work), + typeof(*b), max_unboost); + + clear_bit(MAX_BOOST, &b->state); + wake_up(&b->boost_waitq); +} + +static int cpu_boost_thread(void *data) +{ + static const struct sched_param sched_max_rt_prio = { + .sched_priority = MAX_RT_PRIO - 1 + }; + struct boost_drv *b = data; + unsigned long old_state = 0; + + sched_setscheduler_nocheck(current, SCHED_FIFO, &sched_max_rt_prio); + + while (1) { + bool should_stop = false; + unsigned long curr_state; + + wait_event(b->boost_waitq, + (curr_state = READ_ONCE(b->state)) != old_state || + (should_stop = kthread_should_stop())); + + if (should_stop) + break; + + old_state = curr_state; + update_online_cpu_policy(); + } + + return 0; +} + +static int cpu_notifier_cb(struct notifier_block *nb, unsigned long action, + void *data) +{ + struct boost_drv *b = container_of(nb, typeof(*b), cpu_notif); + struct cpufreq_policy *policy = data; + + if (action != CPUFREQ_ADJUST) + return NOTIFY_OK; + + /* Unboost when the screen is off */ + if (test_bit(SCREEN_OFF, &b->state)) { + policy->min = policy->cpuinfo.min_freq; + return NOTIFY_OK; + } + + /* Boost CPU to max frequency for max boost */ + if (test_bit(MAX_BOOST, &b->state)) { + policy->min = get_max_boost_freq(policy); + return NOTIFY_OK; + } + + /* + * Boost to policy->max if the boost frequency is higher. When + * unboosting, set policy->min to the absolute min freq for the CPU. + */ + if (test_bit(INPUT_BOOST, &b->state)) + policy->min = get_input_boost_freq(policy); + else + policy->min = policy->cpuinfo.min_freq; + + return NOTIFY_OK; +} + +static int msm_drm_notifier_cb(struct notifier_block *nb, unsigned long action, + void *data) +{ + struct boost_drv *b = container_of(nb, typeof(*b), msm_drm_notif); + struct msm_drm_notifier *evdata = data; + int *blank = evdata->data; + + /* Parse framebuffer blank events as soon as they occur */ + if (action != MSM_DRM_EARLY_EVENT_BLANK) + return NOTIFY_OK; + + /* Boost when the screen turns on and unboost when it turns off */ + if (*blank == MSM_DRM_BLANK_UNBLANK_CUST) { + clear_bit(SCREEN_OFF, &b->state); + __cpu_input_boost_kick_max(b, CONFIG_WAKE_BOOST_DURATION_MS); + } else { + set_bit(SCREEN_OFF, &b->state); + wake_up(&b->boost_waitq); + } + + return NOTIFY_OK; +} + +static void cpu_input_boost_input_event(struct input_handle *handle, + unsigned int type, unsigned int code, + int value) +{ + struct boost_drv *b = handle->handler->private; + + __cpu_input_boost_kick(b); +} + +static int cpu_input_boost_input_connect(struct input_handler *handler, + struct input_dev *dev, + const struct input_device_id *id) +{ + struct input_handle *handle; + int ret; + + handle = kzalloc(sizeof(*handle), GFP_KERNEL); + if (!handle) + return -ENOMEM; + + handle->dev = dev; + handle->handler = handler; + handle->name = "cpu_input_boost_handle"; + + ret = input_register_handle(handle); + if (ret) + goto free_handle; + + ret = input_open_device(handle); + if (ret) + goto unregister_handle; + + return 0; + +unregister_handle: + input_unregister_handle(handle); +free_handle: + kfree(handle); + return ret; +} + +static void cpu_input_boost_input_disconnect(struct input_handle *handle) +{ + input_close_device(handle); + input_unregister_handle(handle); + kfree(handle); +} + +static const struct input_device_id cpu_input_boost_ids[] = { + /* Multi-touch touchscreen */ + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT | + INPUT_DEVICE_ID_MATCH_ABSBIT, + .evbit = { BIT_MASK(EV_ABS) }, + .absbit = { [BIT_WORD(ABS_MT_POSITION_X)] = + BIT_MASK(ABS_MT_POSITION_X) | + BIT_MASK(ABS_MT_POSITION_Y) } + }, + /* Touchpad */ + { + .flags = INPUT_DEVICE_ID_MATCH_KEYBIT | + INPUT_DEVICE_ID_MATCH_ABSBIT, + .keybit = { [BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH) }, + .absbit = { [BIT_WORD(ABS_X)] = + BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) } + }, + /* Keypad */ + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT, + .evbit = { BIT_MASK(EV_KEY) } + }, + { } +}; + +static struct input_handler cpu_input_boost_input_handler = { + .event = cpu_input_boost_input_event, + .connect = cpu_input_boost_input_connect, + .disconnect = cpu_input_boost_input_disconnect, + .name = "cpu_input_boost_handler", + .id_table = cpu_input_boost_ids +}; + +static int __init cpu_input_boost_init(void) +{ + struct boost_drv *b = &boost_drv_g; + struct task_struct *thread; + int ret; + + b->cpu_notif.notifier_call = cpu_notifier_cb; + ret = cpufreq_register_notifier(&b->cpu_notif, CPUFREQ_POLICY_NOTIFIER); + if (ret) { + pr_err("Failed to register cpufreq notifier, err: %d\n", ret); + return ret; + } + + cpu_input_boost_input_handler.private = b; + ret = input_register_handler(&cpu_input_boost_input_handler); + if (ret) { + pr_err("Failed to register input handler, err: %d\n", ret); + goto unregister_cpu_notif; + } + + b->msm_drm_notif.notifier_call = msm_drm_notifier_cb; + b->msm_drm_notif.priority = INT_MAX; + ret = msm_drm_register_client(&b->msm_drm_notif); + if (ret) { + pr_err("Failed to register msm_drm notifier, err: %d\n", ret); + goto unregister_handler; + } + + thread = kthread_run(cpu_boost_thread, b, "cpu_boostd"); + if (IS_ERR(thread)) { + ret = PTR_ERR(thread); + pr_err("Failed to start CPU boost thread, err: %d\n", ret); + goto unregister_fb_notif; + } + + return 0; + +unregister_fb_notif: + msm_drm_unregister_client(&b->msm_drm_notif); +unregister_handler: + input_unregister_handler(&cpu_input_boost_input_handler); +unregister_cpu_notif: + cpufreq_unregister_notifier(&b->cpu_notif, CPUFREQ_POLICY_NOTIFIER); + return ret; +} +subsys_initcall(cpu_input_boost_init); diff --git a/include/linux/cpu_input_boost.h b/include/linux/cpu_input_boost.h new file mode 100644 index 000000000000..a988039ffd7d --- /dev/null +++ b/include/linux/cpu_input_boost.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2018-2019 Sultan Alsawaf . + */ +#ifndef _CPU_INPUT_BOOST_H_ +#define _CPU_INPUT_BOOST_H_ + +#ifdef CONFIG_CPU_INPUT_BOOST +void cpu_input_boost_kick(void); +void cpu_input_boost_kick_max(unsigned int duration_ms); +#else +static inline void cpu_input_boost_kick(void) +{ +} +static inline void cpu_input_boost_kick_max(unsigned int duration_ms) +{ +} +#endif + +#endif /* _CPU_INPUT_BOOST_H_ */ From 6899944bb3a9c721fda52a5b3b96e531f49709e7 Mon Sep 17 00:00:00 2001 From: celtare21 Date: Mon, 8 Jun 2020 15:01:35 +0200 Subject: [PATCH 523/592] cpufreq: cpu_input_boost: Remove all input boost code and adjust * We'll only use it for screen on and app launch events. Signed-off-by: celtare21 Signed-off-by: UtsavBalar1231 --- drivers/cpufreq/Kconfig | 24 ----- drivers/cpufreq/cpu_input_boost.c | 173 ++++-------------------------- include/linux/cpu_input_boost.h | 4 - 3 files changed, 22 insertions(+), 179 deletions(-) diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index 39dce9651115..be399b9e50f4 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -307,36 +307,12 @@ config CPU_INPUT_BOOST if CPU_INPUT_BOOST -config INPUT_BOOST_DURATION_MS - int "Input boost duration" - default "100" - help - Input boost duration in milliseconds. - config WAKE_BOOST_DURATION_MS int "Wake boost duration" default "1000" help Wake boost duration in milliseconds. -config INPUT_BOOST_FREQ_LP - int "Low-power cluster boost freq" - default "0" - help - Input boost frequency for the low-power CPU cluster. - -config INPUT_BOOST_FREQ_PERF - int "Performance cluster boost freq" - default "0" - help - Input boost frequency for the performance CPU cluster. - -config INPUT_BOOST_FREQ_PERFP - int "Prime cluster boost freq" - default "0" - help - Input boost frequency for the prime CPU cluster. - config MAX_BOOST_FREQ_LP int "Low-power cluster max-boost freq" default "0" diff --git a/drivers/cpufreq/cpu_input_boost.c b/drivers/cpufreq/cpu_input_boost.c index c2816f62e687..dbc3b422c087 100644 --- a/drivers/cpufreq/cpu_input_boost.c +++ b/drivers/cpufreq/cpu_input_boost.c @@ -20,12 +20,10 @@ enum { SCREEN_OFF, - INPUT_BOOST, MAX_BOOST }; struct boost_drv { - struct delayed_work input_unboost; struct delayed_work max_unboost; struct notifier_block cpu_notif; struct notifier_block msm_drm_notif; @@ -34,30 +32,14 @@ struct boost_drv { unsigned long state; }; -static void input_unboost_worker(struct work_struct *work); static void max_unboost_worker(struct work_struct *work); static struct boost_drv boost_drv_g __read_mostly = { - .input_unboost = __DELAYED_WORK_INITIALIZER(boost_drv_g.input_unboost, - input_unboost_worker, 0), .max_unboost = __DELAYED_WORK_INITIALIZER(boost_drv_g.max_unboost, max_unboost_worker, 0), .boost_waitq = __WAIT_QUEUE_HEAD_INITIALIZER(boost_drv_g.boost_waitq) }; -static unsigned int get_input_boost_freq(struct cpufreq_policy *policy) -{ - unsigned int freq; - - if (cpumask_test_cpu(policy->cpu, cpu_lp_mask)) - freq = CONFIG_INPUT_BOOST_FREQ_LP; - else if (cpumask_test_cpu(policy->cpu, cpu_perf_mask)) - freq = CONFIG_INPUT_BOOST_FREQ_PERF; - else - freq = CONFIG_INPUT_BOOST_FREQ_PERFP; - return min(freq, policy->max); -} - static unsigned int get_max_boost_freq(struct cpufreq_policy *policy) { unsigned int freq; @@ -68,9 +50,24 @@ static unsigned int get_max_boost_freq(struct cpufreq_policy *policy) freq = CONFIG_MAX_BOOST_FREQ_PERF; else freq = CONFIG_MAX_BOOST_FREQ_PERFP; + return min(freq, policy->max); } +static unsigned int get_min_freq(struct cpufreq_policy *policy) +{ + unsigned int freq; + + if (cpumask_test_cpu(policy->cpu, cpu_lp_mask)) + freq = CONFIG_CPU_FREQ_DEFAULT_LITTLE_MIN; + else if (cpumask_test_cpu(policy->cpu, cpu_perf_mask)) + freq = CONFIG_CPU_FREQ_DEFAULT_BIG_MIN; + else + freq = CONFIG_CPU_FREQ_DEFAULT_PRIME_MIN; + + return max(freq, policy->cpuinfo.min_freq); +} + static void update_online_cpu_policy(void) { unsigned int cpu; @@ -86,24 +83,6 @@ static void update_online_cpu_policy(void) put_online_cpus(); } -static void __cpu_input_boost_kick(struct boost_drv *b) -{ - if (test_bit(SCREEN_OFF, &b->state)) - return; - - set_bit(INPUT_BOOST, &b->state); - if (!mod_delayed_work(system_unbound_wq, &b->input_unboost, - msecs_to_jiffies(CONFIG_INPUT_BOOST_DURATION_MS))) - wake_up(&b->boost_waitq); -} - -void cpu_input_boost_kick(void) -{ - struct boost_drv *b = &boost_drv_g; - - __cpu_input_boost_kick(b); -} - static void __cpu_input_boost_kick_max(struct boost_drv *b, unsigned int duration_ms) { @@ -136,15 +115,6 @@ void cpu_input_boost_kick_max(unsigned int duration_ms) __cpu_input_boost_kick_max(b, duration_ms); } -static void input_unboost_worker(struct work_struct *work) -{ - struct boost_drv *b = container_of(to_delayed_work(work), - typeof(*b), input_unboost); - - clear_bit(INPUT_BOOST, &b->state); - wake_up(&b->boost_waitq); -} - static void max_unboost_worker(struct work_struct *work) { struct boost_drv *b = container_of(to_delayed_work(work), @@ -192,10 +162,8 @@ static int cpu_notifier_cb(struct notifier_block *nb, unsigned long action, return NOTIFY_OK; /* Unboost when the screen is off */ - if (test_bit(SCREEN_OFF, &b->state)) { - policy->min = policy->cpuinfo.min_freq; - return NOTIFY_OK; - } + if (test_bit(SCREEN_OFF, &b->state)) + goto min; /* Boost CPU to max frequency for max boost */ if (test_bit(MAX_BOOST, &b->state)) { @@ -203,15 +171,9 @@ static int cpu_notifier_cb(struct notifier_block *nb, unsigned long action, return NOTIFY_OK; } - /* - * Boost to policy->max if the boost frequency is higher. When - * unboosting, set policy->min to the absolute min freq for the CPU. - */ - if (test_bit(INPUT_BOOST, &b->state)) - policy->min = get_input_boost_freq(policy); - else - policy->min = policy->cpuinfo.min_freq; - +min: + /* Set policy->min to the absolute min freq for the CPU */ + policy->min = get_min_freq(policy); return NOTIFY_OK; } @@ -227,7 +189,7 @@ static int msm_drm_notifier_cb(struct notifier_block *nb, unsigned long action, return NOTIFY_OK; /* Boost when the screen turns on and unboost when it turns off */ - if (*blank == MSM_DRM_BLANK_UNBLANK_CUST) { + if (*blank == MSM_DRM_BLANK_UNBLANK) { clear_bit(SCREEN_OFF, &b->state); __cpu_input_boost_kick_max(b, CONFIG_WAKE_BOOST_DURATION_MS); } else { @@ -238,88 +200,6 @@ static int msm_drm_notifier_cb(struct notifier_block *nb, unsigned long action, return NOTIFY_OK; } -static void cpu_input_boost_input_event(struct input_handle *handle, - unsigned int type, unsigned int code, - int value) -{ - struct boost_drv *b = handle->handler->private; - - __cpu_input_boost_kick(b); -} - -static int cpu_input_boost_input_connect(struct input_handler *handler, - struct input_dev *dev, - const struct input_device_id *id) -{ - struct input_handle *handle; - int ret; - - handle = kzalloc(sizeof(*handle), GFP_KERNEL); - if (!handle) - return -ENOMEM; - - handle->dev = dev; - handle->handler = handler; - handle->name = "cpu_input_boost_handle"; - - ret = input_register_handle(handle); - if (ret) - goto free_handle; - - ret = input_open_device(handle); - if (ret) - goto unregister_handle; - - return 0; - -unregister_handle: - input_unregister_handle(handle); -free_handle: - kfree(handle); - return ret; -} - -static void cpu_input_boost_input_disconnect(struct input_handle *handle) -{ - input_close_device(handle); - input_unregister_handle(handle); - kfree(handle); -} - -static const struct input_device_id cpu_input_boost_ids[] = { - /* Multi-touch touchscreen */ - { - .flags = INPUT_DEVICE_ID_MATCH_EVBIT | - INPUT_DEVICE_ID_MATCH_ABSBIT, - .evbit = { BIT_MASK(EV_ABS) }, - .absbit = { [BIT_WORD(ABS_MT_POSITION_X)] = - BIT_MASK(ABS_MT_POSITION_X) | - BIT_MASK(ABS_MT_POSITION_Y) } - }, - /* Touchpad */ - { - .flags = INPUT_DEVICE_ID_MATCH_KEYBIT | - INPUT_DEVICE_ID_MATCH_ABSBIT, - .keybit = { [BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH) }, - .absbit = { [BIT_WORD(ABS_X)] = - BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) } - }, - /* Keypad */ - { - .flags = INPUT_DEVICE_ID_MATCH_EVBIT, - .evbit = { BIT_MASK(EV_KEY) } - }, - { } -}; - -static struct input_handler cpu_input_boost_input_handler = { - .event = cpu_input_boost_input_event, - .connect = cpu_input_boost_input_connect, - .disconnect = cpu_input_boost_input_disconnect, - .name = "cpu_input_boost_handler", - .id_table = cpu_input_boost_ids -}; - static int __init cpu_input_boost_init(void) { struct boost_drv *b = &boost_drv_g; @@ -333,19 +213,12 @@ static int __init cpu_input_boost_init(void) return ret; } - cpu_input_boost_input_handler.private = b; - ret = input_register_handler(&cpu_input_boost_input_handler); - if (ret) { - pr_err("Failed to register input handler, err: %d\n", ret); - goto unregister_cpu_notif; - } - b->msm_drm_notif.notifier_call = msm_drm_notifier_cb; b->msm_drm_notif.priority = INT_MAX; ret = msm_drm_register_client(&b->msm_drm_notif); if (ret) { pr_err("Failed to register msm_drm notifier, err: %d\n", ret); - goto unregister_handler; + goto unregister_cpu_notif; } thread = kthread_run(cpu_boost_thread, b, "cpu_boostd"); @@ -359,8 +232,6 @@ static int __init cpu_input_boost_init(void) unregister_fb_notif: msm_drm_unregister_client(&b->msm_drm_notif); -unregister_handler: - input_unregister_handler(&cpu_input_boost_input_handler); unregister_cpu_notif: cpufreq_unregister_notifier(&b->cpu_notif, CPUFREQ_POLICY_NOTIFIER); return ret; diff --git a/include/linux/cpu_input_boost.h b/include/linux/cpu_input_boost.h index a988039ffd7d..3c0860cc3c9b 100644 --- a/include/linux/cpu_input_boost.h +++ b/include/linux/cpu_input_boost.h @@ -6,12 +6,8 @@ #define _CPU_INPUT_BOOST_H_ #ifdef CONFIG_CPU_INPUT_BOOST -void cpu_input_boost_kick(void); void cpu_input_boost_kick_max(unsigned int duration_ms); #else -static inline void cpu_input_boost_kick(void) -{ -} static inline void cpu_input_boost_kick_max(unsigned int duration_ms) { } From 22eaf3447c67518cc71093452dcfe5d089d0aeb0 Mon Sep 17 00:00:00 2001 From: celtare21 Date: Wed, 12 Aug 2020 12:32:46 +0200 Subject: [PATCH 524/592] cpufreq: cpu_input_boost: Don't touch the prime cluster Signed-off-by: celtare21 Signed-off-by: UtsavBalar1231 --- drivers/cpufreq/cpu_input_boost.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/cpufreq/cpu_input_boost.c b/drivers/cpufreq/cpu_input_boost.c index dbc3b422c087..65c6d7f47fe7 100644 --- a/drivers/cpufreq/cpu_input_boost.c +++ b/drivers/cpufreq/cpu_input_boost.c @@ -78,8 +78,6 @@ static void update_online_cpu_policy(void) cpufreq_update_policy(cpu); cpu = cpumask_first_and(cpu_perf_mask, cpu_online_mask); cpufreq_update_policy(cpu); - cpu = cpumask_first_and(cpu_perfp_mask, cpu_online_mask); - cpufreq_update_policy(cpu); put_online_cpus(); } From 9df0b265e6c0b712956177dfaa84839fc1a2a3f1 Mon Sep 17 00:00:00 2001 From: UtsavBalar1231 Date: Sun, 16 Aug 2020 22:43:10 +0530 Subject: [PATCH 525/592] ARM64: configs: raphael: Enable CIB Signed-off-by: UtsavBalar1231 --- arch/arm64/configs/raphael_defconfig | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/configs/raphael_defconfig b/arch/arm64/configs/raphael_defconfig index acf159685f4e..c3afd3b6f7ba 100644 --- a/arch/arm64/configs/raphael_defconfig +++ b/arch/arm64/configs/raphael_defconfig @@ -747,6 +747,11 @@ CONFIG_SCHEDUTIL_DOWN_RATE_LIMIT=20000 CONFIG_CPU_FREQ_DEFAULT_LITTLE_MIN=768000 CONFIG_CPU_FREQ_DEFAULT_BIG_MIN=1056000 CONFIG_CPU_FREQ_DEFAULT_PRIME_MIN=1171200 +CONFIG_CPU_INPUT_BOOST=y +CONFIG_WAKE_BOOST_DURATION_MS=1000 +CONFIG_MAX_BOOST_FREQ_LP=1785600 +CONFIG_MAX_BOOST_FREQ_PERF=2323200 +CONFIG_MAX_BOOST_FREQ_PERFP=2649600 # # CPU frequency scaling drivers From 1d249c659aa6ce0f608dda9935671c06611b2cce Mon Sep 17 00:00:00 2001 From: Sultan Alsawaf Date: Fri, 14 Aug 2020 20:08:19 -0700 Subject: [PATCH 526/592] scsi: ufs: Only create one pm_qos object for the IRQ Creating multiple pm_qos objects for the same IRQ causes them to clash with one another. Since we're not using the nonsensical pm_qos groups anyway, just force it to only create one pm_qos object. Signed-off-by: Sultan Alsawaf Signed-off-by: celtare21 Signed-off-by: UtsavBalar1231 --- drivers/scsi/ufs/ufs-qcom.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index becb6ae75a33..d6b1f23e2d69 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -1900,28 +1900,16 @@ static int ufs_qcom_pm_qos_init(struct ufs_qcom_host *host) struct device_node *node = host->hba->dev->of_node; struct device_attribute *attr; int ret = 0; - int num_groups; int num_values; char wq_name[sizeof("ufs_pm_qos_00")]; int i; - num_groups = of_property_count_u32_elems(node, - "qcom,pm-qos-cpu-groups"); - if (num_groups <= 0) - goto no_pm_qos; - num_values = of_property_count_u32_elems(node, "qcom,pm-qos-cpu-group-latency-us"); if (num_values <= 0) goto no_pm_qos; - if (num_values != num_groups || num_groups > num_possible_cpus()) { - dev_err(host->hba->dev, "%s: invalid count: num_groups=%d, num_values=%d, num_possible_cpus=%d\n", - __func__, num_groups, num_values, num_possible_cpus()); - goto no_pm_qos; - } - - host->pm_qos.num_groups = num_groups; + host->pm_qos.num_groups = 1; host->pm_qos.groups = kcalloc(host->pm_qos.num_groups, sizeof(struct ufs_qcom_pm_qos_cpu_group), GFP_KERNEL); if (!host->pm_qos.groups) From 3d69d2464048e76576aaca86c1102956275f45a9 Mon Sep 17 00:00:00 2001 From: celtare21 Date: Sat, 15 Aug 2020 11:07:32 +0200 Subject: [PATCH 527/592] Revert "irq/core: Fix boot crash when the irqaffinity= boot parameter is passed on CPUMASK_OFFSTACK=y kernels(v1)" This reverts commit 07a1c2d1131b2675776480118d0855845cfffaef. Signed-off-by: celtare21 Signed-off-by: UtsavBalar1231 --- kernel/irq/irqdesc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c index 92784b290564..3744a9a2dbdf 100644 --- a/kernel/irq/irqdesc.c +++ b/kernel/irq/irqdesc.c @@ -27,7 +27,7 @@ static struct lock_class_key irq_desc_lock_class; #if defined(CONFIG_SMP) static int __init irq_affinity_setup(char *str) { - alloc_bootmem_cpumask_var(&irq_default_affinity); + zalloc_cpumask_var(&irq_default_affinity, GFP_NOWAIT); cpulist_parse(str, irq_default_affinity); /* * Set at least the boot cpu. We don't want to end up with @@ -40,8 +40,10 @@ __setup("irqaffinity=", irq_affinity_setup); static void __init init_irq_default_affinity(void) { - if (!cpumask_available(irq_default_affinity)) +#ifdef CONFIG_CPUMASK_OFFSTACK + if (!irq_default_affinity) zalloc_cpumask_var(&irq_default_affinity, GFP_NOWAIT); +#endif if (cpumask_empty(irq_default_affinity)) cpumask_setall(irq_default_affinity); } From 2c193c9897b9de2500fad470fd623f281979cb69 Mon Sep 17 00:00:00 2001 From: celtare21 Date: Sat, 15 Aug 2020 11:07:52 +0200 Subject: [PATCH 528/592] Revert "genirq: Add default affinity mask command line option" This reverts commit fbf198030e0b027538c290300cfaf9e2efdce122. Signed-off-by: celtare21 Signed-off-by: UtsavBalar1231 --- kernel/irq/irqdesc.c | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c index 3744a9a2dbdf..01c59e5d0955 100644 --- a/kernel/irq/irqdesc.c +++ b/kernel/irq/irqdesc.c @@ -25,27 +25,10 @@ static struct lock_class_key irq_desc_lock_class; #if defined(CONFIG_SMP) -static int __init irq_affinity_setup(char *str) -{ - zalloc_cpumask_var(&irq_default_affinity, GFP_NOWAIT); - cpulist_parse(str, irq_default_affinity); - /* - * Set at least the boot cpu. We don't want to end up with - * bugreports caused by random comandline masks - */ - cpumask_set_cpu(smp_processor_id(), irq_default_affinity); - return 1; -} -__setup("irqaffinity=", irq_affinity_setup); - static void __init init_irq_default_affinity(void) { -#ifdef CONFIG_CPUMASK_OFFSTACK - if (!irq_default_affinity) - zalloc_cpumask_var(&irq_default_affinity, GFP_NOWAIT); -#endif - if (cpumask_empty(irq_default_affinity)) - cpumask_setall(irq_default_affinity); + alloc_cpumask_var(&irq_default_affinity, GFP_NOWAIT); + cpumask_setall(irq_default_affinity); } #else static void __init init_irq_default_affinity(void) From 99e0da68853421d9a1108f807badf0e9ad98b9ba Mon Sep 17 00:00:00 2001 From: Sultan Alsawaf Date: Fri, 14 Aug 2020 20:11:38 -0700 Subject: [PATCH 529/592] kernel: Only set one CPU in the default IRQ affinity mask On ARM, IRQs are executed on the first CPU inside the affinity mask, so setting an affinity mask with more than one CPU set is deceptive and causes issues with pm_qos. To fix this, only set the CPU0 bit inside the affinity mask, since that's where IRQs will run by default. This is a follow-up to "kernel: Don't allow IRQ affinity masks to have more than one CPU". Signed-off-by: Sultan Alsawaf Signed-off-by: celtare21 Signed-off-by: UtsavBalar1231 --- kernel/irq/irqdesc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c index 01c59e5d0955..1305e57ddd2d 100644 --- a/kernel/irq/irqdesc.c +++ b/kernel/irq/irqdesc.c @@ -27,8 +27,8 @@ static struct lock_class_key irq_desc_lock_class; #if defined(CONFIG_SMP) static void __init init_irq_default_affinity(void) { - alloc_cpumask_var(&irq_default_affinity, GFP_NOWAIT); - cpumask_setall(irq_default_affinity); + zalloc_cpumask_var(&irq_default_affinity, GFP_NOWAIT); + cpumask_set_cpu(0, irq_default_affinity); } #else static void __init init_irq_default_affinity(void) From 8da7ea0182edcaac5cd0b564557c72fc6c3d74f6 Mon Sep 17 00:00:00 2001 From: Sultan Alsawaf Date: Fri, 14 Aug 2020 21:09:13 -0700 Subject: [PATCH 530/592] kernel: Warn when an IRQ's affinity notifier gets overwritten An IRQ affinity notifier getting overwritten can point to some annoying issues which need to be resolved, like multiple pm_qos objects being registered to the same IRQ. Print out a warning when this happens to aid debugging. Signed-off-by: Sultan Alsawaf Signed-off-by: celtare21 Signed-off-by: UtsavBalar1231 --- kernel/irq/manage.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 3fe3ccd0eea9..639a6de48b4c 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -341,6 +341,8 @@ irq_set_affinity_notifier(unsigned int irq, struct irq_affinity_notify *notify) raw_spin_unlock_irqrestore(&desc->lock, flags); if (old_notify) { + if (notify) + WARN(1, "overwriting previous IRQ affinity notifier\n"); if (cancel_work_sync(&old_notify->work)) { /* Pending work had a ref, put that one too */ kref_put(&old_notify->kref, old_notify->release); From c700274130183ee92c50ba00ee07713d14105bd9 Mon Sep 17 00:00:00 2001 From: UtsavBalar1231 Date: Mon, 17 Aug 2020 08:52:18 +0530 Subject: [PATCH 531/592] Revert "soc:qcom:icnss Async suspend/resume callbacks." bruh go into suspend This reverts commit ac24011533e1c88e8217eaac66a12bee5815a789. Signed-off-by: UtsavBalar1231 --- drivers/soc/qcom/icnss.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c index 1b145e90d7d8..dead80705242 100644 --- a/drivers/soc/qcom/icnss.c +++ b/drivers/soc/qcom/icnss.c @@ -3859,8 +3859,6 @@ static int icnss_probe(struct platform_device *pdev) goto out_unregister_ext_modem; } - device_enable_async_suspend(dev); - spin_lock_init(&priv->event_lock); spin_lock_init(&priv->on_off_lock); mutex_init(&priv->dev_lock); From 76255a4d95d98ec8102a8e9f9e5e1c13f7ffe6ba Mon Sep 17 00:00:00 2001 From: UtsavBalar1231 Date: Mon, 17 Aug 2020 08:58:38 +0530 Subject: [PATCH 532/592] ARM64: configs: raphael: some cpu related changes Signed-off-by: UtsavBalar1231 --- arch/arm64/configs/raphael_defconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm64/configs/raphael_defconfig b/arch/arm64/configs/raphael_defconfig index c3afd3b6f7ba..e9b2930fc06f 100644 --- a/arch/arm64/configs/raphael_defconfig +++ b/arch/arm64/configs/raphael_defconfig @@ -741,10 +741,10 @@ CONFIG_CPU_FREQ_GOV_POWERSAVE=y # CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set # CONFIG_CPU_BOOST is not set CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y -CONFIG_SCHEDUTIL_UP_RATE_LIMIT=500 -CONFIG_SCHEDUTIL_DOWN_RATE_LIMIT=20000 +CONFIG_SCHEDUTIL_UP_RATE_LIMIT=5000 +CONFIG_SCHEDUTIL_DOWN_RATE_LIMIT=10000 # CONFIG_CPU_FREQ_GOV_INTERACTIVE is not set -CONFIG_CPU_FREQ_DEFAULT_LITTLE_MIN=768000 +CONFIG_CPU_FREQ_DEFAULT_LITTLE_MIN=1036800 CONFIG_CPU_FREQ_DEFAULT_BIG_MIN=1056000 CONFIG_CPU_FREQ_DEFAULT_PRIME_MIN=1171200 CONFIG_CPU_INPUT_BOOST=y From d6806b642aac7b82036cf31482b65135c96b6056 Mon Sep 17 00:00:00 2001 From: UtsavBalar1231 Date: Mon, 17 Aug 2020 09:14:03 +0530 Subject: [PATCH 533/592] drivers: staging: remove staging exfat Signed-off-by: UtsavBalar1231 --- drivers/staging/Kconfig | 2 - drivers/staging/Makefile | 1 - drivers/staging/exfat/Kconfig | 41 - drivers/staging/exfat/Makefile | 10 - drivers/staging/exfat/TODO | 69 - drivers/staging/exfat/exfat.h | 760 ------ drivers/staging/exfat/exfat_blkdev.c | 138 -- drivers/staging/exfat/exfat_cache.c | 514 ---- drivers/staging/exfat/exfat_core.c | 2529 -------------------- drivers/staging/exfat/exfat_nls.c | 212 -- drivers/staging/exfat/exfat_super.c | 3296 -------------------------- drivers/staging/exfat/exfat_upcase.c | 740 ------ 12 files changed, 8312 deletions(-) delete mode 100644 drivers/staging/exfat/Kconfig delete mode 100644 drivers/staging/exfat/Makefile delete mode 100644 drivers/staging/exfat/TODO delete mode 100644 drivers/staging/exfat/exfat.h delete mode 100644 drivers/staging/exfat/exfat_blkdev.c delete mode 100644 drivers/staging/exfat/exfat_cache.c delete mode 100644 drivers/staging/exfat/exfat_core.c delete mode 100644 drivers/staging/exfat/exfat_nls.c delete mode 100644 drivers/staging/exfat/exfat_super.c delete mode 100644 drivers/staging/exfat/exfat_upcase.c diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 9fff1045d24f..627a3e0989fb 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -120,6 +120,4 @@ source "drivers/staging/pi433/Kconfig" source "drivers/staging/qcacld-3.0/Kconfig" -source "drivers/staging/exfat/Kconfig" - endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index d594c288b84d..fbc0d08612ae 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -51,4 +51,3 @@ obj-$(CONFIG_CRYPTO_DEV_CCREE) += ccree/ obj-$(CONFIG_DRM_VBOXVIDEO) += vboxvideo/ obj-$(CONFIG_PI433) += pi433/ obj-$(CONFIG_QCA_CLD_WLAN) += qcacld-3.0/ -obj-$(CONFIG_STAGING_EXFAT_FS) += exfat/ diff --git a/drivers/staging/exfat/Kconfig b/drivers/staging/exfat/Kconfig deleted file mode 100644 index 292a19dfcaf5..000000000000 --- a/drivers/staging/exfat/Kconfig +++ /dev/null @@ -1,41 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -config STAGING_EXFAT_FS - tristate "exFAT fs support" - depends on BLOCK - select NLS - help - This adds support for the exFAT file system. - -config STAGING_EXFAT_DISCARD - bool "enable discard support" - depends on STAGING_EXFAT_FS - default y - -config STAGING_EXFAT_DELAYED_SYNC - bool "enable delayed sync" - depends on STAGING_EXFAT_FS - default n - -config STAGING_EXFAT_KERNEL_DEBUG - bool "enable kernel debug features via ioctl" - depends on STAGING_EXFAT_FS - default n - -config STAGING_EXFAT_DEBUG_MSG - bool "print debug messages" - depends on STAGING_EXFAT_FS - default n - -config STAGING_EXFAT_DEFAULT_CODEPAGE - int "Default codepage for exFAT" - default 437 - depends on STAGING_EXFAT_FS - help - This option should be set to the codepage of your exFAT filesystems. - -config STAGING_EXFAT_DEFAULT_IOCHARSET - string "Default iocharset for exFAT" - default "utf8" - depends on STAGING_EXFAT_FS - help - Set this to the default input/output character set you'd like exFAT to use. diff --git a/drivers/staging/exfat/Makefile b/drivers/staging/exfat/Makefile deleted file mode 100644 index 057556eeca0c..000000000000 --- a/drivers/staging/exfat/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-or-later - -obj-$(CONFIG_STAGING_EXFAT_FS) += exfat.o - -exfat-y := exfat_core.o \ - exfat_super.o \ - exfat_blkdev.o \ - exfat_cache.o \ - exfat_nls.o \ - exfat_upcase.o diff --git a/drivers/staging/exfat/TODO b/drivers/staging/exfat/TODO deleted file mode 100644 index a283ce534cf4..000000000000 --- a/drivers/staging/exfat/TODO +++ /dev/null @@ -1,69 +0,0 @@ -A laundry list of things that need looking at, most of which will -require more work than the average checkpatch cleanup... - -Note that some of these entries may not be bugs - they're things -that need to be looked at, and *possibly* fixed. - -Clean up the ffsCamelCase function names. - -Fix (thing)->flags to not use magic numbers - multiple offenders - -Sort out all the s32/u32/u8 nonsense - most of these should be plain int. - -exfat_core.c - ffsReadFile - the goto err_out seem to leak a brelse(). -same for ffsWriteFile. - -All the calls to fs_sync() need to be looked at, particularly in the -context of EXFAT_DELAYED_SYNC. Currently, if that's defined, we only -flush to disk when sync() gets called. We should be doing at least -metadata flushes at appropriate times. - -ffsTruncateFile - if (old_size <= new_size) { -That doesn't look right. How did it ever work? Are they relying on lazy -block allocation when actual writes happen? If nothing else, it never -does the 'fid->size = new_size' and do the inode update.... - -ffsSetAttr() is just dangling in the breeze, not wired up at all... - -Convert global mutexes to a per-superblock mutex. - -Right now, we load exactly one UTF-8 table. Check to see -if that plays nice with different codepage and iocharset values -for simultanous mounts of different devices - -exfat_rmdir() checks for -EBUSY but ffsRemoveDir() doesn't return it. -In fact, there's a complete lack of -EBUSY testing anywhere. - -There's probably a few missing checks for -EEXIST - -check return codes of sync_dirty_buffer() - -Why is remove_file doing a num_entries++?? - -Double check a lot of can't-happen parameter checks (for null pointers for -things that have only one call site and can't pass a null, etc). - -All the DEBUG stuff can probably be tossed, including the ioctl(). Either -that, or convert to a proper fault-injection system. - -exfat_remount does exactly one thing. Fix to actually deal with remount -options, particularly handling R/O correctly. For that matter, allow -R/O mounts in the first place. - -Figure out why the VFAT code used multi_sector_(read|write) but the -exfat code doesn't use it. The difference matters on SSDs with wear leveling. - -exfat_fat_sync(), exfat_buf_sync(), and sync_alloc_bitmap() -aren't called anyplace.... - -Create helper function for exfat_set_entry_time() and exfat_set_entry_type() -because it's sort of ugly to be calling the same functionn directly and -other code calling through the fs_func struc ponters... - -clean up the remaining vol_type checks, which are of two types: -some are ?: operators with magic numbers, and the rest are places -where we're doing stuff with '.' and '..'. - -Patches to: - Greg Kroah-Hartman - Valdis Kletnieks diff --git a/drivers/staging/exfat/exfat.h b/drivers/staging/exfat/exfat.h deleted file mode 100644 index 341c9192f7e8..000000000000 --- a/drivers/staging/exfat/exfat.h +++ /dev/null @@ -1,760 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. - */ - -#ifndef _EXFAT_H -#define _EXFAT_H - -#include -#include - -#ifdef CONFIG_STAGING_EXFAT_KERNEL_DEBUG - /* For Debugging Purpose */ - /* IOCTL code 'f' used by - * - file systems typically #0~0x1F - * - embedded terminal devices #128~ - * - exts for debugging purpose #99 - * number 100 and 101 is available now but has possible conflicts - */ -#define EXFAT_IOC_GET_DEBUGFLAGS _IOR('f', 100, long) -#define EXFAT_IOC_SET_DEBUGFLAGS _IOW('f', 101, long) - -#define EXFAT_DEBUGFLAGS_INVALID_UMOUNT 0x01 -#define EXFAT_DEBUGFLAGS_ERROR_RW 0x02 -#endif /* CONFIG_STAGING_EXFAT_KERNEL_DEBUG */ - -#ifdef CONFIG_STAGING_EXFAT_DEBUG_MSG -#define DEBUG 1 -#else -#undef DEBUG -#endif - -#define EFSCORRUPTED EUCLEAN /* Filesystem is corrupted */ - -#define DENTRY_SIZE 32 /* dir entry size */ -#define DENTRY_SIZE_BITS 5 - -/* PBR entries */ -#define PBR_SIGNATURE 0xAA55 -#define EXT_SIGNATURE 0xAA550000 -#define VOL_LABEL "NO NAME " /* size should be 11 */ -#define OEM_NAME "MSWIN4.1" /* size should be 8 */ -#define STR_FAT12 "FAT12 " /* size should be 8 */ -#define STR_FAT16 "FAT16 " /* size should be 8 */ -#define STR_FAT32 "FAT32 " /* size should be 8 */ -#define STR_EXFAT "EXFAT " /* size should be 8 */ -#define VOL_CLEAN 0x0000 -#define VOL_DIRTY 0x0002 - -/* max number of clusters */ -#define FAT12_THRESHOLD 4087 /* 2^12 - 1 + 2 (clu 0 & 1) */ -#define FAT16_THRESHOLD 65527 /* 2^16 - 1 + 2 */ -#define FAT32_THRESHOLD 268435457 /* 2^28 - 1 + 2 */ -#define EXFAT_THRESHOLD 268435457 /* 2^28 - 1 + 2 */ - -/* file types */ -#define TYPE_UNUSED 0x0000 -#define TYPE_DELETED 0x0001 -#define TYPE_INVALID 0x0002 -#define TYPE_CRITICAL_PRI 0x0100 -#define TYPE_BITMAP 0x0101 -#define TYPE_UPCASE 0x0102 -#define TYPE_VOLUME 0x0103 -#define TYPE_DIR 0x0104 -#define TYPE_FILE 0x011F -#define TYPE_CRITICAL_SEC 0x0200 -#define TYPE_STREAM 0x0201 -#define TYPE_EXTEND 0x0202 -#define TYPE_ACL 0x0203 -#define TYPE_BENIGN_PRI 0x0400 -#define TYPE_GUID 0x0401 -#define TYPE_PADDING 0x0402 -#define TYPE_ACLTAB 0x0403 -#define TYPE_BENIGN_SEC 0x0800 -#define TYPE_ALL 0x0FFF - -/* time modes */ -#define TM_CREATE 0 -#define TM_MODIFY 1 -#define TM_ACCESS 2 - -/* checksum types */ -#define CS_DIR_ENTRY 0 -#define CS_PBR_SECTOR 1 -#define CS_DEFAULT 2 - -#define CLUSTER_16(x) ((u16)(x)) -#define CLUSTER_32(x) ((u32)(x)) - -#define START_SECTOR(x) \ - ((((sector_t)((x) - 2)) << p_fs->sectors_per_clu_bits) + \ - p_fs->data_start_sector) - -#define IS_LAST_SECTOR_IN_CLUSTER(sec) \ - ((((sec) - p_fs->data_start_sector + 1) & \ - ((1 << p_fs->sectors_per_clu_bits) - 1)) == 0) - -#define GET_CLUSTER_FROM_SECTOR(sec) \ - ((u32)((((sec) - p_fs->data_start_sector) >> \ - p_fs->sectors_per_clu_bits) + 2)) - -#define GET16(p_src) \ - (((u16)(p_src)[0]) | (((u16)(p_src)[1]) << 8)) -#define GET32(p_src) \ - (((u32)(p_src)[0]) | (((u32)(p_src)[1]) << 8) | \ - (((u32)(p_src)[2]) << 16) | (((u32)(p_src)[3]) << 24)) -#define GET64(p_src) \ - (((u64)(p_src)[0]) | (((u64)(p_src)[1]) << 8) | \ - (((u64)(p_src)[2]) << 16) | (((u64)(p_src)[3]) << 24) | \ - (((u64)(p_src)[4]) << 32) | (((u64)(p_src)[5]) << 40) | \ - (((u64)(p_src)[6]) << 48) | (((u64)(p_src)[7]) << 56)) - -#define SET16(p_dst, src) \ - do { \ - (p_dst)[0] = (u8)(src); \ - (p_dst)[1] = (u8)(((u16)(src)) >> 8); \ - } while (0) -#define SET32(p_dst, src) \ - do { \ - (p_dst)[0] = (u8)(src); \ - (p_dst)[1] = (u8)(((u32)(src)) >> 8); \ - (p_dst)[2] = (u8)(((u32)(src)) >> 16); \ - (p_dst)[3] = (u8)(((u32)(src)) >> 24); \ - } while (0) -#define SET64(p_dst, src) \ - do { \ - (p_dst)[0] = (u8)(src); \ - (p_dst)[1] = (u8)(((u64)(src)) >> 8); \ - (p_dst)[2] = (u8)(((u64)(src)) >> 16); \ - (p_dst)[3] = (u8)(((u64)(src)) >> 24); \ - (p_dst)[4] = (u8)(((u64)(src)) >> 32); \ - (p_dst)[5] = (u8)(((u64)(src)) >> 40); \ - (p_dst)[6] = (u8)(((u64)(src)) >> 48); \ - (p_dst)[7] = (u8)(((u64)(src)) >> 56); \ - } while (0) - -#ifdef __LITTLE_ENDIAN -#define GET16_A(p_src) (*((u16 *)(p_src))) -#define GET32_A(p_src) (*((u32 *)(p_src))) -#define GET64_A(p_src) (*((u64 *)(p_src))) -#define SET16_A(p_dst, src) (*((u16 *)(p_dst)) = (u16)(src)) -#define SET32_A(p_dst, src) (*((u32 *)(p_dst)) = (u32)(src)) -#define SET64_A(p_dst, src) (*((u64 *)(p_dst)) = (u64)(src)) -#else /* BIG_ENDIAN */ -#define GET16_A(p_src) GET16(p_src) -#define GET32_A(p_src) GET32(p_src) -#define GET64_A(p_src) GET64(p_src) -#define SET16_A(p_dst, src) SET16(p_dst, src) -#define SET32_A(p_dst, src) SET32(p_dst, src) -#define SET64_A(p_dst, src) SET64(p_dst, src) -#endif - -/* cache size (in number of sectors) */ -/* (should be an exponential value of 2) */ -#define FAT_CACHE_SIZE 128 -#define FAT_CACHE_HASH_SIZE 64 -#define BUF_CACHE_SIZE 256 -#define BUF_CACHE_HASH_SIZE 64 - -/* Upcase table macro */ -#define HIGH_INDEX_BIT (8) -#define HIGH_INDEX_MASK (0xFF00) -#define LOW_INDEX_BIT (16 - HIGH_INDEX_BIT) -#define UTBL_ROW_COUNT BIT(LOW_INDEX_BIT) -#define UTBL_COL_COUNT BIT(HIGH_INDEX_BIT) - -static inline u16 get_col_index(u16 i) -{ - return i >> LOW_INDEX_BIT; -} - -static inline u16 get_row_index(u16 i) -{ - return i & ~HIGH_INDEX_MASK; -} - -#define EXFAT_SUPER_MAGIC (0x2011BAB0L) -#define EXFAT_ROOT_INO 1 - -/* FAT types */ -#define FAT12 0x01 /* FAT12 */ -#define FAT16 0x0E /* Win95 FAT16 (LBA) */ -#define FAT32 0x0C /* Win95 FAT32 (LBA) */ -#define EXFAT 0x07 /* exFAT */ - -/* file name lengths */ -#define MAX_CHARSET_SIZE 3 /* max size of multi-byte character */ -#define MAX_PATH_DEPTH 15 /* max depth of path name */ -#define MAX_NAME_LENGTH 256 /* max len of filename including NULL */ -#define MAX_PATH_LENGTH 260 /* max len of pathname including NULL */ - -/* file attributes */ -#define ATTR_NORMAL 0x0000 -#define ATTR_READONLY 0x0001 -#define ATTR_HIDDEN 0x0002 -#define ATTR_SYSTEM 0x0004 -#define ATTR_VOLUME 0x0008 -#define ATTR_SUBDIR 0x0010 -#define ATTR_ARCHIVE 0x0020 -#define ATTR_EXTEND 0x000F -#define ATTR_RWMASK 0x007E - -#define NUM_UPCASE 2918 - -#ifdef __LITTLE_ENDIAN -#define UNI_CUR_DIR_NAME ".\0" -#define UNI_PAR_DIR_NAME ".\0.\0" -#else -#define UNI_CUR_DIR_NAME "\0." -#define UNI_PAR_DIR_NAME "\0.\0." -#endif - -struct date_time_t { - u16 year; - u16 month; - u16 day; - u16 hour; - u16 minute; - u16 second; - u16 millisecond; -}; - -struct vol_info_t { - u32 FatType; - u32 ClusterSize; - u32 NumClusters; - u32 FreeClusters; - u32 UsedClusters; -}; - -/* directory structure */ -struct chain_t { - u32 dir; - s32 size; - u8 flags; -}; - -struct file_id_t { - struct chain_t dir; - s32 entry; - u32 type; - u32 attr; - u32 start_clu; - u64 size; - u8 flags; - s64 rwoffset; - s32 hint_last_off; - u32 hint_last_clu; -}; - -struct dir_entry_t { - char name[MAX_NAME_LENGTH * MAX_CHARSET_SIZE]; - u32 attr; - u64 Size; - u32 num_subdirs; - struct date_time_t create_timestamp; - struct date_time_t modify_timestamp; - struct date_time_t access_timestamp; -}; - -struct timestamp_t { - u16 sec; /* 0 ~ 59 */ - u16 min; /* 0 ~ 59 */ - u16 hour; /* 0 ~ 23 */ - u16 day; /* 1 ~ 31 */ - u16 mon; /* 1 ~ 12 */ - u16 year; /* 0 ~ 127 (since 1980) */ -}; - -/* MS_DOS FAT partition boot record (512 bytes) */ -struct pbr_sector_t { - u8 jmp_boot[3]; - u8 oem_name[8]; - u8 bpb[109]; - u8 boot_code[390]; - u8 signature[2]; -}; - -/* MS-DOS FAT12/16 BIOS parameter block (51 bytes) */ -struct bpb16_t { - u8 sector_size[2]; - u8 sectors_per_clu; - u8 num_reserved[2]; - u8 num_fats; - u8 num_root_entries[2]; - u8 num_sectors[2]; - u8 media_type; - u8 num_fat_sectors[2]; - u8 sectors_in_track[2]; - u8 num_heads[2]; - u8 num_hid_sectors[4]; - u8 num_huge_sectors[4]; - - u8 phy_drv_no; - u8 reserved; - u8 ext_signature; - u8 vol_serial[4]; - u8 vol_label[11]; - u8 vol_type[8]; -}; - -/* MS-DOS FAT32 BIOS parameter block (79 bytes) */ -struct bpb32_t { - u8 sector_size[2]; - u8 sectors_per_clu; - u8 num_reserved[2]; - u8 num_fats; - u8 num_root_entries[2]; - u8 num_sectors[2]; - u8 media_type; - u8 num_fat_sectors[2]; - u8 sectors_in_track[2]; - u8 num_heads[2]; - u8 num_hid_sectors[4]; - u8 num_huge_sectors[4]; - u8 num_fat32_sectors[4]; - u8 ext_flags[2]; - u8 fs_version[2]; - u8 root_cluster[4]; - u8 fsinfo_sector[2]; - u8 backup_sector[2]; - u8 reserved[12]; - - u8 phy_drv_no; - u8 ext_reserved; - u8 ext_signature; - u8 vol_serial[4]; - u8 vol_label[11]; - u8 vol_type[8]; -}; - -/* MS-DOS EXFAT BIOS parameter block (109 bytes) */ -struct bpbex_t { - u8 reserved1[53]; - u8 vol_offset[8]; - u8 vol_length[8]; - u8 fat_offset[4]; - u8 fat_length[4]; - u8 clu_offset[4]; - u8 clu_count[4]; - u8 root_cluster[4]; - u8 vol_serial[4]; - u8 fs_version[2]; - u8 vol_flags[2]; - u8 sector_size_bits; - u8 sectors_per_clu_bits; - u8 num_fats; - u8 phy_drv_no; - u8 perc_in_use; - u8 reserved2[7]; -}; - -/* MS-DOS FAT file system information sector (512 bytes) */ -struct fsi_sector_t { - u8 signature1[4]; - u8 reserved1[480]; - u8 signature2[4]; - u8 free_cluster[4]; - u8 next_cluster[4]; - u8 reserved2[14]; - u8 signature3[2]; -}; - -/* MS-DOS FAT directory entry (32 bytes) */ -struct dentry_t { - u8 dummy[32]; -}; - -/* MS-DOS EXFAT file directory entry (32 bytes) */ -struct file_dentry_t { - u8 type; - u8 num_ext; - u8 checksum[2]; - u8 attr[2]; - u8 reserved1[2]; - u8 create_time[2]; - u8 create_date[2]; - u8 modify_time[2]; - u8 modify_date[2]; - u8 access_time[2]; - u8 access_date[2]; - u8 create_time_ms; - u8 modify_time_ms; - u8 access_time_ms; - u8 reserved2[9]; -}; - -/* MS-DOS EXFAT stream extension directory entry (32 bytes) */ -struct strm_dentry_t { - u8 type; - u8 flags; - u8 reserved1; - u8 name_len; - u8 name_hash[2]; - u8 reserved2[2]; - u8 valid_size[8]; - u8 reserved3[4]; - u8 start_clu[4]; - u8 size[8]; -}; - -/* MS-DOS EXFAT file name directory entry (32 bytes) */ -struct name_dentry_t { - u8 type; - u8 flags; - u8 unicode_0_14[30]; -}; - -/* MS-DOS EXFAT allocation bitmap directory entry (32 bytes) */ -struct bmap_dentry_t { - u8 type; - u8 flags; - u8 reserved[18]; - u8 start_clu[4]; - u8 size[8]; -}; - -/* MS-DOS EXFAT up-case table directory entry (32 bytes) */ -struct case_dentry_t { - u8 type; - u8 reserved1[3]; - u8 checksum[4]; - u8 reserved2[12]; - u8 start_clu[4]; - u8 size[8]; -}; - -/* MS-DOS EXFAT volume label directory entry (32 bytes) */ -struct volm_dentry_t { - u8 type; - u8 label_len; - u8 unicode_0_10[22]; - u8 reserved[8]; -}; - -/* unused entry hint information */ -struct uentry_t { - u32 dir; - s32 entry; - struct chain_t clu; -}; - -/* unicode name structure */ -struct uni_name_t { - u16 name[MAX_NAME_LENGTH]; - u16 name_hash; - u8 name_len; -}; - -struct buf_cache_t { - struct buf_cache_t *next; - struct buf_cache_t *prev; - struct buf_cache_t *hash_next; - struct buf_cache_t *hash_prev; - s32 drv; - sector_t sec; - bool locked; - struct buffer_head *buf_bh; -}; - -struct fs_info_t { - u32 drv; /* drive ID */ - u32 vol_id; /* volume serial number */ - - u64 num_sectors; /* num of sectors in volume */ - u32 num_clusters; /* num of clusters in volume */ - u32 cluster_size; /* cluster size in bytes */ - u32 cluster_size_bits; - u32 sectors_per_clu; /* cluster size in sectors */ - u32 sectors_per_clu_bits; - - u32 PBR_sector; /* PBR sector */ - u32 FAT1_start_sector; /* FAT1 start sector */ - u32 FAT2_start_sector; /* FAT2 start sector */ - u32 root_start_sector; /* root dir start sector */ - u32 data_start_sector; /* data area start sector */ - u32 num_FAT_sectors; /* num of FAT sectors */ - - u32 root_dir; /* root dir cluster */ - u32 dentries_in_root; /* num of dentries in root dir */ - u32 dentries_per_clu; /* num of dentries per cluster */ - - u32 vol_flag; /* volume dirty flag */ - struct buffer_head *pbr_bh; /* PBR sector */ - - u32 map_clu; /* allocation bitmap start cluster */ - u32 map_sectors; /* num of allocation bitmap sectors */ - struct buffer_head **vol_amap; /* allocation bitmap */ - - u16 **vol_utbl; /* upcase table */ - - u32 clu_srch_ptr; /* cluster search pointer */ - u32 used_clusters; /* number of used clusters */ - struct uentry_t hint_uentry; /* unused entry hint information */ - - u32 dev_ejected; /* block device operation error flag */ - - struct mutex v_mutex; - - /* FAT cache */ - struct buf_cache_t FAT_cache_array[FAT_CACHE_SIZE]; - struct buf_cache_t FAT_cache_lru_list; - struct buf_cache_t FAT_cache_hash_list[FAT_CACHE_HASH_SIZE]; - - /* buf cache */ - struct buf_cache_t buf_cache_array[BUF_CACHE_SIZE]; - struct buf_cache_t buf_cache_lru_list; - struct buf_cache_t buf_cache_hash_list[BUF_CACHE_HASH_SIZE]; -}; - -#define ES_2_ENTRIES 2 -#define ES_3_ENTRIES 3 -#define ES_ALL_ENTRIES 0 - -struct entry_set_cache_t { - /* sector number that contains file_entry */ - sector_t sector; - - /* byte offset in the sector */ - s32 offset; - - /* - * flag in stream entry. - * 01 for cluster chain, - * 03 for contig. clusteres. - */ - s32 alloc_flag; - - u32 num_entries; - - /* __buf should be the last member */ - void *__buf; -}; - -#define EXFAT_ERRORS_CONT 1 /* ignore error and continue */ -#define EXFAT_ERRORS_PANIC 2 /* panic on error */ -#define EXFAT_ERRORS_RO 3 /* remount r/o on error */ - -/* ioctl command */ -#define EXFAT_IOCTL_GET_VOLUME_ID _IOR('r', 0x12, __u32) - -struct exfat_mount_options { - kuid_t fs_uid; - kgid_t fs_gid; - unsigned short fs_fmask; - unsigned short fs_dmask; - - /* permission for setting the [am]time */ - unsigned short allow_utime; - - /* codepage for shortname conversions */ - unsigned short codepage; - - /* charset for filename input/display */ - char *iocharset; - - unsigned char casesensitive; - - /* on error: continue, panic, remount-ro */ - unsigned char errors; -#ifdef CONFIG_STAGING_EXFAT_DISCARD - /* flag on if -o dicard specified and device support discard() */ - unsigned char discard; -#endif /* CONFIG_STAGING_EXFAT_DISCARD */ -}; - -#define EXFAT_HASH_BITS 8 -#define EXFAT_HASH_SIZE BIT(EXFAT_HASH_BITS) - -/* - * EXFAT file system in-core superblock data - */ -struct bd_info_t { - s32 sector_size; /* in bytes */ - s32 sector_size_bits; - s32 sector_size_mask; - - /* total number of sectors in this block device */ - s32 num_sectors; - - /* opened or not */ - bool opened; -}; - -struct exfat_sb_info { - struct fs_info_t fs_info; - struct bd_info_t bd_info; - - struct exfat_mount_options options; - - int s_dirt; - struct mutex s_lock; - struct nls_table *nls_disk; /* Codepage used on disk */ - struct nls_table *nls_io; /* Charset used for input and display */ - - struct inode *fat_inode; - - spinlock_t inode_hash_lock; - struct hlist_head inode_hashtable[EXFAT_HASH_SIZE]; -#ifdef CONFIG_STAGING_EXFAT_KERNEL_DEBUG - long debug_flags; -#endif /* CONFIG_STAGING_EXFAT_KERNEL_DEBUG */ -}; - -/* - * EXFAT file system inode data in memory - */ -struct exfat_inode_info { - struct file_id_t fid; - char *target; - /* NOTE: mmu_private is 64bits, so must hold ->i_mutex to access */ - loff_t mmu_private; /* physically allocated size */ - loff_t i_pos; /* on-disk position of directory entry or 0 */ - struct hlist_node i_hash_fat; /* hash by i_location */ - struct rw_semaphore truncate_lock; - struct inode vfs_inode; - struct rw_semaphore i_alloc_sem; /* protect bmap against truncate */ -}; - -#define EXFAT_SB(sb) ((struct exfat_sb_info *)((sb)->s_fs_info)) - -static inline struct exfat_inode_info *EXFAT_I(struct inode *inode) -{ - return container_of(inode, struct exfat_inode_info, vfs_inode); -} - -/* NLS management function */ -u16 nls_upper(struct super_block *sb, u16 a); -int nls_uniname_cmp(struct super_block *sb, u16 *a, u16 *b); -void nls_uniname_to_cstring(struct super_block *sb, u8 *p_cstring, - struct uni_name_t *p_uniname); -void nls_cstring_to_uniname(struct super_block *sb, - struct uni_name_t *p_uniname, u8 *p_cstring, - bool *p_lossy); - -/* buffer cache management */ -void exfat_buf_init(struct super_block *sb); -void exfat_buf_shutdown(struct super_block *sb); -int exfat_fat_read(struct super_block *sb, u32 loc, u32 *content); -s32 exfat_fat_write(struct super_block *sb, u32 loc, u32 content); -u8 *exfat_fat_getblk(struct super_block *sb, sector_t sec); -void exfat_fat_modify(struct super_block *sb, sector_t sec); -void exfat_fat_release_all(struct super_block *sb); -u8 *exfat_buf_getblk(struct super_block *sb, sector_t sec); -void exfat_buf_modify(struct super_block *sb, sector_t sec); -void exfat_buf_lock(struct super_block *sb, sector_t sec); -void exfat_buf_unlock(struct super_block *sb, sector_t sec); -void exfat_buf_release(struct super_block *sb, sector_t sec); -void exfat_buf_release_all(struct super_block *sb); - -/* fs management functions */ -void fs_set_vol_flags(struct super_block *sb, u32 new_flag); -void fs_error(struct super_block *sb); - -/* cluster management functions */ -s32 count_num_clusters(struct super_block *sb, struct chain_t *dir); -void exfat_chain_cont_cluster(struct super_block *sb, u32 chain, s32 len); - -/* allocation bitmap management functions */ -s32 load_alloc_bitmap(struct super_block *sb); -void free_alloc_bitmap(struct super_block *sb); - -/* upcase table management functions */ -s32 load_upcase_table(struct super_block *sb); -void free_upcase_table(struct super_block *sb); - -/* dir entry management functions */ -struct timestamp_t *tm_current(struct timestamp_t *tm); - -struct dentry_t *get_entry_in_dir(struct super_block *sb, struct chain_t *p_dir, - s32 entry, sector_t *sector); -struct entry_set_cache_t *get_entry_set_in_dir(struct super_block *sb, - struct chain_t *p_dir, s32 entry, - u32 type, - struct dentry_t **file_ep); -void release_entry_set(struct entry_set_cache_t *es); -s32 count_dir_entries(struct super_block *sb, struct chain_t *p_dir); -void update_dir_checksum(struct super_block *sb, struct chain_t *p_dir, - s32 entry); -void update_dir_checksum_with_entry_set(struct super_block *sb, - struct entry_set_cache_t *es); -bool is_dir_empty(struct super_block *sb, struct chain_t *p_dir); - -/* name conversion functions */ -s32 get_num_entries(struct super_block *sb, struct chain_t *p_dir, - struct uni_name_t *p_uniname, s32 *entries); -u16 calc_checksum_2byte(void *data, s32 len, u16 chksum, s32 type); - -/* name resolution functions */ -s32 resolve_path(struct inode *inode, char *path, struct chain_t *p_dir, - struct uni_name_t *p_uniname); - -/* file operation functions */ -s32 exfat_mount(struct super_block *sb, struct pbr_sector_t *p_pbr); -s32 create_dir(struct inode *inode, struct chain_t *p_dir, - struct uni_name_t *p_uniname, struct file_id_t *fid); -s32 create_file(struct inode *inode, struct chain_t *p_dir, - struct uni_name_t *p_uniname, struct file_id_t *fid); -void remove_file(struct inode *inode, struct chain_t *p_dir, s32 entry); -s32 exfat_rename_file(struct inode *inode, struct chain_t *p_dir, s32 old_entry, - struct uni_name_t *p_uniname, struct file_id_t *fid); -s32 move_file(struct inode *inode, struct chain_t *p_olddir, s32 oldentry, - struct chain_t *p_newdir, struct uni_name_t *p_uniname, - struct file_id_t *fid); - -/* sector read/write functions */ -int sector_read(struct super_block *sb, sector_t sec, - struct buffer_head **bh, bool read); -int sector_write(struct super_block *sb, sector_t sec, - struct buffer_head *bh, bool sync); -int multi_sector_read(struct super_block *sb, sector_t sec, - struct buffer_head **bh, s32 num_secs, bool read); -int multi_sector_write(struct super_block *sb, sector_t sec, - struct buffer_head *bh, s32 num_secs, bool sync); - -void exfat_bdev_open(struct super_block *sb); -void exfat_bdev_close(struct super_block *sb); -int exfat_bdev_read(struct super_block *sb, sector_t secno, - struct buffer_head **bh, u32 num_secs, bool read); -int exfat_bdev_write(struct super_block *sb, sector_t secno, - struct buffer_head *bh, u32 num_secs, bool sync); -int exfat_bdev_sync(struct super_block *sb); - -/* cluster operation functions */ -s32 exfat_alloc_cluster(struct super_block *sb, s32 num_alloc, - struct chain_t *p_chain); -void exfat_free_cluster(struct super_block *sb, struct chain_t *p_chain, - s32 do_relse); -s32 exfat_count_used_clusters(struct super_block *sb); - -/* dir operation functions */ -s32 exfat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir, - struct uni_name_t *p_uniname, s32 num_entries, - u32 type); -void exfat_delete_dir_entry(struct super_block *sb, struct chain_t *p_dir, - s32 entry, s32 order, s32 num_entries); -void exfat_get_uni_name_from_ext_entry(struct super_block *sb, - struct chain_t *p_dir, s32 entry, - u16 *uniname); -s32 exfat_count_ext_entries(struct super_block *sb, struct chain_t *p_dir, - s32 entry, struct dentry_t *p_entry); -s32 exfat_calc_num_entries(struct uni_name_t *p_uniname); - -/* dir entry getter/setter */ -u32 exfat_get_entry_type(struct dentry_t *p_entry); -u32 exfat_get_entry_attr(struct dentry_t *p_entry); -void exfat_set_entry_attr(struct dentry_t *p_entry, u32 attr); -u8 exfat_get_entry_flag(struct dentry_t *p_entry); -void exfat_set_entry_flag(struct dentry_t *p_entry, u8 flags); -u32 exfat_get_entry_clu0(struct dentry_t *p_entry); -void exfat_set_entry_clu0(struct dentry_t *p_entry, u32 start_clu); -u64 exfat_get_entry_size(struct dentry_t *p_entry); -void exfat_set_entry_size(struct dentry_t *p_entry, u64 size); -void exfat_get_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp, - u8 mode); -void exfat_set_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp, - u8 mode); - -extern const u8 uni_upcase[]; -#endif /* _EXFAT_H */ diff --git a/drivers/staging/exfat/exfat_blkdev.c b/drivers/staging/exfat/exfat_blkdev.c deleted file mode 100644 index ddff019f2803..000000000000 --- a/drivers/staging/exfat/exfat_blkdev.c +++ /dev/null @@ -1,138 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. - */ - -#include -#include -#include -#include "exfat.h" - -void exfat_bdev_open(struct super_block *sb) -{ - struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); - - if (p_bd->opened) - return; - - p_bd->sector_size = bdev_logical_block_size(sb->s_bdev); - p_bd->sector_size_bits = ilog2(p_bd->sector_size); - p_bd->sector_size_mask = p_bd->sector_size - 1; - p_bd->num_sectors = i_size_read(sb->s_bdev->bd_inode) >> - p_bd->sector_size_bits; - p_bd->opened = true; -} - -void exfat_bdev_close(struct super_block *sb) -{ - struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); - - p_bd->opened = false; -} - -int exfat_bdev_read(struct super_block *sb, sector_t secno, - struct buffer_head **bh, u32 num_secs, - bool read) -{ - struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); -#ifdef CONFIG_STAGING_EXFAT_KERNEL_DEBUG - struct exfat_sb_info *sbi = EXFAT_SB(sb); - long flags = sbi->debug_flags; - - if (flags & EXFAT_DEBUGFLAGS_ERROR_RW) - return -EIO; -#endif /* CONFIG_STAGING_EXFAT_KERNEL_DEBUG */ - - if (!p_bd->opened) - return -ENODEV; - - if (*bh) - __brelse(*bh); - - if (read) - *bh = __bread(sb->s_bdev, secno, - num_secs << p_bd->sector_size_bits); - else - *bh = __getblk(sb->s_bdev, secno, - num_secs << p_bd->sector_size_bits); - - if (*bh) - return 0; - - WARN(!p_fs->dev_ejected, - "[EXFAT] No bh, device seems wrong or to be ejected.\n"); - - return -EIO; -} - -int exfat_bdev_write(struct super_block *sb, sector_t secno, - struct buffer_head *bh, - u32 num_secs, bool sync) -{ - s32 count; - struct buffer_head *bh2; - struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); -#ifdef CONFIG_STAGING_EXFAT_KERNEL_DEBUG - struct exfat_sb_info *sbi = EXFAT_SB(sb); - long flags = sbi->debug_flags; - - if (flags & EXFAT_DEBUGFLAGS_ERROR_RW) - return -EIO; -#endif /* CONFIG_STAGING_EXFAT_KERNEL_DEBUG */ - - if (!p_bd->opened) - return -ENODEV; - - if (secno == bh->b_blocknr) { - lock_buffer(bh); - set_buffer_uptodate(bh); - mark_buffer_dirty(bh); - unlock_buffer(bh); - if (sync && (sync_dirty_buffer(bh) != 0)) - return -EIO; - } else { - count = num_secs << p_bd->sector_size_bits; - - bh2 = __getblk(sb->s_bdev, secno, count); - if (!bh2) - goto no_bh; - - lock_buffer(bh2); - memcpy(bh2->b_data, bh->b_data, count); - set_buffer_uptodate(bh2); - mark_buffer_dirty(bh2); - unlock_buffer(bh2); - if (sync && (sync_dirty_buffer(bh2) != 0)) { - __brelse(bh2); - goto no_bh; - } - __brelse(bh2); - } - - return 0; - -no_bh: - WARN(!p_fs->dev_ejected, - "[EXFAT] No bh, device seems wrong or to be ejected.\n"); - - return -EIO; -} - -int exfat_bdev_sync(struct super_block *sb) -{ - struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); -#ifdef CONFIG_STAGING_EXFAT_KERNEL_DEBUG - struct exfat_sb_info *sbi = EXFAT_SB(sb); - long flags = sbi->debug_flags; - - if (flags & EXFAT_DEBUGFLAGS_ERROR_RW) - return -EIO; -#endif /* CONFIG_STAGING_EXFAT_KERNEL_DEBUG */ - - if (!p_bd->opened) - return -ENODEV; - - return sync_blockdev(sb->s_bdev); -} diff --git a/drivers/staging/exfat/exfat_cache.c b/drivers/staging/exfat/exfat_cache.c deleted file mode 100644 index b15203d4e0ae..000000000000 --- a/drivers/staging/exfat/exfat_cache.c +++ /dev/null @@ -1,514 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. - */ - -#include -#include -#include -#include "exfat.h" - -/* Local variables */ -static DEFINE_MUTEX(f_mutex); -static DEFINE_MUTEX(b_mutex); - -static struct buf_cache_t *FAT_cache_find(struct super_block *sb, sector_t sec) -{ - s32 off; - struct buf_cache_t *bp, *hp; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - - off = (sec + - (sec >> p_fs->sectors_per_clu_bits)) & (FAT_CACHE_HASH_SIZE - 1); - - hp = &p_fs->FAT_cache_hash_list[off]; - for (bp = hp->hash_next; bp != hp; bp = bp->hash_next) { - if ((bp->drv == p_fs->drv) && (bp->sec == sec)) { - WARN(!bp->buf_bh, - "[EXFAT] FAT_cache has no bh. It will make system panic.\n"); - - touch_buffer(bp->buf_bh); - return bp; - } - } - return NULL; -} - -static void push_to_mru(struct buf_cache_t *bp, struct buf_cache_t *list) -{ - bp->next = list->next; - bp->prev = list; - list->next->prev = bp; - list->next = bp; -} - -static void push_to_lru(struct buf_cache_t *bp, struct buf_cache_t *list) -{ - bp->prev = list->prev; - bp->next = list; - list->prev->next = bp; - list->prev = bp; -} - -static void move_to_mru(struct buf_cache_t *bp, struct buf_cache_t *list) -{ - bp->prev->next = bp->next; - bp->next->prev = bp->prev; - push_to_mru(bp, list); -} - -static void move_to_lru(struct buf_cache_t *bp, struct buf_cache_t *list) -{ - bp->prev->next = bp->next; - bp->next->prev = bp->prev; - push_to_lru(bp, list); -} - -static struct buf_cache_t *FAT_cache_get(struct super_block *sb, sector_t sec) -{ - struct buf_cache_t *bp; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - - bp = p_fs->FAT_cache_lru_list.prev; - - move_to_mru(bp, &p_fs->FAT_cache_lru_list); - return bp; -} - -static void FAT_cache_insert_hash(struct super_block *sb, - struct buf_cache_t *bp) -{ - s32 off; - struct buf_cache_t *hp; - struct fs_info_t *p_fs; - - p_fs = &(EXFAT_SB(sb)->fs_info); - off = (bp->sec + - (bp->sec >> p_fs->sectors_per_clu_bits)) & - (FAT_CACHE_HASH_SIZE - 1); - - hp = &p_fs->FAT_cache_hash_list[off]; - bp->hash_next = hp->hash_next; - bp->hash_prev = hp; - hp->hash_next->hash_prev = bp; - hp->hash_next = bp; -} - -static void FAT_cache_remove_hash(struct buf_cache_t *bp) -{ - (bp->hash_prev)->hash_next = bp->hash_next; - (bp->hash_next)->hash_prev = bp->hash_prev; -} - -static void buf_cache_insert_hash(struct super_block *sb, - struct buf_cache_t *bp) -{ - s32 off; - struct buf_cache_t *hp; - struct fs_info_t *p_fs; - - p_fs = &(EXFAT_SB(sb)->fs_info); - off = (bp->sec + - (bp->sec >> p_fs->sectors_per_clu_bits)) & - (BUF_CACHE_HASH_SIZE - 1); - - hp = &p_fs->buf_cache_hash_list[off]; - bp->hash_next = hp->hash_next; - bp->hash_prev = hp; - hp->hash_next->hash_prev = bp; - hp->hash_next = bp; -} - -static void buf_cache_remove_hash(struct buf_cache_t *bp) -{ - (bp->hash_prev)->hash_next = bp->hash_next; - (bp->hash_next)->hash_prev = bp->hash_prev; -} - -void exfat_buf_init(struct super_block *sb) -{ - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - - int i; - - /* LRU list */ - p_fs->FAT_cache_lru_list.next = &p_fs->FAT_cache_lru_list; - p_fs->FAT_cache_lru_list.prev = &p_fs->FAT_cache_lru_list; - - for (i = 0; i < FAT_CACHE_SIZE; i++) { - p_fs->FAT_cache_array[i].drv = -1; - p_fs->FAT_cache_array[i].sec = ~0; - p_fs->FAT_cache_array[i].locked = false; - p_fs->FAT_cache_array[i].buf_bh = NULL; - p_fs->FAT_cache_array[i].prev = NULL; - p_fs->FAT_cache_array[i].next = NULL; - push_to_mru(&p_fs->FAT_cache_array[i], - &p_fs->FAT_cache_lru_list); - } - - p_fs->buf_cache_lru_list.next = &p_fs->buf_cache_lru_list; - p_fs->buf_cache_lru_list.prev = &p_fs->buf_cache_lru_list; - - for (i = 0; i < BUF_CACHE_SIZE; i++) { - p_fs->buf_cache_array[i].drv = -1; - p_fs->buf_cache_array[i].sec = ~0; - p_fs->buf_cache_array[i].locked = false; - p_fs->buf_cache_array[i].buf_bh = NULL; - p_fs->buf_cache_array[i].prev = NULL; - p_fs->buf_cache_array[i].next = NULL; - push_to_mru(&p_fs->buf_cache_array[i], - &p_fs->buf_cache_lru_list); - } - - /* HASH list */ - for (i = 0; i < FAT_CACHE_HASH_SIZE; i++) { - p_fs->FAT_cache_hash_list[i].drv = -1; - p_fs->FAT_cache_hash_list[i].sec = ~0; - p_fs->FAT_cache_hash_list[i].hash_next = - &p_fs->FAT_cache_hash_list[i]; - p_fs->FAT_cache_hash_list[i].hash_prev = - &p_fs->FAT_cache_hash_list[i]; - } - - for (i = 0; i < FAT_CACHE_SIZE; i++) - FAT_cache_insert_hash(sb, &p_fs->FAT_cache_array[i]); - - for (i = 0; i < BUF_CACHE_HASH_SIZE; i++) { - p_fs->buf_cache_hash_list[i].drv = -1; - p_fs->buf_cache_hash_list[i].sec = ~0; - p_fs->buf_cache_hash_list[i].hash_next = - &p_fs->buf_cache_hash_list[i]; - p_fs->buf_cache_hash_list[i].hash_prev = - &p_fs->buf_cache_hash_list[i]; - } - - for (i = 0; i < BUF_CACHE_SIZE; i++) - buf_cache_insert_hash(sb, &p_fs->buf_cache_array[i]); -} - -void exfat_buf_shutdown(struct super_block *sb) -{ -} - -static int __exfat_fat_read(struct super_block *sb, u32 loc, u32 *content) -{ - s32 off; - u32 _content; - sector_t sec; - u8 *fat_sector, *fat_entry; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); - - sec = p_fs->FAT1_start_sector + - (loc >> (p_bd->sector_size_bits - 2)); - off = (loc << 2) & p_bd->sector_size_mask; - - fat_sector = exfat_fat_getblk(sb, sec); - if (!fat_sector) - return -1; - - fat_entry = &fat_sector[off]; - _content = GET32_A(fat_entry); - - if (_content >= CLUSTER_32(0xFFFFFFF8)) { - *content = CLUSTER_32(~0); - return 0; - } - *content = CLUSTER_32(_content); - return 0; -} - -/* in : sb, loc - * out: content - * returns 0 on success - * -1 on error - */ -int exfat_fat_read(struct super_block *sb, u32 loc, u32 *content) -{ - s32 ret; - - mutex_lock(&f_mutex); - ret = __exfat_fat_read(sb, loc, content); - mutex_unlock(&f_mutex); - - return ret; -} - -static s32 __exfat_fat_write(struct super_block *sb, u32 loc, u32 content) -{ - s32 off; - sector_t sec; - u8 *fat_sector, *fat_entry; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); - - sec = p_fs->FAT1_start_sector + (loc >> - (p_bd->sector_size_bits - 2)); - off = (loc << 2) & p_bd->sector_size_mask; - - fat_sector = exfat_fat_getblk(sb, sec); - if (!fat_sector) - return -1; - - fat_entry = &fat_sector[off]; - - SET32_A(fat_entry, content); - - exfat_fat_modify(sb, sec); - return 0; -} - -int exfat_fat_write(struct super_block *sb, u32 loc, u32 content) -{ - s32 ret; - - mutex_lock(&f_mutex); - ret = __exfat_fat_write(sb, loc, content); - mutex_unlock(&f_mutex); - - return ret; -} - -u8 *exfat_fat_getblk(struct super_block *sb, sector_t sec) -{ - struct buf_cache_t *bp; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - - bp = FAT_cache_find(sb, sec); - if (bp) { - move_to_mru(bp, &p_fs->FAT_cache_lru_list); - return bp->buf_bh->b_data; - } - - bp = FAT_cache_get(sb, sec); - - FAT_cache_remove_hash(bp); - - bp->drv = p_fs->drv; - bp->sec = sec; - bp->locked = false; - - FAT_cache_insert_hash(sb, bp); - - if (sector_read(sb, sec, &bp->buf_bh, 1) != 0) { - FAT_cache_remove_hash(bp); - bp->drv = -1; - bp->sec = ~0; - bp->locked = false; - bp->buf_bh = NULL; - - move_to_lru(bp, &p_fs->FAT_cache_lru_list); - return NULL; - } - - return bp->buf_bh->b_data; -} - -void exfat_fat_modify(struct super_block *sb, sector_t sec) -{ - struct buf_cache_t *bp; - - bp = FAT_cache_find(sb, sec); - if (bp) - sector_write(sb, sec, bp->buf_bh, 0); -} - -void exfat_fat_release_all(struct super_block *sb) -{ - struct buf_cache_t *bp; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - - mutex_lock(&f_mutex); - - bp = p_fs->FAT_cache_lru_list.next; - while (bp != &p_fs->FAT_cache_lru_list) { - if (bp->drv == p_fs->drv) { - bp->drv = -1; - bp->sec = ~0; - bp->locked = false; - - if (bp->buf_bh) { - __brelse(bp->buf_bh); - bp->buf_bh = NULL; - } - } - bp = bp->next; - } - - mutex_unlock(&f_mutex); -} - -static struct buf_cache_t *buf_cache_find(struct super_block *sb, sector_t sec) -{ - s32 off; - struct buf_cache_t *bp, *hp; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - - off = (sec + (sec >> p_fs->sectors_per_clu_bits)) & - (BUF_CACHE_HASH_SIZE - 1); - - hp = &p_fs->buf_cache_hash_list[off]; - for (bp = hp->hash_next; bp != hp; bp = bp->hash_next) { - if ((bp->drv == p_fs->drv) && (bp->sec == sec)) { - touch_buffer(bp->buf_bh); - return bp; - } - } - return NULL; -} - -static struct buf_cache_t *buf_cache_get(struct super_block *sb, sector_t sec) -{ - struct buf_cache_t *bp; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - - bp = p_fs->buf_cache_lru_list.prev; - while (bp->locked) - bp = bp->prev; - - move_to_mru(bp, &p_fs->buf_cache_lru_list); - return bp; -} - -static u8 *__exfat_buf_getblk(struct super_block *sb, sector_t sec) -{ - struct buf_cache_t *bp; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - - bp = buf_cache_find(sb, sec); - if (bp) { - move_to_mru(bp, &p_fs->buf_cache_lru_list); - return bp->buf_bh->b_data; - } - - bp = buf_cache_get(sb, sec); - - buf_cache_remove_hash(bp); - - bp->drv = p_fs->drv; - bp->sec = sec; - bp->locked = false; - - buf_cache_insert_hash(sb, bp); - - if (sector_read(sb, sec, &bp->buf_bh, 1) != 0) { - buf_cache_remove_hash(bp); - bp->drv = -1; - bp->sec = ~0; - bp->locked = false; - bp->buf_bh = NULL; - - move_to_lru(bp, &p_fs->buf_cache_lru_list); - return NULL; - } - - return bp->buf_bh->b_data; -} - -u8 *exfat_buf_getblk(struct super_block *sb, sector_t sec) -{ - u8 *buf; - - mutex_lock(&b_mutex); - buf = __exfat_buf_getblk(sb, sec); - mutex_unlock(&b_mutex); - - return buf; -} - -void exfat_buf_modify(struct super_block *sb, sector_t sec) -{ - struct buf_cache_t *bp; - - mutex_lock(&b_mutex); - - bp = buf_cache_find(sb, sec); - if (likely(bp)) - sector_write(sb, sec, bp->buf_bh, 0); - - WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%llu).\n", - (unsigned long long)sec); - - mutex_unlock(&b_mutex); -} - -void exfat_buf_lock(struct super_block *sb, sector_t sec) -{ - struct buf_cache_t *bp; - - mutex_lock(&b_mutex); - - bp = buf_cache_find(sb, sec); - if (likely(bp)) - bp->locked = true; - - WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%llu).\n", - (unsigned long long)sec); - - mutex_unlock(&b_mutex); -} - -void exfat_buf_unlock(struct super_block *sb, sector_t sec) -{ - struct buf_cache_t *bp; - - mutex_lock(&b_mutex); - - bp = buf_cache_find(sb, sec); - if (likely(bp)) - bp->locked = false; - - WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%llu).\n", - (unsigned long long)sec); - - mutex_unlock(&b_mutex); -} - -void exfat_buf_release(struct super_block *sb, sector_t sec) -{ - struct buf_cache_t *bp; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - - mutex_lock(&b_mutex); - - bp = buf_cache_find(sb, sec); - if (likely(bp)) { - bp->drv = -1; - bp->sec = ~0; - bp->locked = false; - - if (bp->buf_bh) { - __brelse(bp->buf_bh); - bp->buf_bh = NULL; - } - - move_to_lru(bp, &p_fs->buf_cache_lru_list); - } - - mutex_unlock(&b_mutex); -} - -void exfat_buf_release_all(struct super_block *sb) -{ - struct buf_cache_t *bp; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - - mutex_lock(&b_mutex); - - bp = p_fs->buf_cache_lru_list.next; - while (bp != &p_fs->buf_cache_lru_list) { - if (bp->drv == p_fs->drv) { - bp->drv = -1; - bp->sec = ~0; - bp->locked = false; - - if (bp->buf_bh) { - __brelse(bp->buf_bh); - bp->buf_bh = NULL; - } - } - bp = bp->next; - } - - mutex_unlock(&b_mutex); -} diff --git a/drivers/staging/exfat/exfat_core.c b/drivers/staging/exfat/exfat_core.c deleted file mode 100644 index 374a4fe183f5..000000000000 --- a/drivers/staging/exfat/exfat_core.c +++ /dev/null @@ -1,2529 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. - */ - -#include -#include -#include -#include -#include -#include -#include "exfat.h" - -static void __set_sb_dirty(struct super_block *sb) -{ - struct exfat_sb_info *sbi = EXFAT_SB(sb); - - sbi->s_dirt = 1; -} - -static u8 name_buf[MAX_PATH_LENGTH * MAX_CHARSET_SIZE]; - -static u8 free_bit[] = { - 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, /* 0 ~ 19 */ - 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, /* 20 ~ 39 */ - 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, /* 40 ~ 59 */ - 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, /* 60 ~ 79 */ - 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, /* 80 ~ 99 */ - 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, /* 100 ~ 119 */ - 0, 1, 0, 2, 0, 1, 0, 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, /* 120 ~ 139 */ - 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, /* 140 ~ 159 */ - 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, /* 160 ~ 179 */ - 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, /* 180 ~ 199 */ - 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, /* 200 ~ 219 */ - 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, /* 220 ~ 239 */ - 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 /* 240 ~ 254 */ -}; - -static u8 used_bit[] = { - 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, /* 0 ~ 19 */ - 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, /* 20 ~ 39 */ - 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, /* 40 ~ 59 */ - 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, /* 60 ~ 79 */ - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, /* 80 ~ 99 */ - 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, /* 100 ~ 119 */ - 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, /* 120 ~ 139 */ - 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, /* 140 ~ 159 */ - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, /* 160 ~ 179 */ - 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, /* 180 ~ 199 */ - 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, /* 200 ~ 219 */ - 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, /* 220 ~ 239 */ - 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 /* 240 ~ 255 */ -}; - -#define BITMAP_LOC(v) ((v) >> 3) -#define BITMAP_SHIFT(v) ((v) & 0x07) - -static inline s32 exfat_bitmap_test(u8 *bitmap, int i) -{ - u8 data; - - data = bitmap[BITMAP_LOC(i)]; - if ((data >> BITMAP_SHIFT(i)) & 0x01) - return 1; - return 0; -} - -static inline void exfat_bitmap_set(u8 *bitmap, int i) -{ - bitmap[BITMAP_LOC(i)] |= (0x01 << BITMAP_SHIFT(i)); -} - -static inline void exfat_bitmap_clear(u8 *bitmap, int i) -{ - bitmap[BITMAP_LOC(i)] &= ~(0x01 << BITMAP_SHIFT(i)); -} - -/* - * File System Management Functions - */ - -void fs_set_vol_flags(struct super_block *sb, u32 new_flag) -{ - struct pbr_sector_t *p_pbr; - struct bpbex_t *p_bpb; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - - if (p_fs->vol_flag == new_flag) - return; - - p_fs->vol_flag = new_flag; - - if (!p_fs->pbr_bh) { - if (sector_read(sb, p_fs->PBR_sector, - &p_fs->pbr_bh, 1) != 0) - return; - } - - p_pbr = (struct pbr_sector_t *)p_fs->pbr_bh->b_data; - p_bpb = (struct bpbex_t *)p_pbr->bpb; - SET16(p_bpb->vol_flags, (u16)new_flag); - - /* XXX duyoung - * what can we do here? (cuz fs_set_vol_flags() is void) - */ - if ((new_flag == VOL_DIRTY) && (!buffer_dirty(p_fs->pbr_bh))) - sector_write(sb, p_fs->PBR_sector, p_fs->pbr_bh, 1); - else - sector_write(sb, p_fs->PBR_sector, p_fs->pbr_bh, 0); -} - -void fs_error(struct super_block *sb) -{ - struct exfat_mount_options *opts = &EXFAT_SB(sb)->options; - - if (opts->errors == EXFAT_ERRORS_PANIC) { - panic("[EXFAT] Filesystem panic from previous error\n"); - } else if ((opts->errors == EXFAT_ERRORS_RO) && !sb_rdonly(sb)) { - sb->s_flags |= SB_RDONLY; - pr_err("[EXFAT] Filesystem has been set read-only\n"); - } -} - -/* - * Cluster Management Functions - */ - -static s32 clear_cluster(struct super_block *sb, u32 clu) -{ - sector_t s, n; - s32 ret = 0; - struct buffer_head *tmp_bh = NULL; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); - - if (clu == CLUSTER_32(0)) { /* FAT16 root_dir */ - s = p_fs->root_start_sector; - n = p_fs->data_start_sector; - } else { - s = START_SECTOR(clu); - n = s + p_fs->sectors_per_clu; - } - - for (; s < n; s++) { - ret = sector_read(sb, s, &tmp_bh, 0); - if (ret != 0) - return ret; - - memset((char *)tmp_bh->b_data, 0x0, p_bd->sector_size); - ret = sector_write(sb, s, tmp_bh, 0); - if (ret != 0) - break; - } - - brelse(tmp_bh); - return ret; -} - -static s32 set_alloc_bitmap(struct super_block *sb, u32 clu) -{ - int i, b; - sector_t sector; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); - - i = clu >> (p_bd->sector_size_bits + 3); - b = clu & ((p_bd->sector_size << 3) - 1); - - sector = START_SECTOR(p_fs->map_clu) + i; - - exfat_bitmap_set((u8 *)p_fs->vol_amap[i]->b_data, b); - - return sector_write(sb, sector, p_fs->vol_amap[i], 0); -} - -static s32 clr_alloc_bitmap(struct super_block *sb, u32 clu) -{ - int i, b; - sector_t sector; -#ifdef CONFIG_STAGING_EXFAT_DISCARD - struct exfat_sb_info *sbi = EXFAT_SB(sb); - struct exfat_mount_options *opts = &sbi->options; - int ret; -#endif /* CONFIG_STAGING_EXFAT_DISCARD */ - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); - - i = clu >> (p_bd->sector_size_bits + 3); - b = clu & ((p_bd->sector_size << 3) - 1); - - sector = START_SECTOR(p_fs->map_clu) + i; - - exfat_bitmap_clear((u8 *)p_fs->vol_amap[i]->b_data, b); - -#ifdef CONFIG_STAGING_EXFAT_DISCARD - if (opts->discard) { - ret = sb_issue_discard(sb, START_SECTOR(clu), - (1 << p_fs->sectors_per_clu_bits), - GFP_NOFS, 0); - if (ret == -EOPNOTSUPP) { - pr_warn("discard not supported by device, disabling"); - opts->discard = 0; - } else { - return ret; - } - } -#endif /* CONFIG_STAGING_EXFAT_DISCARD */ - - return sector_write(sb, sector, p_fs->vol_amap[i], 0); -} - -static u32 test_alloc_bitmap(struct super_block *sb, u32 clu) -{ - int i, map_i, map_b; - u32 clu_base, clu_free; - u8 k, clu_mask; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); - - clu_base = (clu & ~(0x7)) + 2; - clu_mask = (1 << (clu - clu_base + 2)) - 1; - - map_i = clu >> (p_bd->sector_size_bits + 3); - map_b = (clu >> 3) & p_bd->sector_size_mask; - - for (i = 2; i < p_fs->num_clusters; i += 8) { - k = *(((u8 *)p_fs->vol_amap[map_i]->b_data) + map_b); - if (clu_mask > 0) { - k |= clu_mask; - clu_mask = 0; - } - if (k < 0xFF) { - clu_free = clu_base + free_bit[k]; - if (clu_free < p_fs->num_clusters) - return clu_free; - } - clu_base += 8; - - if (((++map_b) >= p_bd->sector_size) || - (clu_base >= p_fs->num_clusters)) { - if ((++map_i) >= p_fs->map_sectors) { - clu_base = 2; - map_i = 0; - } - map_b = 0; - } - } - - return CLUSTER_32(~0); -} - -s32 exfat_alloc_cluster(struct super_block *sb, s32 num_alloc, - struct chain_t *p_chain) -{ - s32 num_clusters = 0; - u32 hint_clu, new_clu, last_clu = CLUSTER_32(~0); - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - - hint_clu = p_chain->dir; - if (hint_clu == CLUSTER_32(~0)) { - hint_clu = test_alloc_bitmap(sb, p_fs->clu_srch_ptr - 2); - if (hint_clu == CLUSTER_32(~0)) - return 0; - } else if (hint_clu >= p_fs->num_clusters) { - hint_clu = 2; - p_chain->flags = 0x01; - } - - __set_sb_dirty(sb); - - p_chain->dir = CLUSTER_32(~0); - - while ((new_clu = test_alloc_bitmap(sb, hint_clu - 2)) != CLUSTER_32(~0)) { - if (new_clu != hint_clu) { - if (p_chain->flags == 0x03) { - exfat_chain_cont_cluster(sb, p_chain->dir, - num_clusters); - p_chain->flags = 0x01; - } - } - - if (set_alloc_bitmap(sb, new_clu - 2) != 0) - return -EIO; - - num_clusters++; - - if (p_chain->flags == 0x01) { - if (exfat_fat_write(sb, new_clu, CLUSTER_32(~0)) < 0) - return -EIO; - } - - if (p_chain->dir == CLUSTER_32(~0)) { - p_chain->dir = new_clu; - } else { - if (p_chain->flags == 0x01) { - if (exfat_fat_write(sb, last_clu, new_clu) < 0) - return -EIO; - } - } - last_clu = new_clu; - - if ((--num_alloc) == 0) { - p_fs->clu_srch_ptr = hint_clu; - if (p_fs->used_clusters != UINT_MAX) - p_fs->used_clusters += num_clusters; - - p_chain->size += num_clusters; - return num_clusters; - } - - hint_clu = new_clu + 1; - if (hint_clu >= p_fs->num_clusters) { - hint_clu = 2; - - if (p_chain->flags == 0x03) { - exfat_chain_cont_cluster(sb, p_chain->dir, - num_clusters); - p_chain->flags = 0x01; - } - } - } - - p_fs->clu_srch_ptr = hint_clu; - if (p_fs->used_clusters != UINT_MAX) - p_fs->used_clusters += num_clusters; - - p_chain->size += num_clusters; - return num_clusters; -} - -void exfat_free_cluster(struct super_block *sb, struct chain_t *p_chain, - s32 do_relse) -{ - s32 num_clusters = 0; - u32 clu; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - int i; - sector_t sector; - - if ((p_chain->dir == CLUSTER_32(0)) || (p_chain->dir == CLUSTER_32(~0))) - return; - - if (p_chain->size <= 0) { - pr_err("[EXFAT] free_cluster : skip free-req clu:%u, because of zero-size truncation\n", - p_chain->dir); - return; - } - - __set_sb_dirty(sb); - clu = p_chain->dir; - - if (p_chain->flags == 0x03) { - do { - if (do_relse) { - sector = START_SECTOR(clu); - for (i = 0; i < p_fs->sectors_per_clu; i++) - exfat_buf_release(sb, sector + i); - } - - if (clr_alloc_bitmap(sb, clu - 2) != 0) - break; - clu++; - - num_clusters++; - } while (num_clusters < p_chain->size); - } else { - do { - if (p_fs->dev_ejected) - break; - - if (do_relse) { - sector = START_SECTOR(clu); - for (i = 0; i < p_fs->sectors_per_clu; i++) - exfat_buf_release(sb, sector + i); - } - - if (clr_alloc_bitmap(sb, clu - 2) != 0) - break; - - if (exfat_fat_read(sb, clu, &clu) == -1) - break; - num_clusters++; - } while ((clu != CLUSTER_32(0)) && (clu != CLUSTER_32(~0))); - } - - if (p_fs->used_clusters != UINT_MAX) - p_fs->used_clusters -= num_clusters; -} - -static u32 find_last_cluster(struct super_block *sb, struct chain_t *p_chain) -{ - u32 clu, next; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - - clu = p_chain->dir; - - if (p_chain->flags == 0x03) { - clu += p_chain->size - 1; - } else { - while ((exfat_fat_read(sb, clu, &next) == 0) && - (next != CLUSTER_32(~0))) { - if (p_fs->dev_ejected) - break; - clu = next; - } - } - - return clu; -} - -s32 count_num_clusters(struct super_block *sb, struct chain_t *p_chain) -{ - int i, count = 0; - u32 clu; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - - if ((p_chain->dir == CLUSTER_32(0)) || (p_chain->dir == CLUSTER_32(~0))) - return 0; - - clu = p_chain->dir; - - if (p_chain->flags == 0x03) { - count = p_chain->size; - } else { - for (i = 2; i < p_fs->num_clusters; i++) { - count++; - if (exfat_fat_read(sb, clu, &clu) != 0) - return 0; - if (clu == CLUSTER_32(~0)) - break; - } - } - - return count; -} - -s32 exfat_count_used_clusters(struct super_block *sb) -{ - int i, map_i, map_b, count = 0; - u8 k; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); - - map_i = 0; - map_b = 0; - - for (i = 2; i < p_fs->num_clusters; i += 8) { - k = *(((u8 *)p_fs->vol_amap[map_i]->b_data) + map_b); - count += used_bit[k]; - - if ((++map_b) >= p_bd->sector_size) { - map_i++; - map_b = 0; - } - } - - return count; -} - -void exfat_chain_cont_cluster(struct super_block *sb, u32 chain, s32 len) -{ - if (len == 0) - return; - - while (len > 1) { - if (exfat_fat_write(sb, chain, chain + 1) < 0) - break; - chain++; - len--; - } - exfat_fat_write(sb, chain, CLUSTER_32(~0)); -} - -/* - * Allocation Bitmap Management Functions - */ - -s32 load_alloc_bitmap(struct super_block *sb) -{ - int i, j, ret; - u32 map_size; - u32 type; - sector_t sector; - struct chain_t clu; - struct bmap_dentry_t *ep; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); - - clu.dir = p_fs->root_dir; - clu.flags = 0x01; - - while (clu.dir != CLUSTER_32(~0)) { - if (p_fs->dev_ejected) - break; - - for (i = 0; i < p_fs->dentries_per_clu; i++) { - ep = (struct bmap_dentry_t *)get_entry_in_dir(sb, &clu, - i, NULL); - if (!ep) - return -ENOENT; - - type = exfat_get_entry_type((struct dentry_t *)ep); - - if (type == TYPE_UNUSED) - break; - if (type != TYPE_BITMAP) - continue; - - if (ep->flags == 0x0) { - p_fs->map_clu = GET32_A(ep->start_clu); - map_size = (u32)GET64_A(ep->size); - - p_fs->map_sectors = ((map_size - 1) >> p_bd->sector_size_bits) + 1; - - p_fs->vol_amap = kmalloc_array(p_fs->map_sectors, - sizeof(struct buffer_head *), - GFP_KERNEL); - if (!p_fs->vol_amap) - return -ENOMEM; - - sector = START_SECTOR(p_fs->map_clu); - - for (j = 0; j < p_fs->map_sectors; j++) { - p_fs->vol_amap[j] = NULL; - ret = sector_read(sb, sector + j, &p_fs->vol_amap[j], 1); - if (ret != 0) { - /* release all buffers and free vol_amap */ - i = 0; - while (i < j) - brelse(p_fs->vol_amap[i++]); - - kfree(p_fs->vol_amap); - p_fs->vol_amap = NULL; - return ret; - } - } - - p_fs->pbr_bh = NULL; - return 0; - } - } - - if (exfat_fat_read(sb, clu.dir, &clu.dir) != 0) - return -EIO; - } - - return -EFSCORRUPTED; -} - -void free_alloc_bitmap(struct super_block *sb) -{ - int i; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - - brelse(p_fs->pbr_bh); - - for (i = 0; i < p_fs->map_sectors; i++) - __brelse(p_fs->vol_amap[i]); - - kfree(p_fs->vol_amap); - p_fs->vol_amap = NULL; -} - -/* - * Upcase table Management Functions - */ -static s32 __load_upcase_table(struct super_block *sb, sector_t sector, - u32 num_sectors, u32 utbl_checksum) -{ - int i, ret = -EINVAL; - u32 j; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); - struct buffer_head *tmp_bh = NULL; - sector_t end_sector = num_sectors + sector; - - bool skip = false; - u32 index = 0; - u16 uni = 0; - u16 **upcase_table; - - u32 checksum = 0; - - upcase_table = kmalloc_array(UTBL_COL_COUNT, sizeof(u16 *), GFP_KERNEL); - p_fs->vol_utbl = upcase_table; - if (!upcase_table) - return -ENOMEM; - memset(upcase_table, 0, UTBL_COL_COUNT * sizeof(u16 *)); - - while (sector < end_sector) { - ret = sector_read(sb, sector, &tmp_bh, 1); - if (ret != 0) { - pr_debug("sector read (0x%llX)fail\n", - (unsigned long long)sector); - goto error; - } - sector++; - - for (i = 0; i < p_bd->sector_size && index <= 0xFFFF; i += 2) { - uni = GET16(((u8 *)tmp_bh->b_data) + i); - - checksum = ((checksum & 1) ? 0x80000000 : 0) + - (checksum >> 1) + *(((u8 *)tmp_bh->b_data) + - i); - checksum = ((checksum & 1) ? 0x80000000 : 0) + - (checksum >> 1) + *(((u8 *)tmp_bh->b_data) + - (i + 1)); - - if (skip) { - pr_debug("skip from 0x%X ", index); - index += uni; - pr_debug("to 0x%X (amount of 0x%X)\n", - index, uni); - skip = false; - } else if (uni == index) { - index++; - } else if (uni == 0xFFFF) { - skip = true; - } else { /* uni != index , uni != 0xFFFF */ - u16 col_index = get_col_index(index); - - if (!upcase_table[col_index]) { - pr_debug("alloc = 0x%X\n", col_index); - upcase_table[col_index] = kmalloc_array(UTBL_ROW_COUNT, - sizeof(u16), GFP_KERNEL); - if (!upcase_table[col_index]) { - ret = -ENOMEM; - goto error; - } - - for (j = 0; j < UTBL_ROW_COUNT; j++) - upcase_table[col_index][j] = (col_index << LOW_INDEX_BIT) | j; - } - - upcase_table[col_index][get_row_index(index)] = uni; - index++; - } - } - } - if (index >= 0xFFFF && utbl_checksum == checksum) { - if (tmp_bh) - brelse(tmp_bh); - return 0; - } - ret = -EINVAL; -error: - if (tmp_bh) - brelse(tmp_bh); - free_upcase_table(sb); - return ret; -} - -static s32 __load_default_upcase_table(struct super_block *sb) -{ - int i, ret = -EINVAL; - u32 j; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - - bool skip = false; - u32 index = 0; - u16 uni = 0; - u16 **upcase_table; - - upcase_table = kmalloc_array(UTBL_COL_COUNT, sizeof(u16 *), GFP_KERNEL); - p_fs->vol_utbl = upcase_table; - if (!upcase_table) - return -ENOMEM; - memset(upcase_table, 0, UTBL_COL_COUNT * sizeof(u16 *)); - - for (i = 0; index <= 0xFFFF && i < NUM_UPCASE * 2; i += 2) { - uni = GET16(uni_upcase + i); - if (skip) { - pr_debug("skip from 0x%X ", index); - index += uni; - pr_debug("to 0x%X (amount of 0x%X)\n", index, uni); - skip = false; - } else if (uni == index) { - index++; - } else if (uni == 0xFFFF) { - skip = true; - } else { /* uni != index , uni != 0xFFFF */ - u16 col_index = get_col_index(index); - - if (!upcase_table[col_index]) { - pr_debug("alloc = 0x%X\n", col_index); - upcase_table[col_index] = kmalloc_array(UTBL_ROW_COUNT, - sizeof(u16), - GFP_KERNEL); - if (!upcase_table[col_index]) { - ret = -ENOMEM; - goto error; - } - - for (j = 0; j < UTBL_ROW_COUNT; j++) - upcase_table[col_index][j] = (col_index << LOW_INDEX_BIT) | j; - } - - upcase_table[col_index][get_row_index(index)] = uni; - index++; - } - } - - if (index >= 0xFFFF) - return 0; - -error: - /* FATAL error: default upcase table has error */ - free_upcase_table(sb); - return ret; -} - -s32 load_upcase_table(struct super_block *sb) -{ - int i; - u32 tbl_clu, tbl_size; - sector_t sector; - u32 type, num_sectors; - struct chain_t clu; - struct case_dentry_t *ep; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); - - clu.dir = p_fs->root_dir; - clu.flags = 0x01; - - if (p_fs->dev_ejected) - return -EIO; - - while (clu.dir != CLUSTER_32(~0)) { - for (i = 0; i < p_fs->dentries_per_clu; i++) { - ep = (struct case_dentry_t *)get_entry_in_dir(sb, &clu, - i, NULL); - if (!ep) - return -ENOENT; - - type = exfat_get_entry_type((struct dentry_t *)ep); - - if (type == TYPE_UNUSED) - break; - if (type != TYPE_UPCASE) - continue; - - tbl_clu = GET32_A(ep->start_clu); - tbl_size = (u32)GET64_A(ep->size); - - sector = START_SECTOR(tbl_clu); - num_sectors = ((tbl_size - 1) >> p_bd->sector_size_bits) + 1; - if (__load_upcase_table(sb, sector, num_sectors, - GET32_A(ep->checksum)) != 0) - break; - return 0; - } - if (exfat_fat_read(sb, clu.dir, &clu.dir) != 0) - return -EIO; - } - /* load default upcase table */ - return __load_default_upcase_table(sb); -} - -void free_upcase_table(struct super_block *sb) -{ - u32 i; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - u16 **upcase_table; - - upcase_table = p_fs->vol_utbl; - for (i = 0; i < UTBL_COL_COUNT; i++) - kfree(upcase_table[i]); - - kfree(p_fs->vol_utbl); - p_fs->vol_utbl = NULL; -} - -/* - * Directory Entry Management Functions - */ - -u32 exfat_get_entry_type(struct dentry_t *p_entry) -{ - struct file_dentry_t *ep = (struct file_dentry_t *)p_entry; - - if (ep->type == 0x0) { - return TYPE_UNUSED; - } else if (ep->type < 0x80) { - return TYPE_DELETED; - } else if (ep->type == 0x80) { - return TYPE_INVALID; - } else if (ep->type < 0xA0) { - if (ep->type == 0x81) { - return TYPE_BITMAP; - } else if (ep->type == 0x82) { - return TYPE_UPCASE; - } else if (ep->type == 0x83) { - return TYPE_VOLUME; - } else if (ep->type == 0x85) { - if (GET16_A(ep->attr) & ATTR_SUBDIR) - return TYPE_DIR; - else - return TYPE_FILE; - } - return TYPE_CRITICAL_PRI; - } else if (ep->type < 0xC0) { - if (ep->type == 0xA0) - return TYPE_GUID; - else if (ep->type == 0xA1) - return TYPE_PADDING; - else if (ep->type == 0xA2) - return TYPE_ACLTAB; - return TYPE_BENIGN_PRI; - } else if (ep->type < 0xE0) { - if (ep->type == 0xC0) - return TYPE_STREAM; - else if (ep->type == 0xC1) - return TYPE_EXTEND; - else if (ep->type == 0xC2) - return TYPE_ACL; - return TYPE_CRITICAL_SEC; - } - - return TYPE_BENIGN_SEC; -} - -static void exfat_set_entry_type(struct dentry_t *p_entry, u32 type) -{ - struct file_dentry_t *ep = (struct file_dentry_t *)p_entry; - - if (type == TYPE_UNUSED) { - ep->type = 0x0; - } else if (type == TYPE_DELETED) { - ep->type &= ~0x80; - } else if (type == TYPE_STREAM) { - ep->type = 0xC0; - } else if (type == TYPE_EXTEND) { - ep->type = 0xC1; - } else if (type == TYPE_BITMAP) { - ep->type = 0x81; - } else if (type == TYPE_UPCASE) { - ep->type = 0x82; - } else if (type == TYPE_VOLUME) { - ep->type = 0x83; - } else if (type == TYPE_DIR) { - ep->type = 0x85; - SET16_A(ep->attr, ATTR_SUBDIR); - } else if (type == TYPE_FILE) { - ep->type = 0x85; - SET16_A(ep->attr, ATTR_ARCHIVE); - } -} - -u32 exfat_get_entry_attr(struct dentry_t *p_entry) -{ - struct file_dentry_t *ep = (struct file_dentry_t *)p_entry; - - return (u32)GET16_A(ep->attr); -} - -void exfat_set_entry_attr(struct dentry_t *p_entry, u32 attr) -{ - struct file_dentry_t *ep = (struct file_dentry_t *)p_entry; - - SET16_A(ep->attr, (u16)attr); -} - -u8 exfat_get_entry_flag(struct dentry_t *p_entry) -{ - struct strm_dentry_t *ep = (struct strm_dentry_t *)p_entry; - - return ep->flags; -} - -void exfat_set_entry_flag(struct dentry_t *p_entry, u8 flags) -{ - struct strm_dentry_t *ep = (struct strm_dentry_t *)p_entry; - - ep->flags = flags; -} - -u32 exfat_get_entry_clu0(struct dentry_t *p_entry) -{ - struct strm_dentry_t *ep = (struct strm_dentry_t *)p_entry; - - return GET32_A(ep->start_clu); -} - -void exfat_set_entry_clu0(struct dentry_t *p_entry, u32 start_clu) -{ - struct strm_dentry_t *ep = (struct strm_dentry_t *)p_entry; - - SET32_A(ep->start_clu, start_clu); -} - -u64 exfat_get_entry_size(struct dentry_t *p_entry) -{ - struct strm_dentry_t *ep = (struct strm_dentry_t *)p_entry; - - return GET64_A(ep->valid_size); -} - -void exfat_set_entry_size(struct dentry_t *p_entry, u64 size) -{ - struct strm_dentry_t *ep = (struct strm_dentry_t *)p_entry; - - SET64_A(ep->valid_size, size); - SET64_A(ep->size, size); -} - -void exfat_get_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp, - u8 mode) -{ - u16 t = 0x00, d = 0x21; - struct file_dentry_t *ep = (struct file_dentry_t *)p_entry; - - switch (mode) { - case TM_CREATE: - t = GET16_A(ep->create_time); - d = GET16_A(ep->create_date); - break; - case TM_MODIFY: - t = GET16_A(ep->modify_time); - d = GET16_A(ep->modify_date); - break; - case TM_ACCESS: - t = GET16_A(ep->access_time); - d = GET16_A(ep->access_date); - break; - } - - tp->sec = (t & 0x001F) << 1; - tp->min = (t >> 5) & 0x003F; - tp->hour = (t >> 11); - tp->day = (d & 0x001F); - tp->mon = (d >> 5) & 0x000F; - tp->year = (d >> 9); -} - -void exfat_set_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp, - u8 mode) -{ - u16 t, d; - struct file_dentry_t *ep = (struct file_dentry_t *)p_entry; - - t = (tp->hour << 11) | (tp->min << 5) | (tp->sec >> 1); - d = (tp->year << 9) | (tp->mon << 5) | tp->day; - - switch (mode) { - case TM_CREATE: - SET16_A(ep->create_time, t); - SET16_A(ep->create_date, d); - break; - case TM_MODIFY: - SET16_A(ep->modify_time, t); - SET16_A(ep->modify_date, d); - break; - case TM_ACCESS: - SET16_A(ep->access_time, t); - SET16_A(ep->access_date, d); - break; - } -} - -static void init_file_entry(struct file_dentry_t *ep, u32 type) -{ - struct timestamp_t tm, *tp; - - exfat_set_entry_type((struct dentry_t *)ep, type); - - tp = tm_current(&tm); - exfat_set_entry_time((struct dentry_t *)ep, tp, TM_CREATE); - exfat_set_entry_time((struct dentry_t *)ep, tp, TM_MODIFY); - exfat_set_entry_time((struct dentry_t *)ep, tp, TM_ACCESS); - ep->create_time_ms = 0; - ep->modify_time_ms = 0; - ep->access_time_ms = 0; -} - -static void init_strm_entry(struct strm_dentry_t *ep, u8 flags, u32 start_clu, u64 size) -{ - exfat_set_entry_type((struct dentry_t *)ep, TYPE_STREAM); - ep->flags = flags; - SET32_A(ep->start_clu, start_clu); - SET64_A(ep->valid_size, size); - SET64_A(ep->size, size); -} - -static void init_name_entry(struct name_dentry_t *ep, u16 *uniname) -{ - int i; - - exfat_set_entry_type((struct dentry_t *)ep, TYPE_EXTEND); - ep->flags = 0x0; - - for (i = 0; i < 30; i++, i++) { - SET16_A(ep->unicode_0_14 + i, *uniname); - if (*uniname == 0x0) - break; - uniname++; - } -} - -static s32 exfat_init_dir_entry(struct super_block *sb, struct chain_t *p_dir, - s32 entry, u32 type, u32 start_clu, u64 size) -{ - sector_t sector; - u8 flags; - struct file_dentry_t *file_ep; - struct strm_dentry_t *strm_ep; - - flags = (type == TYPE_FILE) ? 0x01 : 0x03; - - /* we cannot use get_entry_set_in_dir here because file ep is not initialized yet */ - file_ep = (struct file_dentry_t *)get_entry_in_dir(sb, p_dir, entry, - §or); - if (!file_ep) - return -ENOENT; - - strm_ep = (struct strm_dentry_t *)get_entry_in_dir(sb, p_dir, entry + 1, - §or); - if (!strm_ep) - return -ENOENT; - - init_file_entry(file_ep, type); - exfat_buf_modify(sb, sector); - - init_strm_entry(strm_ep, flags, start_clu, size); - exfat_buf_modify(sb, sector); - - return 0; -} - -static s32 exfat_init_ext_entry(struct super_block *sb, struct chain_t *p_dir, - s32 entry, s32 num_entries, - struct uni_name_t *p_uniname) -{ - int i; - sector_t sector; - u16 *uniname = p_uniname->name; - struct file_dentry_t *file_ep; - struct strm_dentry_t *strm_ep; - struct name_dentry_t *name_ep; - - file_ep = (struct file_dentry_t *)get_entry_in_dir(sb, p_dir, entry, - §or); - if (!file_ep) - return -ENOENT; - - file_ep->num_ext = (u8)(num_entries - 1); - exfat_buf_modify(sb, sector); - - strm_ep = (struct strm_dentry_t *)get_entry_in_dir(sb, p_dir, entry + 1, - §or); - if (!strm_ep) - return -ENOENT; - - strm_ep->name_len = p_uniname->name_len; - SET16_A(strm_ep->name_hash, p_uniname->name_hash); - exfat_buf_modify(sb, sector); - - for (i = 2; i < num_entries; i++) { - name_ep = (struct name_dentry_t *)get_entry_in_dir(sb, p_dir, - entry + i, - §or); - if (!name_ep) - return -ENOENT; - - init_name_entry(name_ep, uniname); - exfat_buf_modify(sb, sector); - uniname += 15; - } - - update_dir_checksum(sb, p_dir, entry); - - return 0; -} - -void exfat_delete_dir_entry(struct super_block *sb, struct chain_t *p_dir, - s32 entry, s32 order, s32 num_entries) -{ - int i; - sector_t sector; - struct dentry_t *ep; - - for (i = order; i < num_entries; i++) { - ep = get_entry_in_dir(sb, p_dir, entry + i, §or); - if (!ep) - return; - - exfat_set_entry_type(ep, TYPE_DELETED); - exfat_buf_modify(sb, sector); - } -} - -void update_dir_checksum(struct super_block *sb, struct chain_t *p_dir, - s32 entry) -{ - int i, num_entries; - sector_t sector; - u16 chksum; - struct file_dentry_t *file_ep; - struct dentry_t *ep; - - file_ep = (struct file_dentry_t *)get_entry_in_dir(sb, p_dir, entry, - §or); - if (!file_ep) - return; - - exfat_buf_lock(sb, sector); - - num_entries = (s32)file_ep->num_ext + 1; - chksum = calc_checksum_2byte((void *)file_ep, DENTRY_SIZE, 0, - CS_DIR_ENTRY); - - for (i = 1; i < num_entries; i++) { - ep = get_entry_in_dir(sb, p_dir, entry + i, NULL); - if (!ep) { - exfat_buf_unlock(sb, sector); - return; - } - - chksum = calc_checksum_2byte((void *)ep, DENTRY_SIZE, chksum, - CS_DEFAULT); - } - - SET16_A(file_ep->checksum, chksum); - exfat_buf_modify(sb, sector); - exfat_buf_unlock(sb, sector); -} - -static s32 __write_partial_entries_in_entry_set(struct super_block *sb, - struct entry_set_cache_t *es, - sector_t sec, s32 off, u32 count) -{ - s32 num_entries, buf_off = (off - es->offset); - u32 remaining_byte_in_sector, copy_entries; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); - u32 clu; - u8 *buf, *esbuf = (u8 *)&es->__buf; - - pr_debug("%s entered es %p sec %llu off %d count %d\n", - __func__, es, (unsigned long long)sec, off, count); - num_entries = count; - - while (num_entries) { - /* white per sector base */ - remaining_byte_in_sector = (1 << p_bd->sector_size_bits) - off; - copy_entries = min_t(s32, - remaining_byte_in_sector >> DENTRY_SIZE_BITS, - num_entries); - buf = exfat_buf_getblk(sb, sec); - if (!buf) - goto err_out; - pr_debug("es->buf %p buf_off %u\n", esbuf, buf_off); - pr_debug("copying %d entries from %p to sector %llu\n", - copy_entries, (esbuf + buf_off), - (unsigned long long)sec); - memcpy(buf + off, esbuf + buf_off, - copy_entries << DENTRY_SIZE_BITS); - exfat_buf_modify(sb, sec); - num_entries -= copy_entries; - - if (num_entries) { - /* get next sector */ - if (IS_LAST_SECTOR_IN_CLUSTER(sec)) { - clu = GET_CLUSTER_FROM_SECTOR(sec); - if (es->alloc_flag == 0x03) { - clu++; - } else { - if (exfat_fat_read(sb, clu, &clu) == -1) - goto err_out; - } - sec = START_SECTOR(clu); - } else { - sec++; - } - off = 0; - buf_off += copy_entries << DENTRY_SIZE_BITS; - } - } - - pr_debug("%s exited successfully\n", __func__); - return 0; -err_out: - pr_debug("%s failed\n", __func__); - return -EINVAL; -} - -/* write back all entries in entry set */ -static s32 write_whole_entry_set(struct super_block *sb, struct entry_set_cache_t *es) -{ - return __write_partial_entries_in_entry_set(sb, es, es->sector, - es->offset, - es->num_entries); -} - -void update_dir_checksum_with_entry_set(struct super_block *sb, - struct entry_set_cache_t *es) -{ - struct dentry_t *ep; - u16 chksum = 0; - s32 chksum_type = CS_DIR_ENTRY, i; - - ep = (struct dentry_t *)&es->__buf; - for (i = 0; i < es->num_entries; i++) { - pr_debug("%s ep %p\n", __func__, ep); - chksum = calc_checksum_2byte((void *)ep, DENTRY_SIZE, chksum, - chksum_type); - ep++; - chksum_type = CS_DEFAULT; - } - - ep = (struct dentry_t *)&es->__buf; - SET16_A(((struct file_dentry_t *)ep)->checksum, chksum); - write_whole_entry_set(sb, es); -} - -static s32 _walk_fat_chain(struct super_block *sb, struct chain_t *p_dir, - s32 byte_offset, u32 *clu) -{ - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - s32 clu_offset; - u32 cur_clu; - - clu_offset = byte_offset >> p_fs->cluster_size_bits; - cur_clu = p_dir->dir; - - if (p_dir->flags == 0x03) { - cur_clu += clu_offset; - } else { - while (clu_offset > 0) { - if (exfat_fat_read(sb, cur_clu, &cur_clu) == -1) - return -EIO; - clu_offset--; - } - } - - if (clu) - *clu = cur_clu; - return 0; -} - -static s32 find_location(struct super_block *sb, struct chain_t *p_dir, s32 entry, - sector_t *sector, s32 *offset) -{ - s32 off, ret; - u32 clu = 0; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); - - off = entry << DENTRY_SIZE_BITS; - - if (p_dir->dir == CLUSTER_32(0)) { /* FAT16 root_dir */ - *offset = off & p_bd->sector_size_mask; - *sector = off >> p_bd->sector_size_bits; - *sector += p_fs->root_start_sector; - } else { - ret = _walk_fat_chain(sb, p_dir, off, &clu); - if (ret != 0) - return ret; - - /* byte offset in cluster */ - off &= p_fs->cluster_size - 1; - - /* byte offset in sector */ - *offset = off & p_bd->sector_size_mask; - - /* sector offset in cluster */ - *sector = off >> p_bd->sector_size_bits; - *sector += START_SECTOR(clu); - } - return 0; -} - -struct dentry_t *get_entry_in_dir(struct super_block *sb, struct chain_t *p_dir, - s32 entry, sector_t *sector) -{ - s32 off; - sector_t sec; - u8 *buf; - - if (find_location(sb, p_dir, entry, &sec, &off) != 0) - return NULL; - - buf = exfat_buf_getblk(sb, sec); - - if (!buf) - return NULL; - - if (sector) - *sector = sec; - return (struct dentry_t *)(buf + off); -} - -/* returns a set of dentries for a file or dir. - * Note that this is a copy (dump) of dentries so that user should call write_entry_set() - * to apply changes made in this entry set to the real device. - * in: - * sb+p_dir+entry: indicates a file/dir - * type: specifies how many dentries should be included. - * out: - * file_ep: will point the first dentry(= file dentry) on success - * return: - * pointer of entry set on success, - * NULL on failure. - */ - -#define ES_MODE_STARTED 0 -#define ES_MODE_GET_FILE_ENTRY 1 -#define ES_MODE_GET_STRM_ENTRY 2 -#define ES_MODE_GET_NAME_ENTRY 3 -#define ES_MODE_GET_CRITICAL_SEC_ENTRY 4 -struct entry_set_cache_t *get_entry_set_in_dir(struct super_block *sb, - struct chain_t *p_dir, s32 entry, - u32 type, - struct dentry_t **file_ep) -{ - s32 off, ret, byte_offset; - u32 clu = 0; - sector_t sec; - u32 entry_type; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); - struct entry_set_cache_t *es = NULL; - struct dentry_t *ep, *pos; - u8 *buf; - u8 num_entries; - s32 mode = ES_MODE_STARTED; - size_t bufsize; - - pr_debug("%s entered p_dir dir %u flags %x size %d\n", - __func__, p_dir->dir, p_dir->flags, p_dir->size); - - byte_offset = entry << DENTRY_SIZE_BITS; - ret = _walk_fat_chain(sb, p_dir, byte_offset, &clu); - if (ret != 0) - return NULL; - - /* byte offset in cluster */ - byte_offset &= p_fs->cluster_size - 1; - - /* byte offset in sector */ - off = byte_offset & p_bd->sector_size_mask; - - /* sector offset in cluster */ - sec = byte_offset >> p_bd->sector_size_bits; - sec += START_SECTOR(clu); - - buf = exfat_buf_getblk(sb, sec); - if (!buf) - goto err_out; - - ep = (struct dentry_t *)(buf + off); - entry_type = exfat_get_entry_type(ep); - - if ((entry_type != TYPE_FILE) && (entry_type != TYPE_DIR)) - goto err_out; - - if (type == ES_ALL_ENTRIES) - num_entries = ((struct file_dentry_t *)ep)->num_ext + 1; - else - num_entries = type; - - bufsize = offsetof(struct entry_set_cache_t, __buf) + (num_entries) * - sizeof(struct dentry_t); - pr_debug("%s: trying to kmalloc %zx bytes for %d entries\n", __func__, - bufsize, num_entries); - es = kmalloc(bufsize, GFP_KERNEL); - if (!es) - goto err_out; - - es->num_entries = num_entries; - es->sector = sec; - es->offset = off; - es->alloc_flag = p_dir->flags; - - pos = (struct dentry_t *)&es->__buf; - - while (num_entries) { - /* - * instead of copying whole sector, we will check every entry. - * this will provide minimum stablity and consistency. - */ - entry_type = exfat_get_entry_type(ep); - - if ((entry_type == TYPE_UNUSED) || (entry_type == TYPE_DELETED)) - goto err_out; - - switch (mode) { - case ES_MODE_STARTED: - if ((entry_type == TYPE_FILE) || (entry_type == TYPE_DIR)) - mode = ES_MODE_GET_FILE_ENTRY; - else - goto err_out; - break; - case ES_MODE_GET_FILE_ENTRY: - if (entry_type == TYPE_STREAM) - mode = ES_MODE_GET_STRM_ENTRY; - else - goto err_out; - break; - case ES_MODE_GET_STRM_ENTRY: - if (entry_type == TYPE_EXTEND) - mode = ES_MODE_GET_NAME_ENTRY; - else - goto err_out; - break; - case ES_MODE_GET_NAME_ENTRY: - if (entry_type == TYPE_EXTEND) - break; - else if (entry_type == TYPE_STREAM) - goto err_out; - else if (entry_type & TYPE_CRITICAL_SEC) - mode = ES_MODE_GET_CRITICAL_SEC_ENTRY; - else - goto err_out; - break; - case ES_MODE_GET_CRITICAL_SEC_ENTRY: - if ((entry_type == TYPE_EXTEND) || - (entry_type == TYPE_STREAM)) - goto err_out; - else if ((entry_type & TYPE_CRITICAL_SEC) != - TYPE_CRITICAL_SEC) - goto err_out; - break; - } - - memcpy(pos, ep, sizeof(struct dentry_t)); - - if (--num_entries == 0) - break; - - if (((off + DENTRY_SIZE) & p_bd->sector_size_mask) < - (off & p_bd->sector_size_mask)) { - /* get the next sector */ - if (IS_LAST_SECTOR_IN_CLUSTER(sec)) { - if (es->alloc_flag == 0x03) { - clu++; - } else { - if (exfat_fat_read(sb, clu, &clu) == -1) - goto err_out; - } - sec = START_SECTOR(clu); - } else { - sec++; - } - buf = exfat_buf_getblk(sb, sec); - if (!buf) - goto err_out; - off = 0; - ep = (struct dentry_t *)(buf); - } else { - ep++; - off += DENTRY_SIZE; - } - pos++; - } - - if (file_ep) - *file_ep = (struct dentry_t *)&es->__buf; - - pr_debug("%s exiting es %p sec %llu offset %d flags %d, num_entries %u buf ptr %p\n", - __func__, es, (unsigned long long)es->sector, es->offset, - es->alloc_flag, es->num_entries, &es->__buf); - return es; -err_out: - pr_debug("%s exited NULL (es %p)\n", __func__, es); - kfree(es); - return NULL; -} - -void release_entry_set(struct entry_set_cache_t *es) -{ - pr_debug("%s es=%p\n", __func__, es); - kfree(es); -} - -/* search EMPTY CONTINUOUS "num_entries" entries */ -static s32 search_deleted_or_unused_entry(struct super_block *sb, - struct chain_t *p_dir, - s32 num_entries) -{ - int i, dentry, num_empty = 0; - s32 dentries_per_clu; - u32 type; - struct chain_t clu; - struct dentry_t *ep; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - - if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */ - dentries_per_clu = p_fs->dentries_in_root; - else - dentries_per_clu = p_fs->dentries_per_clu; - - if (p_fs->hint_uentry.dir == p_dir->dir) { - if (p_fs->hint_uentry.entry == -1) - return -1; - - clu.dir = p_fs->hint_uentry.clu.dir; - clu.size = p_fs->hint_uentry.clu.size; - clu.flags = p_fs->hint_uentry.clu.flags; - - dentry = p_fs->hint_uentry.entry; - } else { - p_fs->hint_uentry.entry = -1; - - clu.dir = p_dir->dir; - clu.size = p_dir->size; - clu.flags = p_dir->flags; - - dentry = 0; - } - - while (clu.dir != CLUSTER_32(~0)) { - if (p_fs->dev_ejected) - break; - - if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */ - i = dentry % dentries_per_clu; - else - i = dentry & (dentries_per_clu - 1); - - for (; i < dentries_per_clu; i++, dentry++) { - ep = get_entry_in_dir(sb, &clu, i, NULL); - if (!ep) - return -1; - - type = exfat_get_entry_type(ep); - - if (type == TYPE_UNUSED) { - num_empty++; - if (p_fs->hint_uentry.entry == -1) { - p_fs->hint_uentry.dir = p_dir->dir; - p_fs->hint_uentry.entry = dentry; - - p_fs->hint_uentry.clu.dir = clu.dir; - p_fs->hint_uentry.clu.size = clu.size; - p_fs->hint_uentry.clu.flags = clu.flags; - } - } else if (type == TYPE_DELETED) { - num_empty++; - } else { - num_empty = 0; - } - - if (num_empty >= num_entries) { - p_fs->hint_uentry.dir = CLUSTER_32(~0); - p_fs->hint_uentry.entry = -1; - return dentry - (num_entries - 1); - } - } - - if (p_dir->dir == CLUSTER_32(0)) - break; /* FAT16 root_dir */ - - if (clu.flags == 0x03) { - if ((--clu.size) > 0) - clu.dir++; - else - clu.dir = CLUSTER_32(~0); - } else { - if (exfat_fat_read(sb, clu.dir, &clu.dir) != 0) - return -1; - } - } - - return -1; -} - -static s32 find_empty_entry(struct inode *inode, struct chain_t *p_dir, s32 num_entries) -{ - s32 ret, dentry; - u32 last_clu; - sector_t sector; - u64 size = 0; - struct chain_t clu; - struct dentry_t *ep = NULL; - struct super_block *sb = inode->i_sb; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - struct file_id_t *fid = &(EXFAT_I(inode)->fid); - - if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */ - return search_deleted_or_unused_entry(sb, p_dir, num_entries); - - while ((dentry = search_deleted_or_unused_entry(sb, p_dir, num_entries)) < 0) { - if (p_fs->dev_ejected) - break; - - if (p_dir->dir != p_fs->root_dir) - size = i_size_read(inode); - - last_clu = find_last_cluster(sb, p_dir); - clu.dir = last_clu + 1; - clu.size = 0; - clu.flags = p_dir->flags; - - /* (1) allocate a cluster */ - ret = exfat_alloc_cluster(sb, 1, &clu); - if (ret < 1) - return -EIO; - - if (clear_cluster(sb, clu.dir) != 0) - return -EIO; - - /* (2) append to the FAT chain */ - if (clu.flags != p_dir->flags) { - exfat_chain_cont_cluster(sb, p_dir->dir, p_dir->size); - p_dir->flags = 0x01; - p_fs->hint_uentry.clu.flags = 0x01; - } - if (clu.flags == 0x01) - if (exfat_fat_write(sb, last_clu, clu.dir) < 0) - return -EIO; - - if (p_fs->hint_uentry.entry == -1) { - p_fs->hint_uentry.dir = p_dir->dir; - p_fs->hint_uentry.entry = p_dir->size << (p_fs->cluster_size_bits - DENTRY_SIZE_BITS); - - p_fs->hint_uentry.clu.dir = clu.dir; - p_fs->hint_uentry.clu.size = 0; - p_fs->hint_uentry.clu.flags = clu.flags; - } - p_fs->hint_uentry.clu.size++; - p_dir->size++; - - /* (3) update the directory entry */ - if (p_dir->dir != p_fs->root_dir) { - size += p_fs->cluster_size; - - ep = get_entry_in_dir(sb, &fid->dir, - fid->entry + 1, §or); - if (!ep) - return -ENOENT; - exfat_set_entry_size(ep, size); - exfat_set_entry_flag(ep, p_dir->flags); - exfat_buf_modify(sb, sector); - - update_dir_checksum(sb, &fid->dir, - fid->entry); - } - - i_size_write(inode, i_size_read(inode) + p_fs->cluster_size); - EXFAT_I(inode)->mmu_private += p_fs->cluster_size; - EXFAT_I(inode)->fid.size += p_fs->cluster_size; - EXFAT_I(inode)->fid.flags = p_dir->flags; - inode->i_blocks += 1 << (p_fs->cluster_size_bits - 9); - } - - return dentry; -} - -static s32 extract_uni_name_from_name_entry(struct name_dentry_t *ep, u16 *uniname, - s32 order) -{ - int i, len = 0; - - for (i = 0; i < 30; i += 2) { - *uniname = GET16_A(ep->unicode_0_14 + i); - if (*uniname == 0x0) - return len; - uniname++; - len++; - } - - *uniname = 0x0; - return len; -} - -/* return values of exfat_find_dir_entry() - * >= 0 : return dir entiry position with the name in dir - * -1 : (root dir, ".") it is the root dir itself - * -2 : entry with the name does not exist - */ -s32 exfat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir, - struct uni_name_t *p_uniname, s32 num_entries, - u32 type) -{ - int i = 0, dentry = 0, num_ext_entries = 0, len, step; - s32 order = 0; - bool is_feasible_entry = false; - s32 dentries_per_clu, num_empty = 0; - u32 entry_type; - u16 entry_uniname[16], *uniname = NULL, unichar; - struct chain_t clu; - struct dentry_t *ep; - struct file_dentry_t *file_ep; - struct strm_dentry_t *strm_ep; - struct name_dentry_t *name_ep; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - - if (p_dir->dir == p_fs->root_dir) { - if ((!nls_uniname_cmp(sb, p_uniname->name, - (u16 *)UNI_CUR_DIR_NAME)) || - (!nls_uniname_cmp(sb, p_uniname->name, - (u16 *)UNI_PAR_DIR_NAME))) - return -1; // special case, root directory itself - } - - if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */ - dentries_per_clu = p_fs->dentries_in_root; - else - dentries_per_clu = p_fs->dentries_per_clu; - - clu.dir = p_dir->dir; - clu.size = p_dir->size; - clu.flags = p_dir->flags; - - p_fs->hint_uentry.dir = p_dir->dir; - p_fs->hint_uentry.entry = -1; - - while (clu.dir != CLUSTER_32(~0)) { - if (p_fs->dev_ejected) - break; - - while (i < dentries_per_clu) { - ep = get_entry_in_dir(sb, &clu, i, NULL); - if (!ep) - return -2; - - entry_type = exfat_get_entry_type(ep); - step = 1; - - if ((entry_type == TYPE_UNUSED) || (entry_type == TYPE_DELETED)) { - is_feasible_entry = false; - - if (p_fs->hint_uentry.entry == -1) { - num_empty++; - - if (num_empty == 1) { - p_fs->hint_uentry.clu.dir = clu.dir; - p_fs->hint_uentry.clu.size = clu.size; - p_fs->hint_uentry.clu.flags = clu.flags; - } - if ((num_empty >= num_entries) || (entry_type == TYPE_UNUSED)) - p_fs->hint_uentry.entry = dentry - (num_empty - 1); - } - - if (entry_type == TYPE_UNUSED) - return -2; - } else { - num_empty = 0; - - if ((entry_type == TYPE_FILE) || (entry_type == TYPE_DIR)) { - file_ep = (struct file_dentry_t *)ep; - if ((type == TYPE_ALL) || (type == entry_type)) { - num_ext_entries = file_ep->num_ext; - is_feasible_entry = true; - } else { - is_feasible_entry = false; - step = file_ep->num_ext + 1; - } - } else if (entry_type == TYPE_STREAM) { - if (is_feasible_entry) { - strm_ep = (struct strm_dentry_t *)ep; - if (p_uniname->name_hash == GET16_A(strm_ep->name_hash) && - p_uniname->name_len == strm_ep->name_len) { - order = 1; - } else { - is_feasible_entry = false; - step = num_ext_entries; - } - } - } else if (entry_type == TYPE_EXTEND) { - if (is_feasible_entry) { - name_ep = (struct name_dentry_t *)ep; - - if ((++order) == 2) - uniname = p_uniname->name; - else - uniname += 15; - - len = extract_uni_name_from_name_entry(name_ep, - entry_uniname, order); - - unichar = *(uniname + len); - *(uniname + len) = 0x0; - - if (nls_uniname_cmp(sb, uniname, entry_uniname)) { - is_feasible_entry = false; - step = num_ext_entries - order + 1; - } else if (order == num_ext_entries) { - p_fs->hint_uentry.dir = CLUSTER_32(~0); - p_fs->hint_uentry.entry = -1; - return dentry - (num_ext_entries); - } - - *(uniname + len) = unichar; - } - } else { - is_feasible_entry = false; - } - } - - i += step; - dentry += step; - } - - i -= dentries_per_clu; - - if (p_dir->dir == CLUSTER_32(0)) - break; /* FAT16 root_dir */ - - if (clu.flags == 0x03) { - if ((--clu.size) > 0) - clu.dir++; - else - clu.dir = CLUSTER_32(~0); - } else { - if (exfat_fat_read(sb, clu.dir, &clu.dir) != 0) - return -2; - } - } - - return -2; -} - -s32 exfat_count_ext_entries(struct super_block *sb, struct chain_t *p_dir, - s32 entry, struct dentry_t *p_entry) -{ - int i, count = 0; - u32 type; - struct file_dentry_t *file_ep = (struct file_dentry_t *)p_entry; - struct dentry_t *ext_ep; - - for (i = 0, entry++; i < file_ep->num_ext; i++, entry++) { - ext_ep = get_entry_in_dir(sb, p_dir, entry, NULL); - if (!ext_ep) - return -1; - - type = exfat_get_entry_type(ext_ep); - if ((type == TYPE_EXTEND) || (type == TYPE_STREAM)) - count++; - else - return count; - } - - return count; -} - -s32 count_dir_entries(struct super_block *sb, struct chain_t *p_dir) -{ - int i, count = 0; - s32 dentries_per_clu; - u32 entry_type; - struct chain_t clu; - struct dentry_t *ep; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - - if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */ - dentries_per_clu = p_fs->dentries_in_root; - else - dentries_per_clu = p_fs->dentries_per_clu; - - clu.dir = p_dir->dir; - clu.size = p_dir->size; - clu.flags = p_dir->flags; - - while (clu.dir != CLUSTER_32(~0)) { - if (p_fs->dev_ejected) - break; - - for (i = 0; i < dentries_per_clu; i++) { - ep = get_entry_in_dir(sb, &clu, i, NULL); - if (!ep) - return -ENOENT; - - entry_type = exfat_get_entry_type(ep); - - if (entry_type == TYPE_UNUSED) - return count; - if (entry_type == TYPE_DIR) - count++; - } - - if (p_dir->dir == CLUSTER_32(0)) - break; /* FAT16 root_dir */ - - if (clu.flags == 0x03) { - if ((--clu.size) > 0) - clu.dir++; - else - clu.dir = CLUSTER_32(~0); - } else { - if (exfat_fat_read(sb, clu.dir, &clu.dir) != 0) - return -EIO; - } - } - - return count; -} - -bool is_dir_empty(struct super_block *sb, struct chain_t *p_dir) -{ - int i; - s32 dentries_per_clu; - u32 type; - struct chain_t clu; - struct dentry_t *ep; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - - if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */ - dentries_per_clu = p_fs->dentries_in_root; - else - dentries_per_clu = p_fs->dentries_per_clu; - - clu.dir = p_dir->dir; - clu.size = p_dir->size; - clu.flags = p_dir->flags; - - while (clu.dir != CLUSTER_32(~0)) { - if (p_fs->dev_ejected) - break; - - for (i = 0; i < dentries_per_clu; i++) { - ep = get_entry_in_dir(sb, &clu, i, NULL); - if (!ep) - break; - - type = exfat_get_entry_type(ep); - - if (type == TYPE_UNUSED) - return true; - if ((type == TYPE_FILE) || (type == TYPE_DIR)) - return false; - } - - if (p_dir->dir == CLUSTER_32(0)) - break; /* FAT16 root_dir */ - - if (clu.flags == 0x03) { - if ((--clu.size) > 0) - clu.dir++; - else - clu.dir = CLUSTER_32(~0); - } - if (exfat_fat_read(sb, clu.dir, &clu.dir) != 0) - break; - } - - return true; -} - -/* - * Name Conversion Functions - */ - -/* input : dir, uni_name - * output : num_of_entry - */ -s32 get_num_entries(struct super_block *sb, struct chain_t *p_dir, - struct uni_name_t *p_uniname, s32 *entries) -{ - s32 num_entries; - - num_entries = exfat_calc_num_entries(p_uniname); - if (num_entries == 0) - return -EINVAL; - - *entries = num_entries; - - return 0; -} - -void exfat_get_uni_name_from_ext_entry(struct super_block *sb, - struct chain_t *p_dir, s32 entry, - u16 *uniname) -{ - int i; - struct dentry_t *ep; - struct entry_set_cache_t *es; - - es = get_entry_set_in_dir(sb, p_dir, entry, ES_ALL_ENTRIES, &ep); - if (!es || es->num_entries < 3) { - if (es) - release_entry_set(es); - return; - } - - ep += 2; - - /* - * First entry : file entry - * Second entry : stream-extension entry - * Third entry : first file-name entry - * So, the index of first file-name dentry should start from 2. - */ - for (i = 2; i < es->num_entries; i++, ep++) { - if (exfat_get_entry_type(ep) == TYPE_EXTEND) - extract_uni_name_from_name_entry((struct name_dentry_t *) - ep, uniname, i); - else - goto out; - uniname += 15; - } - -out: - release_entry_set(es); -} - -s32 exfat_calc_num_entries(struct uni_name_t *p_uniname) -{ - s32 len; - - len = p_uniname->name_len; - if (len == 0) - return 0; - - /* 1 file entry + 1 stream entry + name entries */ - return (len - 1) / 15 + 3; -} - -u16 calc_checksum_2byte(void *data, s32 len, u16 chksum, s32 type) -{ - int i; - u8 *c = (u8 *)data; - - switch (type) { - case CS_DIR_ENTRY: - for (i = 0; i < len; i++, c++) { - if ((i == 2) || (i == 3)) - continue; - chksum = (((chksum & 1) << 15) | - ((chksum & 0xFFFE) >> 1)) + (u16)*c; - } - break; - default - : - for (i = 0; i < len; i++, c++) - chksum = (((chksum & 1) << 15) | - ((chksum & 0xFFFE) >> 1)) + (u16)*c; - } - - return chksum; -} - -/* - * Name Resolution Functions - */ - -/* return values of resolve_path() - * > 0 : return the length of the path - * < 0 : return error - */ -s32 resolve_path(struct inode *inode, char *path, struct chain_t *p_dir, - struct uni_name_t *p_uniname) -{ - bool lossy = false; - struct super_block *sb = inode->i_sb; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - struct file_id_t *fid = &(EXFAT_I(inode)->fid); - - if (strscpy(name_buf, path, sizeof(name_buf)) < 0) - return -EINVAL; - - nls_cstring_to_uniname(sb, p_uniname, name_buf, &lossy); - if (lossy) - return -EINVAL; - - fid->size = i_size_read(inode); - - p_dir->dir = fid->start_clu; - p_dir->size = (s32)(fid->size >> p_fs->cluster_size_bits); - p_dir->flags = fid->flags; - - return 0; -} - -s32 exfat_mount(struct super_block *sb, struct pbr_sector_t *p_pbr) -{ - struct bpbex_t *p_bpb = (struct bpbex_t *)p_pbr->bpb; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); - - if (p_bpb->num_fats == 0) - return -EFSCORRUPTED; - - p_fs->sectors_per_clu = 1 << p_bpb->sectors_per_clu_bits; - p_fs->sectors_per_clu_bits = p_bpb->sectors_per_clu_bits; - p_fs->cluster_size_bits = p_fs->sectors_per_clu_bits + - p_bd->sector_size_bits; - p_fs->cluster_size = 1 << p_fs->cluster_size_bits; - - p_fs->num_FAT_sectors = GET32(p_bpb->fat_length); - - p_fs->FAT1_start_sector = p_fs->PBR_sector + GET32(p_bpb->fat_offset); - if (p_bpb->num_fats == 1) - p_fs->FAT2_start_sector = p_fs->FAT1_start_sector; - else - p_fs->FAT2_start_sector = p_fs->FAT1_start_sector + - p_fs->num_FAT_sectors; - - p_fs->root_start_sector = p_fs->PBR_sector + GET32(p_bpb->clu_offset); - p_fs->data_start_sector = p_fs->root_start_sector; - - p_fs->num_sectors = GET64(p_bpb->vol_length); - p_fs->num_clusters = GET32(p_bpb->clu_count) + 2; - /* because the cluster index starts with 2 */ - - p_fs->vol_id = GET32(p_bpb->vol_serial); - - p_fs->root_dir = GET32(p_bpb->root_cluster); - p_fs->dentries_in_root = 0; - p_fs->dentries_per_clu = 1 << (p_fs->cluster_size_bits - - DENTRY_SIZE_BITS); - - p_fs->vol_flag = (u32)GET16(p_bpb->vol_flags); - p_fs->clu_srch_ptr = 2; - p_fs->used_clusters = UINT_MAX; - - return 0; -} - -s32 create_dir(struct inode *inode, struct chain_t *p_dir, - struct uni_name_t *p_uniname, struct file_id_t *fid) -{ - s32 ret, dentry, num_entries; - u64 size; - struct chain_t clu; - struct super_block *sb = inode->i_sb; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - - ret = get_num_entries(sb, p_dir, p_uniname, &num_entries); - if (ret) - return ret; - - /* find_empty_entry must be called before alloc_cluster */ - dentry = find_empty_entry(inode, p_dir, num_entries); - if (dentry < 0) - return -ENOSPC; - - clu.dir = CLUSTER_32(~0); - clu.size = 0; - clu.flags = 0x03; - - /* (1) allocate a cluster */ - ret = exfat_alloc_cluster(sb, 1, &clu); - if (ret < 0) - return ret; - else if (ret == 0) - return -ENOSPC; - - ret = clear_cluster(sb, clu.dir); - if (ret != 0) - return ret; - - size = p_fs->cluster_size; - - /* (2) update the directory entry */ - /* make sub-dir entry in parent directory */ - ret = exfat_init_dir_entry(sb, p_dir, dentry, TYPE_DIR, clu.dir, - size); - if (ret != 0) - return ret; - - ret = exfat_init_ext_entry(sb, p_dir, dentry, num_entries, p_uniname); - if (ret != 0) - return ret; - - fid->dir.dir = p_dir->dir; - fid->dir.size = p_dir->size; - fid->dir.flags = p_dir->flags; - fid->entry = dentry; - - fid->attr = ATTR_SUBDIR; - fid->flags = 0x03; - fid->size = size; - fid->start_clu = clu.dir; - - fid->type = TYPE_DIR; - fid->rwoffset = 0; - fid->hint_last_off = -1; - - return 0; -} - -s32 create_file(struct inode *inode, struct chain_t *p_dir, - struct uni_name_t *p_uniname, struct file_id_t *fid) -{ - s32 ret, dentry, num_entries; - struct super_block *sb = inode->i_sb; - - ret = get_num_entries(sb, p_dir, p_uniname, &num_entries); - if (ret) - return ret; - - /* find_empty_entry must be called before alloc_cluster() */ - dentry = find_empty_entry(inode, p_dir, num_entries); - if (dentry < 0) - return -ENOSPC; - - /* (1) update the directory entry */ - /* fill the directory entry information of the created file. - * the first cluster is not determined yet. (0) - */ - ret = exfat_init_dir_entry(sb, p_dir, dentry, TYPE_FILE, - CLUSTER_32(0), 0); - if (ret != 0) - return ret; - - ret = exfat_init_ext_entry(sb, p_dir, dentry, num_entries, p_uniname); - if (ret != 0) - return ret; - - fid->dir.dir = p_dir->dir; - fid->dir.size = p_dir->size; - fid->dir.flags = p_dir->flags; - fid->entry = dentry; - - fid->attr = ATTR_ARCHIVE; - fid->flags = 0x03; - fid->size = 0; - fid->start_clu = CLUSTER_32(~0); - - fid->type = TYPE_FILE; - fid->rwoffset = 0; - fid->hint_last_off = -1; - - return 0; -} - -void remove_file(struct inode *inode, struct chain_t *p_dir, s32 entry) -{ - s32 num_entries; - sector_t sector; - struct dentry_t *ep; - struct super_block *sb = inode->i_sb; - - ep = get_entry_in_dir(sb, p_dir, entry, §or); - if (!ep) - return; - - exfat_buf_lock(sb, sector); - - /* exfat_buf_lock() before call count_ext_entries() */ - num_entries = exfat_count_ext_entries(sb, p_dir, entry, ep); - if (num_entries < 0) { - exfat_buf_unlock(sb, sector); - return; - } - num_entries++; - - exfat_buf_unlock(sb, sector); - - /* (1) update the directory entry */ - exfat_delete_dir_entry(sb, p_dir, entry, 0, num_entries); -} - -s32 exfat_rename_file(struct inode *inode, struct chain_t *p_dir, s32 oldentry, - struct uni_name_t *p_uniname, struct file_id_t *fid) -{ - s32 ret, newentry = -1, num_old_entries, num_new_entries; - sector_t sector_old, sector_new; - struct dentry_t *epold, *epnew; - struct super_block *sb = inode->i_sb; - - epold = get_entry_in_dir(sb, p_dir, oldentry, §or_old); - if (!epold) - return -ENOENT; - - exfat_buf_lock(sb, sector_old); - - /* exfat_buf_lock() before call count_ext_entries() */ - num_old_entries = exfat_count_ext_entries(sb, p_dir, oldentry, - epold); - if (num_old_entries < 0) { - exfat_buf_unlock(sb, sector_old); - return -ENOENT; - } - num_old_entries++; - - ret = get_num_entries(sb, p_dir, p_uniname, &num_new_entries); - if (ret) { - exfat_buf_unlock(sb, sector_old); - return ret; - } - - if (num_old_entries < num_new_entries) { - newentry = find_empty_entry(inode, p_dir, num_new_entries); - if (newentry < 0) { - exfat_buf_unlock(sb, sector_old); - return -ENOSPC; - } - - epnew = get_entry_in_dir(sb, p_dir, newentry, §or_new); - if (!epnew) { - exfat_buf_unlock(sb, sector_old); - return -ENOENT; - } - - *epnew = *epold; - if (fid->type == TYPE_FILE) { - fid->attr |= ATTR_ARCHIVE; - exfat_set_entry_attr(epnew, fid->attr); - } - exfat_buf_modify(sb, sector_new); - exfat_buf_unlock(sb, sector_old); - - epold = get_entry_in_dir(sb, p_dir, oldentry + 1, - §or_old); - exfat_buf_lock(sb, sector_old); - epnew = get_entry_in_dir(sb, p_dir, newentry + 1, - §or_new); - - if (!epold || !epnew) { - exfat_buf_unlock(sb, sector_old); - return -ENOENT; - } - - *epnew = *epold; - exfat_buf_modify(sb, sector_new); - exfat_buf_unlock(sb, sector_old); - - ret = exfat_init_ext_entry(sb, p_dir, newentry, - num_new_entries, p_uniname); - if (ret != 0) - return ret; - - exfat_delete_dir_entry(sb, p_dir, oldentry, 0, - num_old_entries); - fid->entry = newentry; - } else { - if (fid->type == TYPE_FILE) { - fid->attr |= ATTR_ARCHIVE; - exfat_set_entry_attr(epold, fid->attr); - } - exfat_buf_modify(sb, sector_old); - exfat_buf_unlock(sb, sector_old); - - ret = exfat_init_ext_entry(sb, p_dir, oldentry, - num_new_entries, p_uniname); - if (ret != 0) - return ret; - - exfat_delete_dir_entry(sb, p_dir, oldentry, num_new_entries, - num_old_entries); - } - - return 0; -} - -s32 move_file(struct inode *inode, struct chain_t *p_olddir, s32 oldentry, - struct chain_t *p_newdir, struct uni_name_t *p_uniname, - struct file_id_t *fid) -{ - s32 ret, newentry, num_new_entries, num_old_entries; - sector_t sector_mov, sector_new; - struct dentry_t *epmov, *epnew; - struct super_block *sb = inode->i_sb; - - epmov = get_entry_in_dir(sb, p_olddir, oldentry, §or_mov); - if (!epmov) - return -ENOENT; - - /* check if the source and target directory is the same */ - if (exfat_get_entry_type(epmov) == TYPE_DIR && - exfat_get_entry_clu0(epmov) == p_newdir->dir) - return -EINVAL; - - exfat_buf_lock(sb, sector_mov); - - /* exfat_buf_lock() before call count_ext_entries() */ - num_old_entries = exfat_count_ext_entries(sb, p_olddir, oldentry, - epmov); - if (num_old_entries < 0) { - exfat_buf_unlock(sb, sector_mov); - return -ENOENT; - } - num_old_entries++; - - ret = get_num_entries(sb, p_newdir, p_uniname, &num_new_entries); - if (ret) { - exfat_buf_unlock(sb, sector_mov); - return ret; - } - - newentry = find_empty_entry(inode, p_newdir, num_new_entries); - if (newentry < 0) { - exfat_buf_unlock(sb, sector_mov); - return -ENOSPC; - } - - epnew = get_entry_in_dir(sb, p_newdir, newentry, §or_new); - if (!epnew) { - exfat_buf_unlock(sb, sector_mov); - return -ENOENT; - } - - *epnew = *epmov; - if (fid->type == TYPE_FILE) { - fid->attr |= ATTR_ARCHIVE; - exfat_set_entry_attr(epnew, fid->attr); - } - exfat_buf_modify(sb, sector_new); - exfat_buf_unlock(sb, sector_mov); - - epmov = get_entry_in_dir(sb, p_olddir, oldentry + 1, - §or_mov); - exfat_buf_lock(sb, sector_mov); - epnew = get_entry_in_dir(sb, p_newdir, newentry + 1, - §or_new); - if (!epmov || !epnew) { - exfat_buf_unlock(sb, sector_mov); - return -ENOENT; - } - - *epnew = *epmov; - exfat_buf_modify(sb, sector_new); - exfat_buf_unlock(sb, sector_mov); - - ret = exfat_init_ext_entry(sb, p_newdir, newentry, num_new_entries, - p_uniname); - if (ret != 0) - return ret; - - exfat_delete_dir_entry(sb, p_olddir, oldentry, 0, num_old_entries); - - fid->dir.dir = p_newdir->dir; - fid->dir.size = p_newdir->size; - fid->dir.flags = p_newdir->flags; - - fid->entry = newentry; - - return 0; -} - -/* - * Sector Read/Write Functions - */ - -int sector_read(struct super_block *sb, sector_t sec, struct buffer_head **bh, - bool read) -{ - s32 ret = -EIO; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - - if ((sec >= (p_fs->PBR_sector + p_fs->num_sectors)) && - (p_fs->num_sectors > 0)) { - pr_err("[EXFAT] %s: out of range error! (sec = %llu)\n", - __func__, (unsigned long long)sec); - fs_error(sb); - return ret; - } - - if (!p_fs->dev_ejected) { - ret = exfat_bdev_read(sb, sec, bh, 1, read); - if (ret != 0) - p_fs->dev_ejected = 1; - } - - return ret; -} - -int sector_write(struct super_block *sb, sector_t sec, struct buffer_head *bh, - bool sync) -{ - s32 ret = -EIO; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - - if (sec >= (p_fs->PBR_sector + p_fs->num_sectors) && - (p_fs->num_sectors > 0)) { - pr_err("[EXFAT] %s: out of range error! (sec = %llu)\n", - __func__, (unsigned long long)sec); - fs_error(sb); - return ret; - } - - if (!bh) { - pr_err("[EXFAT] %s: bh is NULL!\n", __func__); - fs_error(sb); - return ret; - } - - if (!p_fs->dev_ejected) { - ret = exfat_bdev_write(sb, sec, bh, 1, sync); - if (ret != 0) - p_fs->dev_ejected = 1; - } - - return ret; -} - -int multi_sector_read(struct super_block *sb, sector_t sec, - struct buffer_head **bh, s32 num_secs, bool read) -{ - s32 ret = -EIO; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - - if (((sec + num_secs) > (p_fs->PBR_sector + p_fs->num_sectors)) && - (p_fs->num_sectors > 0)) { - pr_err("[EXFAT] %s: out of range error! (sec = %llu, num_secs = %d)\n", - __func__, (unsigned long long)sec, num_secs); - fs_error(sb); - return ret; - } - - if (!p_fs->dev_ejected) { - ret = exfat_bdev_read(sb, sec, bh, num_secs, read); - if (ret != 0) - p_fs->dev_ejected = 1; - } - - return ret; -} - -int multi_sector_write(struct super_block *sb, sector_t sec, - struct buffer_head *bh, s32 num_secs, bool sync) -{ - s32 ret = -EIO; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - - if ((sec + num_secs) > (p_fs->PBR_sector + p_fs->num_sectors) && - (p_fs->num_sectors > 0)) { - pr_err("[EXFAT] %s: out of range error! (sec = %llu, num_secs = %d)\n", - __func__, (unsigned long long)sec, num_secs); - fs_error(sb); - return ret; - } - if (!bh) { - pr_err("[EXFAT] %s: bh is NULL!\n", __func__); - fs_error(sb); - return ret; - } - - if (!p_fs->dev_ejected) { - ret = exfat_bdev_write(sb, sec, bh, num_secs, sync); - if (ret != 0) - p_fs->dev_ejected = 1; - } - - return ret; -} diff --git a/drivers/staging/exfat/exfat_nls.c b/drivers/staging/exfat/exfat_nls.c deleted file mode 100644 index 91e8b0c4dce7..000000000000 --- a/drivers/staging/exfat/exfat_nls.c +++ /dev/null @@ -1,212 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. - */ - -#include -#include -#include "exfat.h" - -static u16 bad_uni_chars[] = { - /* " * / : < > ? \ | */ - 0x0022, 0x002A, 0x002F, 0x003A, - 0x003C, 0x003E, 0x003F, 0x005C, 0x007C, - 0 -}; - -static int convert_ch_to_uni(struct nls_table *nls, u16 *uni, u8 *ch, - bool *lossy) -{ - int len; - - *uni = 0x0; - - if (ch[0] < 0x80) { - *uni = (u16)ch[0]; - return 1; - } - - len = nls->char2uni(ch, NLS_MAX_CHARSET_SIZE, uni); - if (len < 0) { - /* conversion failed */ - pr_info("%s: fail to use nls\n", __func__); - if (lossy) - *lossy = true; - *uni = (u16)'_'; - if (!strcmp(nls->charset, "utf8")) - return 1; - else - return 2; - } - - return len; -} - -static int convert_uni_to_ch(struct nls_table *nls, u8 *ch, u16 uni, - bool *lossy) -{ - int len; - - ch[0] = 0x0; - - if (uni < 0x0080) { - ch[0] = (u8)uni; - return 1; - } - - len = nls->uni2char(uni, ch, NLS_MAX_CHARSET_SIZE); - if (len < 0) { - /* conversion failed */ - pr_info("%s: fail to use nls\n", __func__); - if (lossy) - *lossy = true; - ch[0] = '_'; - return 1; - } - - return len; -} - -u16 nls_upper(struct super_block *sb, u16 a) -{ - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - - if (EXFAT_SB(sb)->options.casesensitive) - return a; - if (p_fs->vol_utbl && p_fs->vol_utbl[get_col_index(a)]) - return p_fs->vol_utbl[get_col_index(a)][get_row_index(a)]; - else - return a; -} - -static u16 *nls_wstrchr(u16 *str, u16 wchar) -{ - while (*str) { - if (*(str++) == wchar) - return str; - } - - return NULL; -} - -int nls_uniname_cmp(struct super_block *sb, u16 *a, u16 *b) -{ - int i; - - for (i = 0; i < MAX_NAME_LENGTH; i++, a++, b++) { - if (nls_upper(sb, *a) != nls_upper(sb, *b)) - return 1; - if (*a == 0x0) - return 0; - } - return 0; -} - -void nls_uniname_to_cstring(struct super_block *sb, u8 *p_cstring, - struct uni_name_t *p_uniname) -{ - int i, j, len; - u8 buf[MAX_CHARSET_SIZE]; - u16 *uniname = p_uniname->name; - struct nls_table *nls = EXFAT_SB(sb)->nls_io; - - if (!nls) { - len = utf16s_to_utf8s(uniname, MAX_NAME_LENGTH, - UTF16_HOST_ENDIAN, p_cstring, - MAX_NAME_LENGTH); - p_cstring[len] = 0; - return; - } - - i = 0; - while (i < (MAX_NAME_LENGTH - 1)) { - if (*uniname == (u16)'\0') - break; - - len = convert_uni_to_ch(nls, buf, *uniname, NULL); - - if (len > 1) { - for (j = 0; j < len; j++) - *p_cstring++ = (char)*(buf + j); - } else { /* len == 1 */ - *p_cstring++ = (char)*buf; - } - - uniname++; - i++; - } - - *p_cstring = '\0'; -} - -void nls_cstring_to_uniname(struct super_block *sb, - struct uni_name_t *p_uniname, u8 *p_cstring, - bool *p_lossy) -{ - int i, j; - bool lossy = false; - u8 *end_of_name; - u8 upname[MAX_NAME_LENGTH * 2]; - u16 *uniname = p_uniname->name; - struct nls_table *nls = EXFAT_SB(sb)->nls_io; - - /* strip all trailing spaces */ - end_of_name = p_cstring + strlen(p_cstring); - - while (*(--end_of_name) == ' ') { - if (end_of_name < p_cstring) - break; - } - *(++end_of_name) = '\0'; - - if (strcmp(p_cstring, ".") && strcmp(p_cstring, "..")) { - /* strip all trailing periods */ - while (*(--end_of_name) == '.') { - if (end_of_name < p_cstring) - break; - } - *(++end_of_name) = '\0'; - } - - if (*p_cstring == '\0') - lossy = true; - - if (!nls) { - i = utf8s_to_utf16s(p_cstring, MAX_NAME_LENGTH, - UTF16_HOST_ENDIAN, uniname, - MAX_NAME_LENGTH); - for (j = 0; j < i; j++) - SET16_A(upname + j * 2, nls_upper(sb, uniname[j])); - uniname[i] = '\0'; - } else { - i = 0; - j = 0; - while (j < (MAX_NAME_LENGTH - 1)) { - if (*(p_cstring + i) == '\0') - break; - - i += convert_ch_to_uni(nls, uniname, - (u8 *)(p_cstring + i), &lossy); - - if ((*uniname < 0x0020) || - nls_wstrchr(bad_uni_chars, *uniname)) - lossy = true; - - SET16_A(upname + j * 2, nls_upper(sb, *uniname)); - - uniname++; - j++; - } - - if (*(p_cstring + i) != '\0') - lossy = true; - *uniname = (u16)'\0'; - } - - p_uniname->name_len = j; - p_uniname->name_hash = calc_checksum_2byte(upname, j << 1, 0, - CS_DEFAULT); - - if (p_lossy) - *p_lossy = lossy; -} diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c deleted file mode 100644 index af97f5a83c5b..000000000000 --- a/drivers/staging/exfat/exfat_super.c +++ /dev/null @@ -1,3296 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define EXFAT_VERSION "1.3.0" - -#include "exfat.h" - -static struct kmem_cache *exfat_inode_cachep; - -static int exfat_default_codepage = CONFIG_STAGING_EXFAT_DEFAULT_CODEPAGE; -static char exfat_default_iocharset[] = CONFIG_STAGING_EXFAT_DEFAULT_IOCHARSET; - -#define INC_IVERSION(x) (inode_inc_iversion(x)) -#define GET_IVERSION(x) (inode_peek_iversion_raw(x)) -#define SET_IVERSION(x, y) (inode_set_iversion(x, y)) - -static struct inode *exfat_iget(struct super_block *sb, loff_t i_pos); -static int exfat_sync_inode(struct inode *inode); -static struct inode *exfat_build_inode(struct super_block *sb, - struct file_id_t *fid, loff_t i_pos); -static int exfat_write_inode(struct inode *inode, - struct writeback_control *wbc); -static void exfat_write_super(struct super_block *sb); - -#define UNIX_SECS_1980 315532800L -#define UNIX_SECS_2108 4354819200L - -/* Convert a FAT time/date pair to a UNIX date (seconds since 1 1 70). */ -static void exfat_time_fat2unix(struct timespec64 *ts, struct date_time_t *tp) -{ - ts->tv_sec = mktime64(tp->year + 1980, tp->month + 1, tp->day, - tp->hour, tp->minute, tp->second); - - ts->tv_nsec = tp->millisecond * NSEC_PER_MSEC; -} - -/* Convert linear UNIX date to a FAT time/date pair. */ -static void exfat_time_unix2fat(struct timespec64 *ts, struct date_time_t *tp) -{ - time64_t second = ts->tv_sec; - struct tm tm; - - time64_to_tm(second, 0, &tm); - - if (second < UNIX_SECS_1980) { - tp->millisecond = 0; - tp->second = 0; - tp->minute = 0; - tp->hour = 0; - tp->day = 1; - tp->month = 1; - tp->year = 0; - return; - } - - if (second >= UNIX_SECS_2108) { - tp->millisecond = 999; - tp->second = 59; - tp->minute = 59; - tp->hour = 23; - tp->day = 31; - tp->month = 12; - tp->year = 127; - return; - } - - tp->millisecond = ts->tv_nsec / NSEC_PER_MSEC; - tp->second = tm.tm_sec; - tp->minute = tm.tm_min; - tp->hour = tm.tm_hour; - tp->day = tm.tm_mday; - tp->month = tm.tm_mon + 1; - tp->year = tm.tm_year + 1900 - 1980; -} - -struct timestamp_t *tm_current(struct timestamp_t *tp) -{ - time64_t second = ktime_get_real_seconds(); - struct tm tm; - - time64_to_tm(second, 0, &tm); - - if (second < UNIX_SECS_1980) { - tp->sec = 0; - tp->min = 0; - tp->hour = 0; - tp->day = 1; - tp->mon = 1; - tp->year = 0; - return tp; - } - - if (second >= UNIX_SECS_2108) { - tp->sec = 59; - tp->min = 59; - tp->hour = 23; - tp->day = 31; - tp->mon = 12; - tp->year = 127; - return tp; - } - - tp->sec = tm.tm_sec; - tp->min = tm.tm_min; - tp->hour = tm.tm_hour; - tp->day = tm.tm_mday; - tp->mon = tm.tm_mon + 1; - tp->year = tm.tm_year + 1900 - 1980; - - return tp; -} - -static void __lock_super(struct super_block *sb) -{ - struct exfat_sb_info *sbi = EXFAT_SB(sb); - - mutex_lock(&sbi->s_lock); -} - -static void __unlock_super(struct super_block *sb) -{ - struct exfat_sb_info *sbi = EXFAT_SB(sb); - - mutex_unlock(&sbi->s_lock); -} - -static int __is_sb_dirty(struct super_block *sb) -{ - struct exfat_sb_info *sbi = EXFAT_SB(sb); - - return sbi->s_dirt; -} - -static void __set_sb_clean(struct super_block *sb) -{ - struct exfat_sb_info *sbi = EXFAT_SB(sb); - - sbi->s_dirt = 0; -} - -static int __exfat_revalidate(struct dentry *dentry) -{ - return 0; -} - -static int exfat_revalidate(struct dentry *dentry, unsigned int flags) -{ - if (flags & LOOKUP_RCU) - return -ECHILD; - - if (dentry->d_inode) - return 1; - return __exfat_revalidate(dentry); -} - -static int exfat_revalidate_ci(struct dentry *dentry, unsigned int flags) -{ - if (flags & LOOKUP_RCU) - return -ECHILD; - - if (dentry->d_inode) - return 1; - - if (!flags) - return 0; - - if (flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET)) - return 0; - - return __exfat_revalidate(dentry); -} - -static unsigned int __exfat_striptail_len(unsigned int len, const char *name) -{ - while (len && name[len - 1] == '.') - len--; - return len; -} - -static unsigned int exfat_striptail_len(const struct qstr *qstr) -{ - return __exfat_striptail_len(qstr->len, qstr->name); -} - -static int exfat_d_hash(const struct dentry *dentry, struct qstr *qstr) -{ - qstr->hash = full_name_hash(dentry, qstr->name, - exfat_striptail_len(qstr)); - return 0; -} - -static int exfat_d_hashi(const struct dentry *dentry, struct qstr *qstr) -{ - struct super_block *sb = dentry->d_sb; - const unsigned char *name; - unsigned int len; - unsigned long hash; - - name = qstr->name; - len = exfat_striptail_len(qstr); - - hash = init_name_hash(dentry); - while (len--) - hash = partial_name_hash(nls_upper(sb, *name++), hash); - qstr->hash = end_name_hash(hash); - - return 0; -} - -static int exfat_cmpi(const struct dentry *dentry, unsigned int len, - const char *str, const struct qstr *name) -{ - struct nls_table *t = EXFAT_SB(dentry->d_sb)->nls_io; - unsigned int alen, blen; - - alen = exfat_striptail_len(name); - blen = __exfat_striptail_len(len, str); - if (alen == blen) { - if (!t) { - if (strncasecmp(name->name, str, alen) == 0) - return 0; - } else { - if (nls_strnicmp(t, name->name, str, alen) == 0) - return 0; - } - } - return 1; -} - -static int exfat_cmp(const struct dentry *dentry, unsigned int len, - const char *str, const struct qstr *name) -{ - unsigned int alen, blen; - - alen = exfat_striptail_len(name); - blen = __exfat_striptail_len(len, str); - if (alen == blen) { - if (strncmp(name->name, str, alen) == 0) - return 0; - } - return 1; -} - -static const struct dentry_operations exfat_ci_dentry_ops = { - .d_revalidate = exfat_revalidate_ci, - .d_hash = exfat_d_hashi, - .d_compare = exfat_cmpi, -}; - -static const struct dentry_operations exfat_dentry_ops = { - .d_revalidate = exfat_revalidate, - .d_hash = exfat_d_hash, - .d_compare = exfat_cmp, -}; - -static DEFINE_MUTEX(z_mutex); - -static inline void fs_sync(struct super_block *sb, bool do_sync) -{ - if (do_sync) - exfat_bdev_sync(sb); -} - -/* - * If ->i_mode can't hold S_IWUGO (i.e. ATTR_RO), we use ->i_attrs to - * save ATTR_RO instead of ->i_mode. - * - * If it's directory and !sbi->options.rodir, ATTR_RO isn't read-only - * bit, it's just used as flag for app. - */ -static inline int exfat_mode_can_hold_ro(struct inode *inode) -{ - struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb); - - if (S_ISDIR(inode->i_mode)) - return 0; - - if ((~sbi->options.fs_fmask) & 0222) - return 1; - return 0; -} - -/* Convert attribute bits and a mask to the UNIX mode. */ -static inline mode_t exfat_make_mode(struct exfat_sb_info *sbi, u32 attr, - mode_t mode) -{ - if ((attr & ATTR_READONLY) && !(attr & ATTR_SUBDIR)) - mode &= ~0222; - - if (attr & ATTR_SUBDIR) - return (mode & ~sbi->options.fs_dmask) | S_IFDIR; - else - return (mode & ~sbi->options.fs_fmask) | S_IFREG; -} - -/* Return the FAT attribute byte for this inode */ -static inline u32 exfat_make_attr(struct inode *inode) -{ - if (exfat_mode_can_hold_ro(inode) && !(inode->i_mode & 0222)) - return (EXFAT_I(inode)->fid.attr) | ATTR_READONLY; - else - return EXFAT_I(inode)->fid.attr; -} - -static inline void exfat_save_attr(struct inode *inode, u32 attr) -{ - if (exfat_mode_can_hold_ro(inode)) - EXFAT_I(inode)->fid.attr = attr & ATTR_RWMASK; - else - EXFAT_I(inode)->fid.attr = attr & (ATTR_RWMASK | ATTR_READONLY); -} - -static int ffsMountVol(struct super_block *sb) -{ - int i, ret; - struct pbr_sector_t *p_pbr; - struct buffer_head *tmp_bh = NULL; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); - - pr_info("[EXFAT] trying to mount...\n"); - - mutex_lock(&z_mutex); - - exfat_buf_init(sb); - - mutex_init(&p_fs->v_mutex); - p_fs->dev_ejected = 0; - - /* open the block device */ - exfat_bdev_open(sb); - - if (p_bd->sector_size < sb->s_blocksize) { - pr_info("EXFAT: mount failed - sector size %d less than blocksize %ld\n", - p_bd->sector_size, sb->s_blocksize); - ret = -EINVAL; - goto out; - } - if (p_bd->sector_size > sb->s_blocksize) - sb_set_blocksize(sb, p_bd->sector_size); - - /* read Sector 0 */ - if (sector_read(sb, 0, &tmp_bh, 1) != 0) { - ret = -EIO; - goto out; - } - - p_fs->PBR_sector = 0; - - p_pbr = (struct pbr_sector_t *)tmp_bh->b_data; - - /* check the validity of PBR */ - if (GET16_A(p_pbr->signature) != PBR_SIGNATURE) { - brelse(tmp_bh); - exfat_bdev_close(sb); - ret = -EFSCORRUPTED; - goto out; - } - - /* fill fs_struct */ - for (i = 0; i < 53; i++) - if (p_pbr->bpb[i]) - break; - - if (i < 53) { - /* Not sure how we'd get here, but complain if it does */ - ret = -EINVAL; - pr_info("EXFAT: Attempted to mount VFAT filesystem\n"); - goto out; - } else { - ret = exfat_mount(sb, p_pbr); - } - - brelse(tmp_bh); - - if (ret) { - exfat_bdev_close(sb); - goto out; - } - - ret = load_alloc_bitmap(sb); - if (ret) { - exfat_bdev_close(sb); - goto out; - } - ret = load_upcase_table(sb); - if (ret) { - free_alloc_bitmap(sb); - exfat_bdev_close(sb); - goto out; - } - - if (p_fs->dev_ejected) { - free_upcase_table(sb); - free_alloc_bitmap(sb); - exfat_bdev_close(sb); - ret = -EIO; - goto out; - } - - pr_info("[EXFAT] mounted successfully\n"); - -out: - mutex_unlock(&z_mutex); - - return ret; -} - -static int ffsUmountVol(struct super_block *sb) -{ - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - int err = 0; - - pr_info("[EXFAT] trying to unmount...\n"); - - mutex_lock(&z_mutex); - - /* acquire the lock for file system critical section */ - mutex_lock(&p_fs->v_mutex); - - fs_sync(sb, false); - fs_set_vol_flags(sb, VOL_CLEAN); - - free_upcase_table(sb); - free_alloc_bitmap(sb); - - exfat_fat_release_all(sb); - exfat_buf_release_all(sb); - - /* close the block device */ - exfat_bdev_close(sb); - - if (p_fs->dev_ejected) { - pr_info("[EXFAT] unmounted with media errors. Device is already ejected.\n"); - err = -EIO; - } - - exfat_buf_shutdown(sb); - - /* release the lock for file system critical section */ - mutex_unlock(&p_fs->v_mutex); - mutex_unlock(&z_mutex); - - pr_info("[EXFAT] unmounted successfully\n"); - - return err; -} - -static int ffsGetVolInfo(struct super_block *sb, struct vol_info_t *info) -{ - int err = 0; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - - /* check the validity of pointer parameters */ - if (!info) - return -EINVAL; - - /* acquire the lock for file system critical section */ - mutex_lock(&p_fs->v_mutex); - - if (p_fs->used_clusters == UINT_MAX) - p_fs->used_clusters = exfat_count_used_clusters(sb); - - info->FatType = EXFAT; - info->ClusterSize = p_fs->cluster_size; - info->NumClusters = p_fs->num_clusters - 2; /* clu 0 & 1 */ - info->UsedClusters = p_fs->used_clusters; - info->FreeClusters = info->NumClusters - info->UsedClusters; - - if (p_fs->dev_ejected) - err = -EIO; - - /* release the lock for file system critical section */ - mutex_unlock(&p_fs->v_mutex); - - return err; -} - -static int ffsSyncVol(struct super_block *sb, bool do_sync) -{ - int err = 0; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - - /* acquire the lock for file system critical section */ - mutex_lock(&p_fs->v_mutex); - - /* synchronize the file system */ - fs_sync(sb, do_sync); - fs_set_vol_flags(sb, VOL_CLEAN); - - if (p_fs->dev_ejected) - err = -EIO; - - /* release the lock for file system critical section */ - mutex_unlock(&p_fs->v_mutex); - - return err; -} - -/*----------------------------------------------------------------------*/ -/* File Operation Functions */ -/*----------------------------------------------------------------------*/ - -static int ffsLookupFile(struct inode *inode, char *path, struct file_id_t *fid) -{ - int ret, dentry, num_entries; - struct chain_t dir; - struct uni_name_t uni_name; - struct dentry_t *ep, *ep2; - struct entry_set_cache_t *es = NULL; - struct super_block *sb = inode->i_sb; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - - pr_debug("%s entered\n", __func__); - - /* check the validity of pointer parameters */ - if (!fid || !path || (*path == '\0')) - return -EINVAL; - - /* acquire the lock for file system critical section */ - mutex_lock(&p_fs->v_mutex); - - /* check the validity of directory name in the given pathname */ - ret = resolve_path(inode, path, &dir, &uni_name); - if (ret) - goto out; - - ret = get_num_entries(sb, &dir, &uni_name, &num_entries); - if (ret) - goto out; - - /* search the file name for directories */ - dentry = exfat_find_dir_entry(sb, &dir, &uni_name, num_entries, - TYPE_ALL); - if (dentry < -1) { - ret = -ENOENT; - goto out; - } - - fid->dir.dir = dir.dir; - fid->dir.size = dir.size; - fid->dir.flags = dir.flags; - fid->entry = dentry; - - if (dentry == -1) { - fid->type = TYPE_DIR; - fid->rwoffset = 0; - fid->hint_last_off = -1; - - fid->attr = ATTR_SUBDIR; - fid->flags = 0x01; - fid->size = 0; - fid->start_clu = p_fs->root_dir; - } else { - es = get_entry_set_in_dir(sb, &dir, dentry, - ES_2_ENTRIES, &ep); - if (!es) { - ret = -ENOENT; - goto out; - } - ep2 = ep + 1; - - fid->type = exfat_get_entry_type(ep); - fid->rwoffset = 0; - fid->hint_last_off = -1; - fid->attr = exfat_get_entry_attr(ep); - - fid->size = exfat_get_entry_size(ep2); - if ((fid->type == TYPE_FILE) && (fid->size == 0)) { - fid->flags = 0x03; - fid->start_clu = CLUSTER_32(~0); - } else { - fid->flags = exfat_get_entry_flag(ep2); - fid->start_clu = exfat_get_entry_clu0(ep2); - } - - release_entry_set(es); - } - - if (p_fs->dev_ejected) - ret = -EIO; -out: - /* release the lock for file system critical section */ - mutex_unlock(&p_fs->v_mutex); - - return ret; -} - -static int ffsCreateFile(struct inode *inode, char *path, struct file_id_t *fid) -{ - struct chain_t dir; - struct uni_name_t uni_name; - struct super_block *sb = inode->i_sb; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - int ret = 0; - - /* check the validity of pointer parameters */ - if (!fid || !path || (*path == '\0')) - return -EINVAL; - - /* acquire the lock for file system critical section */ - mutex_lock(&p_fs->v_mutex); - - /* check the validity of directory name in the given pathname */ - ret = resolve_path(inode, path, &dir, &uni_name); - if (ret) - goto out; - - fs_set_vol_flags(sb, VOL_DIRTY); - - /* create a new file */ - ret = create_file(inode, &dir, &uni_name, fid); - -#ifndef CONFIG_STAGING_EXFAT_DELAYED_SYNC - fs_sync(sb, true); - fs_set_vol_flags(sb, VOL_CLEAN); -#endif - - if (p_fs->dev_ejected) - ret = -EIO; - -out: - /* release the lock for file system critical section */ - mutex_unlock(&p_fs->v_mutex); - - return ret; -} - -static int ffsTruncateFile(struct inode *inode, u64 old_size, u64 new_size) -{ - s32 num_clusters; - u32 last_clu = CLUSTER_32(0); - int ret = 0; - struct chain_t clu; - struct timestamp_t tm; - struct dentry_t *ep, *ep2; - struct super_block *sb = inode->i_sb; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - struct file_id_t *fid = &(EXFAT_I(inode)->fid); - struct entry_set_cache_t *es = NULL; - - pr_debug("%s entered (inode %p size %llu)\n", __func__, inode, - new_size); - - /* acquire the lock for file system critical section */ - mutex_lock(&p_fs->v_mutex); - - /* check if the given file ID is opened */ - if (fid->type != TYPE_FILE) { - ret = -EPERM; - goto out; - } - - if (fid->size != old_size) { - pr_err("[EXFAT] truncate : can't skip it because of size-mismatch(old:%lld->fid:%lld).\n", - old_size, fid->size); - } - - if (old_size <= new_size) { - ret = 0; - goto out; - } - - fs_set_vol_flags(sb, VOL_DIRTY); - - clu.dir = fid->start_clu; - clu.size = (s32)((old_size - 1) >> p_fs->cluster_size_bits) + 1; - clu.flags = fid->flags; - - if (new_size > 0) { - num_clusters = (s32)((new_size - 1) >> - p_fs->cluster_size_bits) + 1; - - if (clu.flags == 0x03) { - clu.dir += num_clusters; - } else { - while (num_clusters > 0) { - last_clu = clu.dir; - if (exfat_fat_read(sb, clu.dir, &clu.dir) == -1) { - ret = -EIO; - goto out; - } - num_clusters--; - } - } - - clu.size -= num_clusters; - } - - fid->size = new_size; - fid->attr |= ATTR_ARCHIVE; - if (new_size == 0) { - fid->flags = 0x03; - fid->start_clu = CLUSTER_32(~0); - } - - /* (1) update the directory entry */ - es = get_entry_set_in_dir(sb, &fid->dir, fid->entry, - ES_ALL_ENTRIES, &ep); - if (!es) { - ret = -ENOENT; - goto out; - } - ep2 = ep + 1; - - exfat_set_entry_time(ep, tm_current(&tm), TM_MODIFY); - exfat_set_entry_attr(ep, fid->attr); - - exfat_set_entry_size(ep2, new_size); - if (new_size == 0) { - exfat_set_entry_flag(ep2, 0x01); - exfat_set_entry_clu0(ep2, CLUSTER_32(0)); - } - - update_dir_checksum_with_entry_set(sb, es); - release_entry_set(es); - - /* (2) cut off from the FAT chain */ - if (last_clu != CLUSTER_32(0)) { - if (fid->flags == 0x01) - exfat_fat_write(sb, last_clu, CLUSTER_32(~0)); - } - - /* (3) free the clusters */ - exfat_free_cluster(sb, &clu, 0); - - /* hint information */ - fid->hint_last_off = -1; - if (fid->rwoffset > fid->size) - fid->rwoffset = fid->size; - -#ifndef CONFIG_STAGING_EXFAT_DELAYED_SYNC - fs_sync(sb, true); - fs_set_vol_flags(sb, VOL_CLEAN); -#endif - - if (p_fs->dev_ejected) - ret = -EIO; - -out: - pr_debug("%s exited (%d)\n", __func__, ret); - /* release the lock for file system critical section */ - mutex_unlock(&p_fs->v_mutex); - - return ret; -} - -static void update_parent_info(struct file_id_t *fid, - struct inode *parent_inode) -{ - struct fs_info_t *p_fs = &(EXFAT_SB(parent_inode->i_sb)->fs_info); - struct file_id_t *parent_fid = &(EXFAT_I(parent_inode)->fid); - - if (unlikely((parent_fid->flags != fid->dir.flags) || - (parent_fid->size != - (fid->dir.size << p_fs->cluster_size_bits)) || - (parent_fid->start_clu != fid->dir.dir))) { - fid->dir.dir = parent_fid->start_clu; - fid->dir.flags = parent_fid->flags; - fid->dir.size = ((parent_fid->size + (p_fs->cluster_size - 1)) - >> p_fs->cluster_size_bits); - } -} - -static int ffsMoveFile(struct inode *old_parent_inode, struct file_id_t *fid, - struct inode *new_parent_inode, struct dentry *new_dentry) -{ - s32 ret; - s32 dentry; - struct chain_t olddir, newdir; - struct chain_t *p_dir = NULL; - struct uni_name_t uni_name; - struct dentry_t *ep; - struct super_block *sb = old_parent_inode->i_sb; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - u8 *new_path = (u8 *)new_dentry->d_name.name; - struct inode *new_inode = new_dentry->d_inode; - int num_entries; - struct file_id_t *new_fid = NULL; - s32 new_entry = 0; - - /* check the validity of the given file id */ - if (!fid) - return -EINVAL; - - /* check the validity of pointer parameters */ - if (!new_path || (*new_path == '\0')) - return -EINVAL; - - /* acquire the lock for file system critical section */ - mutex_lock(&p_fs->v_mutex); - - update_parent_info(fid, old_parent_inode); - - olddir.dir = fid->dir.dir; - olddir.size = fid->dir.size; - olddir.flags = fid->dir.flags; - - dentry = fid->entry; - - ep = get_entry_in_dir(sb, &olddir, dentry, NULL); - if (!ep) { - ret = -ENOENT; - goto out2; - } - - if (exfat_get_entry_attr(ep) & ATTR_READONLY) { - ret = -EPERM; - goto out2; - } - - /* check whether new dir is existing directory and empty */ - if (new_inode) { - u32 entry_type; - - ret = -ENOENT; - new_fid = &EXFAT_I(new_inode)->fid; - - update_parent_info(new_fid, new_parent_inode); - - p_dir = &new_fid->dir; - new_entry = new_fid->entry; - ep = get_entry_in_dir(sb, p_dir, new_entry, NULL); - if (!ep) - goto out; - - entry_type = exfat_get_entry_type(ep); - - if (entry_type == TYPE_DIR) { - struct chain_t new_clu; - - new_clu.dir = new_fid->start_clu; - new_clu.size = (s32)((new_fid->size - 1) >> - p_fs->cluster_size_bits) + 1; - new_clu.flags = new_fid->flags; - - if (!is_dir_empty(sb, &new_clu)) { - ret = -EEXIST; - goto out; - } - } - } - - /* check the validity of directory name in the given new pathname */ - ret = resolve_path(new_parent_inode, new_path, &newdir, &uni_name); - if (ret) - goto out2; - - fs_set_vol_flags(sb, VOL_DIRTY); - - if (olddir.dir == newdir.dir) - ret = exfat_rename_file(new_parent_inode, &olddir, dentry, - &uni_name, fid); - else - ret = move_file(new_parent_inode, &olddir, dentry, &newdir, - &uni_name, fid); - - if ((ret == 0) && new_inode) { - /* delete entries of new_dir */ - ep = get_entry_in_dir(sb, p_dir, new_entry, NULL); - if (!ep) - goto out; - - num_entries = exfat_count_ext_entries(sb, p_dir, - new_entry, ep); - if (num_entries < 0) - goto out; - exfat_delete_dir_entry(sb, p_dir, new_entry, 0, - num_entries + 1); - } -out: -#ifndef CONFIG_STAGING_EXFAT_DELAYED_SYNC - fs_sync(sb, true); - fs_set_vol_flags(sb, VOL_CLEAN); -#endif - - if (p_fs->dev_ejected) - ret = -EIO; -out2: - /* release the lock for file system critical section */ - mutex_unlock(&p_fs->v_mutex); - - return ret; -} - -static int ffsRemoveFile(struct inode *inode, struct file_id_t *fid) -{ - s32 dentry; - int ret = 0; - struct chain_t dir, clu_to_free; - struct dentry_t *ep; - struct super_block *sb = inode->i_sb; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - - /* check the validity of the given file id */ - if (!fid) - return -EINVAL; - - /* acquire the lock for file system critical section */ - mutex_lock(&p_fs->v_mutex); - - dir.dir = fid->dir.dir; - dir.size = fid->dir.size; - dir.flags = fid->dir.flags; - - dentry = fid->entry; - - ep = get_entry_in_dir(sb, &dir, dentry, NULL); - if (!ep) { - ret = -ENOENT; - goto out; - } - - if (exfat_get_entry_attr(ep) & ATTR_READONLY) { - ret = -EPERM; - goto out; - } - fs_set_vol_flags(sb, VOL_DIRTY); - - /* (1) update the directory entry */ - remove_file(inode, &dir, dentry); - - clu_to_free.dir = fid->start_clu; - clu_to_free.size = (s32)((fid->size - 1) >> p_fs->cluster_size_bits) + 1; - clu_to_free.flags = fid->flags; - - /* (2) free the clusters */ - exfat_free_cluster(sb, &clu_to_free, 0); - - fid->size = 0; - fid->start_clu = CLUSTER_32(~0); - fid->flags = 0x03; - -#ifndef CONFIG_STAGING_EXFAT_DELAYED_SYNC - fs_sync(sb, true); - fs_set_vol_flags(sb, VOL_CLEAN); -#endif - - if (p_fs->dev_ejected) - ret = -EIO; -out: - /* release the lock for file system critical section */ - mutex_unlock(&p_fs->v_mutex); - - return ret; -} - -static int ffsReadStat(struct inode *inode, struct dir_entry_t *info) -{ - s32 count; - int ret = 0; - struct chain_t dir; - struct uni_name_t uni_name; - struct timestamp_t tm; - struct dentry_t *ep, *ep2; - struct super_block *sb = inode->i_sb; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - struct file_id_t *fid = &(EXFAT_I(inode)->fid); - struct entry_set_cache_t *es = NULL; - u8 is_dir = (fid->type == TYPE_DIR) ? 1 : 0; - - pr_debug("%s entered\n", __func__); - - /* acquire the lock for file system critical section */ - mutex_lock(&p_fs->v_mutex); - - if (is_dir) { - if ((fid->dir.dir == p_fs->root_dir) && - (fid->entry == -1)) { - info->attr = ATTR_SUBDIR; - memset((char *)&info->create_timestamp, 0, - sizeof(struct date_time_t)); - memset((char *)&info->modify_timestamp, 0, - sizeof(struct date_time_t)); - memset((char *)&info->access_timestamp, 0, - sizeof(struct date_time_t)); - strcpy(info->name, "."); - - dir.dir = p_fs->root_dir; - dir.flags = 0x01; - - if (p_fs->root_dir == CLUSTER_32(0)) { - /* FAT16 root_dir */ - info->Size = p_fs->dentries_in_root << - DENTRY_SIZE_BITS; - } else { - info->Size = count_num_clusters(sb, &dir) << - p_fs->cluster_size_bits; - } - - count = count_dir_entries(sb, &dir); - if (count < 0) { - ret = count; /* propagate error upward */ - goto out; - } - info->num_subdirs = count; - - if (p_fs->dev_ejected) - ret = -EIO; - goto out; - } - } - - /* get the directory entry of given file or directory */ - es = get_entry_set_in_dir(sb, &fid->dir, fid->entry, - ES_2_ENTRIES, &ep); - if (!es) { - ret = -ENOENT; - goto out; - } - ep2 = ep + 1; - - /* set FILE_INFO structure using the acquired struct dentry_t */ - info->attr = exfat_get_entry_attr(ep); - - exfat_get_entry_time(ep, &tm, TM_CREATE); - info->create_timestamp.year = tm.year; - info->create_timestamp.month = tm.mon; - info->create_timestamp.day = tm.day; - info->create_timestamp.hour = tm.hour; - info->create_timestamp.minute = tm.min; - info->create_timestamp.second = tm.sec; - info->create_timestamp.millisecond = 0; - - exfat_get_entry_time(ep, &tm, TM_MODIFY); - info->modify_timestamp.year = tm.year; - info->modify_timestamp.month = tm.mon; - info->modify_timestamp.day = tm.day; - info->modify_timestamp.hour = tm.hour; - info->modify_timestamp.minute = tm.min; - info->modify_timestamp.second = tm.sec; - info->modify_timestamp.millisecond = 0; - - memset((char *)&info->access_timestamp, 0, sizeof(struct date_time_t)); - - *uni_name.name = 0x0; - /* XXX this is very bad for exfat cuz name is already included in es. - * API should be revised - */ - exfat_get_uni_name_from_ext_entry(sb, &fid->dir, fid->entry, - uni_name.name); - nls_uniname_to_cstring(sb, info->name, &uni_name); - - info->num_subdirs = 2; - - info->Size = exfat_get_entry_size(ep2); - - release_entry_set(es); - - if (is_dir) { - dir.dir = fid->start_clu; - dir.flags = 0x01; - - if (info->Size == 0) - info->Size = (u64)count_num_clusters(sb, &dir) << - p_fs->cluster_size_bits; - - count = count_dir_entries(sb, &dir); - if (count < 0) { - ret = count; /* propagate error upward */ - goto out; - } - info->num_subdirs += count; - } - - if (p_fs->dev_ejected) - ret = -EIO; - -out: - /* release the lock for file system critical section */ - mutex_unlock(&p_fs->v_mutex); - - pr_debug("%s exited successfully\n", __func__); - return ret; -} - -static int ffsWriteStat(struct inode *inode, struct dir_entry_t *info) -{ - int ret = 0; - struct timestamp_t tm; - struct dentry_t *ep, *ep2; - struct entry_set_cache_t *es = NULL; - struct super_block *sb = inode->i_sb; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - struct file_id_t *fid = &(EXFAT_I(inode)->fid); - u8 is_dir = (fid->type == TYPE_DIR) ? 1 : 0; - - pr_debug("%s entered (inode %p info %p\n", __func__, inode, info); - - /* acquire the lock for file system critical section */ - mutex_lock(&p_fs->v_mutex); - - if (is_dir) { - if ((fid->dir.dir == p_fs->root_dir) && - (fid->entry == -1)) { - if (p_fs->dev_ejected) - ret = -EIO; - ret = 0; - goto out; - } - } - - fs_set_vol_flags(sb, VOL_DIRTY); - - /* get the directory entry of given file or directory */ - es = get_entry_set_in_dir(sb, &fid->dir, fid->entry, - ES_ALL_ENTRIES, &ep); - if (!es) { - ret = -ENOENT; - goto out; - } - ep2 = ep + 1; - - exfat_set_entry_attr(ep, info->attr); - - /* set FILE_INFO structure using the acquired struct dentry_t */ - tm.sec = info->create_timestamp.second; - tm.min = info->create_timestamp.minute; - tm.hour = info->create_timestamp.hour; - tm.day = info->create_timestamp.day; - tm.mon = info->create_timestamp.month; - tm.year = info->create_timestamp.year; - exfat_set_entry_time(ep, &tm, TM_CREATE); - - tm.sec = info->modify_timestamp.second; - tm.min = info->modify_timestamp.minute; - tm.hour = info->modify_timestamp.hour; - tm.day = info->modify_timestamp.day; - tm.mon = info->modify_timestamp.month; - tm.year = info->modify_timestamp.year; - exfat_set_entry_time(ep, &tm, TM_MODIFY); - - exfat_set_entry_size(ep2, info->Size); - - update_dir_checksum_with_entry_set(sb, es); - release_entry_set(es); - - if (p_fs->dev_ejected) - ret = -EIO; - -out: - /* release the lock for file system critical section */ - mutex_unlock(&p_fs->v_mutex); - - pr_debug("%s exited (%d)\n", __func__, ret); - - return ret; -} - -static int ffsMapCluster(struct inode *inode, s32 clu_offset, u32 *clu) -{ - s32 num_clusters, num_alloced; - bool modified = false; - u32 last_clu; - int ret = 0; - struct chain_t new_clu; - struct dentry_t *ep; - struct entry_set_cache_t *es = NULL; - struct super_block *sb = inode->i_sb; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - struct file_id_t *fid = &(EXFAT_I(inode)->fid); - - /* check the validity of pointer parameters */ - if (!clu) - return -EINVAL; - - /* acquire the lock for file system critical section */ - mutex_lock(&p_fs->v_mutex); - - fid->rwoffset = (s64)(clu_offset) << p_fs->cluster_size_bits; - - if (EXFAT_I(inode)->mmu_private == 0) - num_clusters = 0; - else - num_clusters = (s32)((EXFAT_I(inode)->mmu_private - 1) >> - p_fs->cluster_size_bits) + 1; - - *clu = last_clu = fid->start_clu; - - if (fid->flags == 0x03) { - if ((clu_offset > 0) && (*clu != CLUSTER_32(~0))) { - last_clu += clu_offset - 1; - - if (clu_offset == num_clusters) - *clu = CLUSTER_32(~0); - else - *clu += clu_offset; - } - } else { - /* hint information */ - if ((clu_offset > 0) && (fid->hint_last_off > 0) && - (clu_offset >= fid->hint_last_off)) { - clu_offset -= fid->hint_last_off; - *clu = fid->hint_last_clu; - } - - while ((clu_offset > 0) && (*clu != CLUSTER_32(~0))) { - last_clu = *clu; - if (exfat_fat_read(sb, *clu, clu) == -1) { - ret = -EIO; - goto out; - } - clu_offset--; - } - } - - if (*clu == CLUSTER_32(~0)) { - fs_set_vol_flags(sb, VOL_DIRTY); - - new_clu.dir = (last_clu == CLUSTER_32(~0)) ? CLUSTER_32(~0) : - last_clu + 1; - new_clu.size = 0; - new_clu.flags = fid->flags; - - /* (1) allocate a cluster */ - num_alloced = exfat_alloc_cluster(sb, 1, &new_clu); - if (num_alloced < 0) { - ret = -EIO; - goto out; - } else if (num_alloced == 0) { - ret = -ENOSPC; - goto out; - } - - /* (2) append to the FAT chain */ - if (last_clu == CLUSTER_32(~0)) { - if (new_clu.flags == 0x01) - fid->flags = 0x01; - fid->start_clu = new_clu.dir; - modified = true; - } else { - if (new_clu.flags != fid->flags) { - exfat_chain_cont_cluster(sb, fid->start_clu, - num_clusters); - fid->flags = 0x01; - modified = true; - } - if (new_clu.flags == 0x01) - exfat_fat_write(sb, last_clu, new_clu.dir); - } - - num_clusters += num_alloced; - *clu = new_clu.dir; - - es = get_entry_set_in_dir(sb, &fid->dir, fid->entry, - ES_ALL_ENTRIES, &ep); - if (!es) { - ret = -ENOENT; - goto out; - } - /* get stream entry */ - ep++; - - /* (3) update directory entry */ - if (modified) { - exfat_set_entry_flag(ep, fid->flags); - exfat_set_entry_clu0(ep, fid->start_clu); - } - - update_dir_checksum_with_entry_set(sb, es); - release_entry_set(es); - - /* add number of new blocks to inode */ - inode->i_blocks += num_alloced << (p_fs->cluster_size_bits - 9); - } - - /* hint information */ - fid->hint_last_off = (s32)(fid->rwoffset >> p_fs->cluster_size_bits); - fid->hint_last_clu = *clu; - - if (p_fs->dev_ejected) - ret = -EIO; - -out: - /* release the lock for file system critical section */ - mutex_unlock(&p_fs->v_mutex); - - return ret; -} - -/*----------------------------------------------------------------------*/ -/* Directory Operation Functions */ -/*----------------------------------------------------------------------*/ - -static int ffsCreateDir(struct inode *inode, char *path, struct file_id_t *fid) -{ - int ret = 0; - struct chain_t dir; - struct uni_name_t uni_name; - struct super_block *sb = inode->i_sb; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - - pr_debug("%s entered\n", __func__); - - /* check the validity of pointer parameters */ - if (!fid || !path || (*path == '\0')) - return -EINVAL; - - /* acquire the lock for file system critical section */ - mutex_lock(&p_fs->v_mutex); - - /* check the validity of directory name in the given old pathname */ - ret = resolve_path(inode, path, &dir, &uni_name); - if (ret) - goto out; - - fs_set_vol_flags(sb, VOL_DIRTY); - - ret = create_dir(inode, &dir, &uni_name, fid); - -#ifndef CONFIG_STAGING_EXFAT_DELAYED_SYNC - fs_sync(sb, true); - fs_set_vol_flags(sb, VOL_CLEAN); -#endif - - if (p_fs->dev_ejected) - ret = -EIO; -out: - /* release the lock for file system critical section */ - mutex_unlock(&p_fs->v_mutex); - - return ret; -} - -static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry) -{ - int i, dentry, clu_offset; - int ret = 0; - s32 dentries_per_clu, dentries_per_clu_bits = 0; - u32 type; - sector_t sector; - struct chain_t dir, clu; - struct uni_name_t uni_name; - struct timestamp_t tm; - struct dentry_t *ep; - struct super_block *sb = inode->i_sb; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - struct file_id_t *fid = &(EXFAT_I(inode)->fid); - - /* check the validity of pointer parameters */ - if (!dir_entry) - return -EINVAL; - - /* check if the given file ID is opened */ - if (fid->type != TYPE_DIR) - return -ENOTDIR; - - /* acquire the lock for file system critical section */ - mutex_lock(&p_fs->v_mutex); - - if (fid->entry == -1) { - dir.dir = p_fs->root_dir; - dir.flags = 0x01; - } else { - dir.dir = fid->start_clu; - dir.size = (s32)(fid->size >> p_fs->cluster_size_bits); - dir.flags = fid->flags; - } - - dentry = (s32)fid->rwoffset; - - if (dir.dir == CLUSTER_32(0)) { - /* FAT16 root_dir */ - dentries_per_clu = p_fs->dentries_in_root; - - if (dentry == dentries_per_clu) { - clu.dir = CLUSTER_32(~0); - } else { - clu.dir = dir.dir; - clu.size = dir.size; - clu.flags = dir.flags; - } - } else { - dentries_per_clu = p_fs->dentries_per_clu; - dentries_per_clu_bits = ilog2(dentries_per_clu); - - clu_offset = dentry >> dentries_per_clu_bits; - clu.dir = dir.dir; - clu.size = dir.size; - clu.flags = dir.flags; - - if (clu.flags == 0x03) { - clu.dir += clu_offset; - clu.size -= clu_offset; - } else { - /* hint_information */ - if ((clu_offset > 0) && (fid->hint_last_off > 0) && - (clu_offset >= fid->hint_last_off)) { - clu_offset -= fid->hint_last_off; - clu.dir = fid->hint_last_clu; - } - - while (clu_offset > 0) { - /* clu.dir = exfat_fat_read(sb, clu.dir); */ - if (exfat_fat_read(sb, clu.dir, &clu.dir) == -1) { - ret = -EIO; - goto out; - } - clu_offset--; - } - } - } - - while (clu.dir != CLUSTER_32(~0)) { - if (p_fs->dev_ejected) - break; - - if (dir.dir == CLUSTER_32(0)) /* FAT16 root_dir */ - i = dentry % dentries_per_clu; - else - i = dentry & (dentries_per_clu - 1); - - for ( ; i < dentries_per_clu; i++, dentry++) { - ep = get_entry_in_dir(sb, &clu, i, §or); - if (!ep) { - ret = -ENOENT; - goto out; - } - type = exfat_get_entry_type(ep); - - if (type == TYPE_UNUSED) - break; - - if ((type != TYPE_FILE) && (type != TYPE_DIR)) - continue; - - exfat_buf_lock(sb, sector); - dir_entry->attr = exfat_get_entry_attr(ep); - - exfat_get_entry_time(ep, &tm, TM_CREATE); - dir_entry->create_timestamp.year = tm.year; - dir_entry->create_timestamp.month = tm.mon; - dir_entry->create_timestamp.day = tm.day; - dir_entry->create_timestamp.hour = tm.hour; - dir_entry->create_timestamp.minute = tm.min; - dir_entry->create_timestamp.second = tm.sec; - dir_entry->create_timestamp.millisecond = 0; - - exfat_get_entry_time(ep, &tm, TM_MODIFY); - dir_entry->modify_timestamp.year = tm.year; - dir_entry->modify_timestamp.month = tm.mon; - dir_entry->modify_timestamp.day = tm.day; - dir_entry->modify_timestamp.hour = tm.hour; - dir_entry->modify_timestamp.minute = tm.min; - dir_entry->modify_timestamp.second = tm.sec; - dir_entry->modify_timestamp.millisecond = 0; - - memset((char *)&dir_entry->access_timestamp, 0, - sizeof(struct date_time_t)); - - *uni_name.name = 0x0; - exfat_get_uni_name_from_ext_entry(sb, &dir, dentry, - uni_name.name); - nls_uniname_to_cstring(sb, dir_entry->name, &uni_name); - exfat_buf_unlock(sb, sector); - - ep = get_entry_in_dir(sb, &clu, i + 1, NULL); - if (!ep) { - ret = -ENOENT; - goto out; - } - - dir_entry->Size = exfat_get_entry_size(ep); - - /* hint information */ - if (dir.dir == CLUSTER_32(0)) { /* FAT16 root_dir */ - } else { - fid->hint_last_off = dentry >> - dentries_per_clu_bits; - fid->hint_last_clu = clu.dir; - } - - fid->rwoffset = (s64)(++dentry); - - if (p_fs->dev_ejected) - ret = -EIO; - goto out; - } - - if (dir.dir == CLUSTER_32(0)) - break; /* FAT16 root_dir */ - - if (clu.flags == 0x03) { - if ((--clu.size) > 0) - clu.dir++; - else - clu.dir = CLUSTER_32(~0); - } else { - /* clu.dir = exfat_fat_read(sb, clu.dir); */ - if (exfat_fat_read(sb, clu.dir, &clu.dir) == -1) { - ret = -EIO; - goto out; - } - } - } - - *dir_entry->name = '\0'; - - fid->rwoffset = (s64)(++dentry); - - if (p_fs->dev_ejected) - ret = -EIO; - -out: - /* release the lock for file system critical section */ - mutex_unlock(&p_fs->v_mutex); - - return ret; -} - -static int ffsRemoveDir(struct inode *inode, struct file_id_t *fid) -{ - s32 dentry; - int ret = 0; - struct chain_t dir, clu_to_free; - struct super_block *sb = inode->i_sb; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - - /* check the validity of the given file id */ - if (!fid) - return -EINVAL; - - dir.dir = fid->dir.dir; - dir.size = fid->dir.size; - dir.flags = fid->dir.flags; - - dentry = fid->entry; - - /* acquire the lock for file system critical section */ - mutex_lock(&p_fs->v_mutex); - - clu_to_free.dir = fid->start_clu; - clu_to_free.size = (s32)((fid->size - 1) >> p_fs->cluster_size_bits) + 1; - clu_to_free.flags = fid->flags; - - if (!is_dir_empty(sb, &clu_to_free)) { - ret = -ENOTEMPTY; - goto out; - } - - fs_set_vol_flags(sb, VOL_DIRTY); - - /* (1) update the directory entry */ - remove_file(inode, &dir, dentry); - - /* (2) free the clusters */ - exfat_free_cluster(sb, &clu_to_free, 1); - - fid->size = 0; - fid->start_clu = CLUSTER_32(~0); - fid->flags = 0x03; - -#ifndef CONFIG_STAGING_EXFAT_DELAYED_SYNC - fs_sync(sb, true); - fs_set_vol_flags(sb, VOL_CLEAN); -#endif - - if (p_fs->dev_ejected) - ret = -EIO; - -out: - /* release the lock for file system critical section */ - mutex_unlock(&p_fs->v_mutex); - - return ret; -} - -/*======================================================================*/ -/* Directory Entry Operations */ -/*======================================================================*/ - -static int exfat_readdir(struct file *filp, struct dir_context *ctx) -{ - struct inode *inode = file_inode(filp); - struct super_block *sb = inode->i_sb; - struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); - struct dir_entry_t de; - struct inode *tmp; - unsigned long inum; - loff_t cpos, i_pos; - int err = 0; - - __lock_super(sb); - - cpos = ctx->pos; - /* Fake . and .. for any directory. */ - while (cpos < 2) { - if (inode->i_ino == EXFAT_ROOT_INO) - inum = EXFAT_ROOT_INO; - else if (cpos == 0) - inum = inode->i_ino; - else /* (cpos == 1) */ - inum = parent_ino(filp->f_path.dentry); - - if (!dir_emit_dots(filp, ctx)) - goto out; - cpos++; - ctx->pos++; - } - if (cpos == 2) - cpos = 0; - if (cpos & (DENTRY_SIZE - 1)) { - err = -ENOENT; - goto out; - } - -get_new: - EXFAT_I(inode)->fid.size = i_size_read(inode); - EXFAT_I(inode)->fid.rwoffset = cpos >> DENTRY_SIZE_BITS; - - err = ffsReadDir(inode, &de); - if (err) { - /* at least we tried to read a sector - * move cpos to next sector position (should be aligned) - */ - if (err == -EIO) { - cpos += 1 << p_bd->sector_size_bits; - cpos &= ~((1 << p_bd->sector_size_bits) - 1); - } - - goto end_of_dir; - } - - cpos = EXFAT_I(inode)->fid.rwoffset << DENTRY_SIZE_BITS; - - if (!de.name[0]) - goto end_of_dir; - - i_pos = ((loff_t)EXFAT_I(inode)->fid.start_clu << 32) | - ((EXFAT_I(inode)->fid.rwoffset - 1) & 0xffffffff); - tmp = exfat_iget(sb, i_pos); - if (tmp) { - inum = tmp->i_ino; - iput(tmp); - } else { - inum = iunique(sb, EXFAT_ROOT_INO); - } - - if (!dir_emit(ctx, de.name, strlen(de.name), inum, - (de.attr & ATTR_SUBDIR) ? DT_DIR : DT_REG)) - goto out; - - ctx->pos = cpos; - goto get_new; - -end_of_dir: - ctx->pos = cpos; -out: - __unlock_super(sb); - return err; -} - -static int exfat_ioctl_volume_id(struct inode *dir) -{ - struct super_block *sb = dir->i_sb; - struct exfat_sb_info *sbi = EXFAT_SB(sb); - struct fs_info_t *p_fs = &sbi->fs_info; - - return p_fs->vol_id; -} - -static long exfat_generic_ioctl(struct file *filp, unsigned int cmd, - unsigned long arg) -{ - struct inode *inode = filp->f_path.dentry->d_inode; -#ifdef CONFIG_STAGING_EXFAT_KERNEL_DEBUG - unsigned int flags; -#endif /* CONFIG_STAGING_EXFAT_KERNEL_DEBUG */ - - switch (cmd) { - case EXFAT_IOCTL_GET_VOLUME_ID: - return exfat_ioctl_volume_id(inode); -#ifdef CONFIG_STAGING_EXFAT_KERNEL_DEBUG - case EXFAT_IOC_GET_DEBUGFLAGS: { - struct super_block *sb = inode->i_sb; - struct exfat_sb_info *sbi = EXFAT_SB(sb); - - flags = sbi->debug_flags; - return put_user(flags, (int __user *)arg); - } - case EXFAT_IOC_SET_DEBUGFLAGS: { - struct super_block *sb = inode->i_sb; - struct exfat_sb_info *sbi = EXFAT_SB(sb); - - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - - if (get_user(flags, (int __user *)arg)) - return -EFAULT; - - __lock_super(sb); - sbi->debug_flags = flags; - __unlock_super(sb); - - return 0; - } -#endif /* CONFIG_STAGING_EXFAT_KERNEL_DEBUG */ - default: - return -ENOTTY; /* Inappropriate ioctl for device */ - } -} - -static const struct file_operations exfat_dir_operations = { - .llseek = generic_file_llseek, - .read = generic_read_dir, - .iterate = exfat_readdir, - .unlocked_ioctl = exfat_generic_ioctl, - .fsync = generic_file_fsync, -}; - -static int exfat_create(struct inode *dir, struct dentry *dentry, umode_t mode, - bool excl) -{ - struct super_block *sb = dir->i_sb; - struct timespec64 curtime; - struct inode *inode; - struct file_id_t fid; - loff_t i_pos; - int err; - - __lock_super(sb); - - pr_debug("%s entered\n", __func__); - - err = ffsCreateFile(dir, (u8 *)dentry->d_name.name, &fid); - if (err) - goto out; - - INC_IVERSION(dir); - curtime = current_time(dir); - dir->i_ctime = curtime; - dir->i_mtime = curtime; - dir->i_atime = curtime; - if (IS_DIRSYNC(dir)) - (void)exfat_sync_inode(dir); - else - mark_inode_dirty(dir); - - i_pos = ((loff_t)fid.dir.dir << 32) | (fid.entry & 0xffffffff); - - inode = exfat_build_inode(sb, &fid, i_pos); - if (IS_ERR(inode)) { - err = PTR_ERR(inode); - goto out; - } - INC_IVERSION(inode); - curtime = current_time(inode); - inode->i_mtime = curtime; - inode->i_atime = curtime; - inode->i_ctime = curtime; - /* - * timestamp is already written, so mark_inode_dirty() is unnecessary. - */ - - dentry->d_time = GET_IVERSION(dentry->d_parent->d_inode); - d_instantiate(dentry, inode); - -out: - __unlock_super(sb); - pr_debug("%s exited\n", __func__); - return err; -} - -static int exfat_find(struct inode *dir, struct qstr *qname, - struct file_id_t *fid) -{ - int err; - - if (qname->len == 0) - return -ENOENT; - - err = ffsLookupFile(dir, (u8 *)qname->name, fid); - if (err) - return -ENOENT; - - return 0; -} - -static int exfat_d_anon_disconn(struct dentry *dentry) -{ - return IS_ROOT(dentry) && (dentry->d_flags & DCACHE_DISCONNECTED); -} - -static struct dentry *exfat_lookup(struct inode *dir, struct dentry *dentry, - unsigned int flags) -{ - struct super_block *sb = dir->i_sb; - struct inode *inode; - struct dentry *alias; - int err; - struct file_id_t fid; - loff_t i_pos; - mode_t i_mode; - - __lock_super(sb); - pr_debug("%s entered\n", __func__); - err = exfat_find(dir, &dentry->d_name, &fid); - if (err) { - if (err == -ENOENT) { - inode = NULL; - goto out; - } - goto error; - } - - i_pos = ((loff_t)fid.dir.dir << 32) | (fid.entry & 0xffffffff); - inode = exfat_build_inode(sb, &fid, i_pos); - if (IS_ERR(inode)) { - err = PTR_ERR(inode); - goto error; - } - - i_mode = inode->i_mode; - alias = d_find_alias(inode); - if (alias && !exfat_d_anon_disconn(alias)) { - BUG_ON(d_unhashed(alias)); - if (!S_ISDIR(i_mode)) - d_move(alias, dentry); - iput(inode); - __unlock_super(sb); - pr_debug("%s exited 1\n", __func__); - return alias; - } - dput(alias); -out: - __unlock_super(sb); - dentry->d_time = GET_IVERSION(dentry->d_parent->d_inode); - dentry = d_splice_alias(inode, dentry); - if (dentry) - dentry->d_time = GET_IVERSION(dentry->d_parent->d_inode); - pr_debug("%s exited 2\n", __func__); - return dentry; - -error: - __unlock_super(sb); - pr_debug("%s exited 3\n", __func__); - return ERR_PTR(err); -} - -static inline unsigned long exfat_hash(loff_t i_pos) -{ - return hash_32(i_pos, EXFAT_HASH_BITS); -} - -static void exfat_attach(struct inode *inode, loff_t i_pos) -{ - struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb); - struct hlist_head *head = sbi->inode_hashtable + exfat_hash(i_pos); - - spin_lock(&sbi->inode_hash_lock); - EXFAT_I(inode)->i_pos = i_pos; - hlist_add_head(&EXFAT_I(inode)->i_hash_fat, head); - spin_unlock(&sbi->inode_hash_lock); -} - -static void exfat_detach(struct inode *inode) -{ - struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb); - - spin_lock(&sbi->inode_hash_lock); - hlist_del_init(&EXFAT_I(inode)->i_hash_fat); - EXFAT_I(inode)->i_pos = 0; - spin_unlock(&sbi->inode_hash_lock); -} - -static int exfat_unlink(struct inode *dir, struct dentry *dentry) -{ - struct inode *inode = dentry->d_inode; - struct super_block *sb = dir->i_sb; - struct timespec64 curtime; - int err; - - __lock_super(sb); - - pr_debug("%s entered\n", __func__); - - EXFAT_I(inode)->fid.size = i_size_read(inode); - - err = ffsRemoveFile(dir, &(EXFAT_I(inode)->fid)); - if (err) - goto out; - - INC_IVERSION(dir); - curtime = current_time(dir); - dir->i_mtime = curtime; - dir->i_atime = curtime; - if (IS_DIRSYNC(dir)) - (void)exfat_sync_inode(dir); - else - mark_inode_dirty(dir); - - clear_nlink(inode); - curtime = current_time(inode); - inode->i_mtime = curtime; - inode->i_atime = curtime; - exfat_detach(inode); - remove_inode_hash(inode); - -out: - __unlock_super(sb); - pr_debug("%s exited\n", __func__); - return err; -} - -static int exfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) -{ - struct super_block *sb = dir->i_sb; - struct timespec64 curtime; - struct inode *inode; - struct file_id_t fid; - loff_t i_pos; - int err; - - __lock_super(sb); - - pr_debug("%s entered\n", __func__); - - err = ffsCreateDir(dir, (u8 *)dentry->d_name.name, &fid); - if (err) - goto out; - - INC_IVERSION(dir); - curtime = current_time(dir); - dir->i_ctime = curtime; - dir->i_mtime = curtime; - dir->i_atime = curtime; - if (IS_DIRSYNC(dir)) - (void)exfat_sync_inode(dir); - else - mark_inode_dirty(dir); - inc_nlink(dir); - - i_pos = ((loff_t)fid.dir.dir << 32) | (fid.entry & 0xffffffff); - - inode = exfat_build_inode(sb, &fid, i_pos); - if (IS_ERR(inode)) { - err = PTR_ERR(inode); - goto out; - } - INC_IVERSION(inode); - curtime = current_time(inode); - inode->i_mtime = curtime; - inode->i_atime = curtime; - inode->i_ctime = curtime; - /* timestamp is already written, so mark_inode_dirty() is unneeded. */ - - dentry->d_time = GET_IVERSION(dentry->d_parent->d_inode); - d_instantiate(dentry, inode); - -out: - __unlock_super(sb); - pr_debug("%s exited\n", __func__); - return err; -} - -static int exfat_rmdir(struct inode *dir, struct dentry *dentry) -{ - struct inode *inode = dentry->d_inode; - struct super_block *sb = dir->i_sb; - struct timespec64 curtime; - int err; - - __lock_super(sb); - - pr_debug("%s entered\n", __func__); - - EXFAT_I(inode)->fid.size = i_size_read(inode); - - err = ffsRemoveDir(dir, &(EXFAT_I(inode)->fid)); - if (err) - goto out; - - INC_IVERSION(dir); - curtime = current_time(dir); - dir->i_mtime = curtime; - dir->i_atime = curtime; - if (IS_DIRSYNC(dir)) - (void)exfat_sync_inode(dir); - else - mark_inode_dirty(dir); - drop_nlink(dir); - - clear_nlink(inode); - curtime = current_time(inode); - inode->i_mtime = curtime; - inode->i_atime = curtime; - exfat_detach(inode); - remove_inode_hash(inode); - -out: - __unlock_super(sb); - pr_debug("%s exited\n", __func__); - return err; -} - -static int exfat_rename(struct inode *old_dir, struct dentry *old_dentry, - struct inode *new_dir, struct dentry *new_dentry, - unsigned int flags) -{ - struct inode *old_inode, *new_inode; - struct super_block *sb = old_dir->i_sb; - struct timespec64 curtime; - loff_t i_pos; - int err; - - if (flags) - return -EINVAL; - - __lock_super(sb); - - pr_debug("%s entered\n", __func__); - - old_inode = old_dentry->d_inode; - new_inode = new_dentry->d_inode; - - EXFAT_I(old_inode)->fid.size = i_size_read(old_inode); - - err = ffsMoveFile(old_dir, &(EXFAT_I(old_inode)->fid), new_dir, - new_dentry); - if (err) - goto out; - - INC_IVERSION(new_dir); - curtime = current_time(new_dir); - new_dir->i_ctime = curtime; - new_dir->i_mtime = curtime; - new_dir->i_atime = curtime; - - if (IS_DIRSYNC(new_dir)) - (void)exfat_sync_inode(new_dir); - else - mark_inode_dirty(new_dir); - - i_pos = ((loff_t)EXFAT_I(old_inode)->fid.dir.dir << 32) | - (EXFAT_I(old_inode)->fid.entry & 0xffffffff); - - exfat_detach(old_inode); - exfat_attach(old_inode, i_pos); - if (IS_DIRSYNC(new_dir)) - (void)exfat_sync_inode(old_inode); - else - mark_inode_dirty(old_inode); - - if ((S_ISDIR(old_inode->i_mode)) && (old_dir != new_dir)) { - drop_nlink(old_dir); - if (!new_inode) - inc_nlink(new_dir); - } - INC_IVERSION(old_dir); - curtime = current_time(old_dir); - old_dir->i_ctime = curtime; - old_dir->i_mtime = curtime; - if (IS_DIRSYNC(old_dir)) - (void)exfat_sync_inode(old_dir); - else - mark_inode_dirty(old_dir); - - if (new_inode) { - exfat_detach(new_inode); - drop_nlink(new_inode); - if (S_ISDIR(new_inode->i_mode)) - drop_nlink(new_inode); - new_inode->i_ctime = current_time(new_inode); - } - -out: - __unlock_super(sb); - pr_debug("%s exited\n", __func__); - return err; -} - -static int exfat_cont_expand(struct inode *inode, loff_t size) -{ - struct address_space *mapping = inode->i_mapping; - loff_t start = i_size_read(inode), count = size - i_size_read(inode); - struct timespec64 curtime; - int err, err2; - - err = generic_cont_expand_simple(inode, size); - if (err != 0) - return err; - - curtime = current_time(inode); - inode->i_ctime = curtime; - inode->i_mtime = curtime; - mark_inode_dirty(inode); - - if (IS_SYNC(inode)) { - err = filemap_fdatawrite_range(mapping, start, - start + count - 1); - err2 = sync_mapping_buffers(mapping); - err = (err) ? (err) : (err2); - err2 = write_inode_now(inode, 1); - err = (err) ? (err) : (err2); - if (!err) - err = filemap_fdatawait_range(mapping, start, - start + count - 1); - } - return err; -} - -static int exfat_allow_set_time(struct exfat_sb_info *sbi, struct inode *inode) -{ - mode_t allow_utime = sbi->options.allow_utime; - - if (!uid_eq(current_fsuid(), inode->i_uid)) { - if (in_group_p(inode->i_gid)) - allow_utime >>= 3; - if (allow_utime & MAY_WRITE) - return 1; - } - - /* use a default check */ - return 0; -} - -static int exfat_sanitize_mode(const struct exfat_sb_info *sbi, - struct inode *inode, umode_t *mode_ptr) -{ - mode_t i_mode, mask, perm; - - i_mode = inode->i_mode; - - if (S_ISREG(i_mode) || S_ISLNK(i_mode)) - mask = sbi->options.fs_fmask; - else - mask = sbi->options.fs_dmask; - - perm = *mode_ptr & ~(S_IFMT | mask); - - /* Of the r and x bits, all (subject to umask) must be present.*/ - if ((perm & 0555) != (i_mode & 0555)) - return -EPERM; - - if (exfat_mode_can_hold_ro(inode)) { - /* - * Of the w bits, either all (subject to umask) or none must be - * present. - */ - if ((perm & 0222) && ((perm & 0222) != (0222 & ~mask))) - return -EPERM; - } else { - /* - * If exfat_mode_can_hold_ro(inode) is false, can't change w - * bits. - */ - if ((perm & 0222) != (0222 & ~mask)) - return -EPERM; - } - - *mode_ptr &= S_IFMT | perm; - - return 0; -} - -static void exfat_truncate(struct inode *inode, loff_t old_size) -{ - struct super_block *sb = inode->i_sb; - struct exfat_sb_info *sbi = EXFAT_SB(sb); - struct fs_info_t *p_fs = &sbi->fs_info; - struct timespec64 curtime; - int err; - - __lock_super(sb); - - /* - * This protects against truncating a file bigger than it was then - * trying to write into the hole. - */ - if (EXFAT_I(inode)->mmu_private > i_size_read(inode)) - EXFAT_I(inode)->mmu_private = i_size_read(inode); - - if (EXFAT_I(inode)->fid.start_clu == 0) - goto out; - - err = ffsTruncateFile(inode, old_size, i_size_read(inode)); - if (err) - goto out; - - curtime = current_time(inode); - inode->i_ctime = curtime; - inode->i_mtime = curtime; - if (IS_DIRSYNC(inode)) - (void)exfat_sync_inode(inode); - else - mark_inode_dirty(inode); - - inode->i_blocks = ((i_size_read(inode) + (p_fs->cluster_size - 1)) & - ~((loff_t)p_fs->cluster_size - 1)) >> 9; -out: - __unlock_super(sb); -} - -static int exfat_setattr(struct dentry *dentry, struct iattr *attr) -{ - struct exfat_sb_info *sbi = EXFAT_SB(dentry->d_sb); - struct inode *inode = dentry->d_inode; - unsigned int ia_valid; - int error; - loff_t old_size; - - pr_debug("%s entered\n", __func__); - - if ((attr->ia_valid & ATTR_SIZE) && - attr->ia_size > i_size_read(inode)) { - error = exfat_cont_expand(inode, attr->ia_size); - if (error || attr->ia_valid == ATTR_SIZE) - return error; - attr->ia_valid &= ~ATTR_SIZE; - } - - ia_valid = attr->ia_valid; - - if ((ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET)) && - exfat_allow_set_time(sbi, inode)) { - attr->ia_valid &= ~(ATTR_MTIME_SET | - ATTR_ATIME_SET | - ATTR_TIMES_SET); - } - - error = setattr_prepare(dentry, attr); - attr->ia_valid = ia_valid; - if (error) - return error; - - if (((attr->ia_valid & ATTR_UID) && - (!uid_eq(attr->ia_uid, sbi->options.fs_uid))) || - ((attr->ia_valid & ATTR_GID) && - (!gid_eq(attr->ia_gid, sbi->options.fs_gid))) || - ((attr->ia_valid & ATTR_MODE) && - (attr->ia_mode & ~(S_IFREG | S_IFLNK | S_IFDIR | 0777)))) { - return -EPERM; - } - - /* - * We don't return -EPERM here. Yes, strange, but this is too - * old behavior. - */ - if (attr->ia_valid & ATTR_MODE) { - if (exfat_sanitize_mode(sbi, inode, &attr->ia_mode) < 0) - attr->ia_valid &= ~ATTR_MODE; - } - - EXFAT_I(inode)->fid.size = i_size_read(inode); - - if (attr->ia_valid & ATTR_SIZE) { - old_size = i_size_read(inode); - down_write(&EXFAT_I(inode)->truncate_lock); - truncate_setsize(inode, attr->ia_size); - exfat_truncate(inode, old_size); - up_write(&EXFAT_I(inode)->truncate_lock); - } - setattr_copy(inode, attr); - mark_inode_dirty(inode); - - pr_debug("%s exited\n", __func__); - return error; -} - -static int exfat_getattr(const struct path *path, struct kstat *stat, - u32 request_mask, unsigned int flags) -{ - struct inode *inode = path->dentry->d_inode; - - pr_debug("%s entered\n", __func__); - - generic_fillattr(inode, stat); - stat->blksize = EXFAT_SB(inode->i_sb)->fs_info.cluster_size; - - pr_debug("%s exited\n", __func__); - return 0; -} - -static const struct inode_operations exfat_dir_inode_operations = { - .create = exfat_create, - .lookup = exfat_lookup, - .unlink = exfat_unlink, - .mkdir = exfat_mkdir, - .rmdir = exfat_rmdir, - .rename = exfat_rename, - .setattr = exfat_setattr, - .getattr = exfat_getattr, -}; - -/*======================================================================*/ -/* File Operations */ -/*======================================================================*/ -static int exfat_file_release(struct inode *inode, struct file *filp) -{ - struct super_block *sb = inode->i_sb; - - EXFAT_I(inode)->fid.size = i_size_read(inode); - ffsSyncVol(sb, false); - return 0; -} - -static const struct file_operations exfat_file_operations = { - .llseek = generic_file_llseek, - .read_iter = generic_file_read_iter, - .write_iter = generic_file_write_iter, - .mmap = generic_file_mmap, - .release = exfat_file_release, - .unlocked_ioctl = exfat_generic_ioctl, - .fsync = generic_file_fsync, - .splice_read = generic_file_splice_read, -}; - -static const struct inode_operations exfat_file_inode_operations = { - .setattr = exfat_setattr, - .getattr = exfat_getattr, -}; - -/*======================================================================*/ -/* Address Space Operations */ -/*======================================================================*/ - -static int exfat_bmap(struct inode *inode, sector_t sector, sector_t *phys, - unsigned long *mapped_blocks, int *create) -{ - struct super_block *sb = inode->i_sb; - struct exfat_sb_info *sbi = EXFAT_SB(sb); - struct fs_info_t *p_fs = &sbi->fs_info; - const unsigned long blocksize = sb->s_blocksize; - const unsigned char blocksize_bits = sb->s_blocksize_bits; - sector_t last_block; - int err, clu_offset, sec_offset; - unsigned int cluster; - - *phys = 0; - *mapped_blocks = 0; - - last_block = (i_size_read(inode) + (blocksize - 1)) >> blocksize_bits; - if (sector >= last_block) { - if (*create == 0) - return 0; - } else { - *create = 0; - } - - /* cluster offset */ - clu_offset = sector >> p_fs->sectors_per_clu_bits; - - /* sector offset in cluster */ - sec_offset = sector & (p_fs->sectors_per_clu - 1); - - EXFAT_I(inode)->fid.size = i_size_read(inode); - - err = ffsMapCluster(inode, clu_offset, &cluster); - - if (!err && (cluster != CLUSTER_32(~0))) { - *phys = START_SECTOR(cluster) + sec_offset; - *mapped_blocks = p_fs->sectors_per_clu - sec_offset; - } - - return 0; -} - -static int exfat_get_block(struct inode *inode, sector_t iblock, - struct buffer_head *bh_result, int create) -{ - struct super_block *sb = inode->i_sb; - unsigned long max_blocks = bh_result->b_size >> inode->i_blkbits; - int err; - unsigned long mapped_blocks; - sector_t phys; - - __lock_super(sb); - - err = exfat_bmap(inode, iblock, &phys, &mapped_blocks, &create); - if (err) { - __unlock_super(sb); - return err; - } - - if (phys) { - max_blocks = min(mapped_blocks, max_blocks); - if (create) { - EXFAT_I(inode)->mmu_private += max_blocks << - sb->s_blocksize_bits; - set_buffer_new(bh_result); - } - map_bh(bh_result, sb, phys); - } - - bh_result->b_size = max_blocks << sb->s_blocksize_bits; - __unlock_super(sb); - - return 0; -} - -static int exfat_readpage(struct file *file, struct page *page) -{ - return mpage_readpage(page, exfat_get_block); -} - -static int exfat_readpages(struct file *file, struct address_space *mapping, - struct list_head *pages, unsigned int nr_pages) -{ - return mpage_readpages(mapping, pages, nr_pages, exfat_get_block); -} - -static int exfat_writepage(struct page *page, struct writeback_control *wbc) -{ - return block_write_full_page(page, exfat_get_block, wbc); -} - -static int exfat_writepages(struct address_space *mapping, - struct writeback_control *wbc) -{ - return mpage_writepages(mapping, wbc, exfat_get_block); -} - -static void exfat_write_failed(struct address_space *mapping, loff_t to) -{ - struct inode *inode = mapping->host; - - if (to > i_size_read(inode)) { - truncate_pagecache(inode, i_size_read(inode)); - EXFAT_I(inode)->fid.size = i_size_read(inode); - exfat_truncate(inode, i_size_read(inode)); - } -} - -static int exfat_write_begin(struct file *file, struct address_space *mapping, - loff_t pos, unsigned int len, unsigned int flags, - struct page **pagep, void **fsdata) -{ - int ret; - - *pagep = NULL; - ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata, - exfat_get_block, - &EXFAT_I(mapping->host)->mmu_private); - - if (ret < 0) - exfat_write_failed(mapping, pos + len); - return ret; -} - -static int exfat_write_end(struct file *file, struct address_space *mapping, - loff_t pos, unsigned int len, unsigned int copied, - struct page *pagep, void *fsdata) -{ - struct inode *inode = mapping->host; - struct file_id_t *fid = &(EXFAT_I(inode)->fid); - struct timespec64 curtime; - int err; - - err = generic_write_end(file, mapping, pos, len, copied, pagep, fsdata); - - if (err < len) - exfat_write_failed(mapping, pos + len); - - if (!(err < 0) && !(fid->attr & ATTR_ARCHIVE)) { - curtime = current_time(inode); - inode->i_mtime = curtime; - inode->i_ctime = curtime; - fid->attr |= ATTR_ARCHIVE; - mark_inode_dirty(inode); - } - return err; -} - -static ssize_t exfat_direct_IO(struct kiocb *iocb, struct iov_iter *iter) -{ - struct inode *inode = iocb->ki_filp->f_mapping->host; - struct address_space *mapping = iocb->ki_filp->f_mapping; - ssize_t ret; - int rw; - - rw = iov_iter_rw(iter); - - if (rw == WRITE) { - if (EXFAT_I(inode)->mmu_private < iov_iter_count(iter)) - return 0; - } - ret = blockdev_direct_IO(iocb, inode, iter, exfat_get_block); - - if ((ret < 0) && (rw & WRITE)) - exfat_write_failed(mapping, iov_iter_count(iter)); - return ret; -} - -static sector_t _exfat_bmap(struct address_space *mapping, sector_t block) -{ - sector_t blocknr; - - /* exfat_get_cluster() assumes the requested blocknr isn't truncated. */ - down_read(&EXFAT_I(mapping->host)->truncate_lock); - blocknr = generic_block_bmap(mapping, block, exfat_get_block); - up_read(&EXFAT_I(mapping->host)->truncate_lock); - - return blocknr; -} - -static const struct address_space_operations exfat_aops = { - .readpage = exfat_readpage, - .readpages = exfat_readpages, - .writepage = exfat_writepage, - .writepages = exfat_writepages, - .write_begin = exfat_write_begin, - .write_end = exfat_write_end, - .direct_IO = exfat_direct_IO, - .bmap = _exfat_bmap -}; - -/*======================================================================*/ -/* Super Operations */ -/*======================================================================*/ - -static struct inode *exfat_iget(struct super_block *sb, loff_t i_pos) -{ - struct exfat_sb_info *sbi = EXFAT_SB(sb); - struct exfat_inode_info *info; - struct hlist_head *head = sbi->inode_hashtable + exfat_hash(i_pos); - struct inode *inode = NULL; - - spin_lock(&sbi->inode_hash_lock); - hlist_for_each_entry(info, head, i_hash_fat) { - BUG_ON(info->vfs_inode.i_sb != sb); - - if (i_pos != info->i_pos) - continue; - inode = igrab(&info->vfs_inode); - if (inode) - break; - } - spin_unlock(&sbi->inode_hash_lock); - return inode; -} - -/* doesn't deal with root inode */ -static int exfat_fill_inode(struct inode *inode, struct file_id_t *fid) -{ - struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb); - struct fs_info_t *p_fs = &sbi->fs_info; - struct dir_entry_t info; - - memcpy(&(EXFAT_I(inode)->fid), fid, sizeof(struct file_id_t)); - - ffsReadStat(inode, &info); - - EXFAT_I(inode)->i_pos = 0; - EXFAT_I(inode)->target = NULL; - inode->i_uid = sbi->options.fs_uid; - inode->i_gid = sbi->options.fs_gid; - INC_IVERSION(inode); - inode->i_generation = prandom_u32(); - - if (info.attr & ATTR_SUBDIR) { /* directory */ - inode->i_generation &= ~1; - inode->i_mode = exfat_make_mode(sbi, info.attr, 0777); - inode->i_op = &exfat_dir_inode_operations; - inode->i_fop = &exfat_dir_operations; - - i_size_write(inode, info.Size); - EXFAT_I(inode)->mmu_private = i_size_read(inode); - set_nlink(inode, info.num_subdirs); - } else { /* regular file */ - inode->i_generation |= 1; - inode->i_mode = exfat_make_mode(sbi, info.attr, 0777); - inode->i_op = &exfat_file_inode_operations; - inode->i_fop = &exfat_file_operations; - inode->i_mapping->a_ops = &exfat_aops; - inode->i_mapping->nrpages = 0; - - i_size_write(inode, info.Size); - EXFAT_I(inode)->mmu_private = i_size_read(inode); - } - exfat_save_attr(inode, info.attr); - - inode->i_blocks = ((i_size_read(inode) + (p_fs->cluster_size - 1)) - & ~((loff_t)p_fs->cluster_size - 1)) >> 9; - - exfat_time_fat2unix(&inode->i_mtime, &info.modify_timestamp); - exfat_time_fat2unix(&inode->i_ctime, &info.create_timestamp); - exfat_time_fat2unix(&inode->i_atime, &info.access_timestamp); - - return 0; -} - -static struct inode *exfat_build_inode(struct super_block *sb, - struct file_id_t *fid, loff_t i_pos) -{ - struct inode *inode; - int err; - - inode = exfat_iget(sb, i_pos); - if (inode) - goto out; - inode = new_inode(sb); - if (!inode) { - inode = ERR_PTR(-ENOMEM); - goto out; - } - inode->i_ino = iunique(sb, EXFAT_ROOT_INO); - SET_IVERSION(inode, 1); - err = exfat_fill_inode(inode, fid); - if (err) { - iput(inode); - inode = ERR_PTR(err); - goto out; - } - exfat_attach(inode, i_pos); - insert_inode_hash(inode); -out: - return inode; -} - -static int exfat_sync_inode(struct inode *inode) -{ - return exfat_write_inode(inode, NULL); -} - -static struct inode *exfat_alloc_inode(struct super_block *sb) -{ - struct exfat_inode_info *ei; - - ei = kmem_cache_alloc(exfat_inode_cachep, GFP_NOFS); - if (!ei) - return NULL; - - init_rwsem(&ei->truncate_lock); - - return &ei->vfs_inode; -} - -static void exfat_destroy_inode(struct inode *inode) -{ - kfree(EXFAT_I(inode)->target); - EXFAT_I(inode)->target = NULL; - - kmem_cache_free(exfat_inode_cachep, EXFAT_I(inode)); -} - -static int exfat_write_inode(struct inode *inode, struct writeback_control *wbc) -{ - struct dir_entry_t info; - - if (inode->i_ino == EXFAT_ROOT_INO) - return 0; - - info.attr = exfat_make_attr(inode); - info.Size = i_size_read(inode); - - exfat_time_unix2fat(&inode->i_mtime, &info.modify_timestamp); - exfat_time_unix2fat(&inode->i_ctime, &info.create_timestamp); - exfat_time_unix2fat(&inode->i_atime, &info.access_timestamp); - - ffsWriteStat(inode, &info); - - return 0; -} - -static void exfat_evict_inode(struct inode *inode) -{ - truncate_inode_pages(&inode->i_data, 0); - - if (!inode->i_nlink) - i_size_write(inode, 0); - invalidate_inode_buffers(inode); - clear_inode(inode); - exfat_detach(inode); - - remove_inode_hash(inode); -} - -static void exfat_free_super(struct exfat_sb_info *sbi) -{ - if (sbi->nls_disk) - unload_nls(sbi->nls_disk); - if (sbi->nls_io) - unload_nls(sbi->nls_io); - if (sbi->options.iocharset != exfat_default_iocharset) - kfree(sbi->options.iocharset); - /* mutex_init is in exfat_fill_super function. only for 3.7+ */ - mutex_destroy(&sbi->s_lock); - kvfree(sbi); -} - -static void exfat_put_super(struct super_block *sb) -{ - struct exfat_sb_info *sbi = EXFAT_SB(sb); - - if (__is_sb_dirty(sb)) - exfat_write_super(sb); - - ffsUmountVol(sb); - - sb->s_fs_info = NULL; - exfat_free_super(sbi); -} - -static void exfat_write_super(struct super_block *sb) -{ - __lock_super(sb); - - __set_sb_clean(sb); - - if (!sb_rdonly(sb)) - ffsSyncVol(sb, true); - - __unlock_super(sb); -} - -static int exfat_sync_fs(struct super_block *sb, int wait) -{ - int err = 0; - - if (__is_sb_dirty(sb)) { - __lock_super(sb); - __set_sb_clean(sb); - err = ffsSyncVol(sb, true); - __unlock_super(sb); - } - - return err; -} - -static int exfat_statfs(struct dentry *dentry, struct kstatfs *buf) -{ - struct super_block *sb = dentry->d_sb; - u64 id = huge_encode_dev(sb->s_bdev->bd_dev); - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - struct vol_info_t info; - - if (p_fs->used_clusters == UINT_MAX) { - if (ffsGetVolInfo(sb, &info) == -EIO) - return -EIO; - - } else { - info.FatType = EXFAT; - info.ClusterSize = p_fs->cluster_size; - info.NumClusters = p_fs->num_clusters - 2; - info.UsedClusters = p_fs->used_clusters; - info.FreeClusters = info.NumClusters - info.UsedClusters; - - if (p_fs->dev_ejected) - pr_info("[EXFAT] statfs on device that is ejected\n"); - } - - buf->f_type = sb->s_magic; - buf->f_bsize = info.ClusterSize; - buf->f_blocks = info.NumClusters; - buf->f_bfree = info.FreeClusters; - buf->f_bavail = info.FreeClusters; - buf->f_fsid.val[0] = (u32)id; - buf->f_fsid.val[1] = (u32)(id >> 32); - buf->f_namelen = 260; - - return 0; -} - -static int exfat_remount(struct super_block *sb, int *flags, char *data) -{ - *flags |= SB_NODIRATIME; - return 0; -} - -static int exfat_show_options(struct seq_file *m, struct dentry *root) -{ - struct exfat_sb_info *sbi = EXFAT_SB(root->d_sb); - struct exfat_mount_options *opts = &sbi->options; - - if (__kuid_val(opts->fs_uid)) - seq_printf(m, ",uid=%u", __kuid_val(opts->fs_uid)); - if (__kgid_val(opts->fs_gid)) - seq_printf(m, ",gid=%u", __kgid_val(opts->fs_gid)); - seq_printf(m, ",fmask=%04o", opts->fs_fmask); - seq_printf(m, ",dmask=%04o", opts->fs_dmask); - if (opts->allow_utime) - seq_printf(m, ",allow_utime=%04o", opts->allow_utime); - if (sbi->nls_disk) - seq_printf(m, ",codepage=%s", sbi->nls_disk->charset); - if (sbi->nls_io) - seq_printf(m, ",iocharset=%s", sbi->nls_io->charset); - seq_printf(m, ",namecase=%u", opts->casesensitive); - if (opts->errors == EXFAT_ERRORS_CONT) - seq_puts(m, ",errors=continue"); - else if (opts->errors == EXFAT_ERRORS_PANIC) - seq_puts(m, ",errors=panic"); - else - seq_puts(m, ",errors=remount-ro"); -#ifdef CONFIG_STAGING_EXFAT_DISCARD - if (opts->discard) - seq_puts(m, ",discard"); -#endif - return 0; -} - -static const struct super_operations exfat_sops = { - .alloc_inode = exfat_alloc_inode, - .destroy_inode = exfat_destroy_inode, - .write_inode = exfat_write_inode, - .evict_inode = exfat_evict_inode, - .put_super = exfat_put_super, - .sync_fs = exfat_sync_fs, - .statfs = exfat_statfs, - .remount_fs = exfat_remount, - .show_options = exfat_show_options, -}; - -/*======================================================================*/ -/* Export Operations */ -/*======================================================================*/ - -static struct inode *exfat_nfs_get_inode(struct super_block *sb, u64 ino, - u32 generation) -{ - struct inode *inode = NULL; - - if (ino < EXFAT_ROOT_INO) - return inode; - inode = ilookup(sb, ino); - - if (inode && generation && (inode->i_generation != generation)) { - iput(inode); - inode = NULL; - } - - return inode; -} - -static struct dentry *exfat_fh_to_dentry(struct super_block *sb, - struct fid *fid, int fh_len, - int fh_type) -{ - return generic_fh_to_dentry(sb, fid, fh_len, fh_type, - exfat_nfs_get_inode); -} - -static struct dentry *exfat_fh_to_parent(struct super_block *sb, - struct fid *fid, int fh_len, - int fh_type) -{ - return generic_fh_to_parent(sb, fid, fh_len, fh_type, - exfat_nfs_get_inode); -} - -static const struct export_operations exfat_export_ops = { - .fh_to_dentry = exfat_fh_to_dentry, - .fh_to_parent = exfat_fh_to_parent, -}; - -/*======================================================================*/ -/* Super Block Read Operations */ -/*======================================================================*/ - -enum { - Opt_uid, - Opt_gid, - Opt_umask, - Opt_dmask, - Opt_fmask, - Opt_allow_utime, - Opt_codepage, - Opt_charset, - Opt_namecase, - Opt_debug, - Opt_err_cont, - Opt_err_panic, - Opt_err_ro, - Opt_utf8_hack, - Opt_err, -#ifdef CONFIG_STAGING_EXFAT_DISCARD - Opt_discard, -#endif /* EXFAT_CONFIG_DISCARD */ -}; - -static const match_table_t exfat_tokens = { - {Opt_uid, "uid=%u"}, - {Opt_gid, "gid=%u"}, - {Opt_umask, "umask=%o"}, - {Opt_dmask, "dmask=%o"}, - {Opt_fmask, "fmask=%o"}, - {Opt_allow_utime, "allow_utime=%o"}, - {Opt_codepage, "codepage=%u"}, - {Opt_charset, "iocharset=%s"}, - {Opt_namecase, "namecase=%u"}, - {Opt_debug, "debug"}, - {Opt_err_cont, "errors=continue"}, - {Opt_err_panic, "errors=panic"}, - {Opt_err_ro, "errors=remount-ro"}, - {Opt_utf8_hack, "utf8"}, -#ifdef CONFIG_STAGING_EXFAT_DISCARD - {Opt_discard, "discard"}, -#endif /* CONFIG_STAGING_EXFAT_DISCARD */ - {Opt_err, NULL} -}; - -static int parse_options(char *options, int silent, int *debug, - struct exfat_mount_options *opts) -{ - char *p; - substring_t args[MAX_OPT_ARGS]; - int option; - char *iocharset; - - opts->fs_uid = current_uid(); - opts->fs_gid = current_gid(); - opts->fs_fmask = current->fs->umask; - opts->fs_dmask = current->fs->umask; - opts->allow_utime = U16_MAX; - opts->codepage = exfat_default_codepage; - opts->iocharset = exfat_default_iocharset; - opts->casesensitive = 0; - opts->errors = EXFAT_ERRORS_RO; -#ifdef CONFIG_STAGING_EXFAT_DISCARD - opts->discard = 0; -#endif - *debug = 0; - - if (!options) - goto out; - - while ((p = strsep(&options, ","))) { - int token; - - if (!*p) - continue; - - token = match_token(p, exfat_tokens, args); - switch (token) { - case Opt_uid: - if (match_int(&args[0], &option)) - return 0; - opts->fs_uid = KUIDT_INIT(option); - break; - case Opt_gid: - if (match_int(&args[0], &option)) - return 0; - opts->fs_gid = KGIDT_INIT(option); - break; - case Opt_umask: - case Opt_dmask: - case Opt_fmask: - if (match_octal(&args[0], &option)) - return 0; - if (token != Opt_dmask) - opts->fs_fmask = option; - if (token != Opt_fmask) - opts->fs_dmask = option; - break; - case Opt_allow_utime: - if (match_octal(&args[0], &option)) - return 0; - opts->allow_utime = option & 0022; - break; - case Opt_codepage: - if (match_int(&args[0], &option)) - return 0; - opts->codepage = option; - break; - case Opt_charset: - if (opts->iocharset != exfat_default_iocharset) - kfree(opts->iocharset); - iocharset = match_strdup(&args[0]); - if (!iocharset) - return -ENOMEM; - opts->iocharset = iocharset; - break; - case Opt_namecase: - if (match_int(&args[0], &option)) - return 0; - opts->casesensitive = option; - break; - case Opt_err_cont: - opts->errors = EXFAT_ERRORS_CONT; - break; - case Opt_err_panic: - opts->errors = EXFAT_ERRORS_PANIC; - break; - case Opt_err_ro: - opts->errors = EXFAT_ERRORS_RO; - break; - case Opt_debug: - *debug = 1; - break; -#ifdef CONFIG_STAGING_EXFAT_DISCARD - case Opt_discard: - opts->discard = 1; - break; -#endif /* CONFIG_STAGING_EXFAT_DISCARD */ - case Opt_utf8_hack: - break; - default: - if (!silent) - pr_err("[EXFAT] Unrecognized mount option %s or missing value\n", - p); - return -EINVAL; - } - } - -out: - if (opts->allow_utime == U16_MAX) - opts->allow_utime = ~opts->fs_dmask & 0022; - - return 0; -} - -static void exfat_hash_init(struct super_block *sb) -{ - struct exfat_sb_info *sbi = EXFAT_SB(sb); - int i; - - spin_lock_init(&sbi->inode_hash_lock); - for (i = 0; i < EXFAT_HASH_SIZE; i++) - INIT_HLIST_HEAD(&sbi->inode_hashtable[i]); -} - -static int exfat_read_root(struct inode *inode) -{ - struct super_block *sb = inode->i_sb; - struct exfat_sb_info *sbi = EXFAT_SB(sb); - struct fs_info_t *p_fs = &sbi->fs_info; - struct timespec64 curtime; - struct dir_entry_t info; - - EXFAT_I(inode)->fid.dir.dir = p_fs->root_dir; - EXFAT_I(inode)->fid.dir.flags = 0x01; - EXFAT_I(inode)->fid.entry = -1; - EXFAT_I(inode)->fid.start_clu = p_fs->root_dir; - EXFAT_I(inode)->fid.flags = 0x01; - EXFAT_I(inode)->fid.type = TYPE_DIR; - EXFAT_I(inode)->fid.rwoffset = 0; - EXFAT_I(inode)->fid.hint_last_off = -1; - - EXFAT_I(inode)->target = NULL; - - ffsReadStat(inode, &info); - - inode->i_uid = sbi->options.fs_uid; - inode->i_gid = sbi->options.fs_gid; - INC_IVERSION(inode); - inode->i_generation = 0; - inode->i_mode = exfat_make_mode(sbi, ATTR_SUBDIR, 0777); - inode->i_op = &exfat_dir_inode_operations; - inode->i_fop = &exfat_dir_operations; - - i_size_write(inode, info.Size); - inode->i_blocks = ((i_size_read(inode) + (p_fs->cluster_size - 1)) - & ~((loff_t)p_fs->cluster_size - 1)) >> 9; - EXFAT_I(inode)->i_pos = ((loff_t)p_fs->root_dir << 32) | 0xffffffff; - EXFAT_I(inode)->mmu_private = i_size_read(inode); - - exfat_save_attr(inode, ATTR_SUBDIR); - curtime = current_time(inode); - inode->i_mtime = curtime; - inode->i_atime = curtime; - inode->i_ctime = curtime; - set_nlink(inode, info.num_subdirs + 2); - - return 0; -} - -static void setup_dops(struct super_block *sb) -{ - if (EXFAT_SB(sb)->options.casesensitive == 0) - sb->s_d_op = &exfat_ci_dentry_ops; - else - sb->s_d_op = &exfat_dentry_ops; -} - -static int exfat_fill_super(struct super_block *sb, void *data, int silent) -{ - struct inode *root_inode = NULL; - struct exfat_sb_info *sbi; - int debug, ret; - long error; - - /* - * GFP_KERNEL is ok here, because while we do hold the - * supeblock lock, memory pressure can't call back into - * the filesystem, since we're only just about to mount - * it and have no inodes etc active! - */ - sbi = kvzalloc(sizeof(*sbi), GFP_KERNEL); - if (!sbi) - return -ENOMEM; - mutex_init(&sbi->s_lock); - sb->s_fs_info = sbi; - sb->s_flags |= SB_NODIRATIME; - sb->s_magic = EXFAT_SUPER_MAGIC; - sb->s_op = &exfat_sops; - sb->s_export_op = &exfat_export_ops; - - error = parse_options(data, silent, &debug, &sbi->options); - if (error) - goto out_fail; - - setup_dops(sb); - - error = -EIO; - sb_min_blocksize(sb, 512); - sb->s_maxbytes = 0x7fffffffffffffffLL; /* maximum file size */ - - ret = ffsMountVol(sb); - if (ret) { - if (!silent) - pr_err("[EXFAT] ffsMountVol failed\n"); - - goto out_fail; - } - - /* set up enough so that it can read an inode */ - exfat_hash_init(sb); - - /* - * The low byte of FAT's first entry must have same value with - * media-field. But in real world, too many devices is - * writing wrong value. So, removed that validity check. - * - * if (FAT_FIRST_ENT(sb, media) != first) - */ - - sbi->nls_io = load_nls(sbi->options.iocharset); - - error = -ENOMEM; - root_inode = new_inode(sb); - if (!root_inode) - goto out_fail2; - root_inode->i_ino = EXFAT_ROOT_INO; - SET_IVERSION(root_inode, 1); - - error = exfat_read_root(root_inode); - if (error < 0) - goto out_fail2; - error = -ENOMEM; - exfat_attach(root_inode, EXFAT_I(root_inode)->i_pos); - insert_inode_hash(root_inode); - sb->s_root = d_make_root(root_inode); - if (!sb->s_root) { - pr_err("[EXFAT] Getting the root inode failed\n"); - goto out_fail2; - } - - return 0; - -out_fail2: - ffsUmountVol(sb); -out_fail: - if (root_inode) - iput(root_inode); - sb->s_fs_info = NULL; - exfat_free_super(sbi); - return error; -} - -static struct dentry *exfat_fs_mount(struct file_system_type *fs_type, - int flags, const char *dev_name, - void *data) -{ - return mount_bdev(fs_type, flags, dev_name, data, exfat_fill_super); -} - -static void init_once(void *foo) -{ - struct exfat_inode_info *ei = (struct exfat_inode_info *)foo; - - INIT_HLIST_NODE(&ei->i_hash_fat); - inode_init_once(&ei->vfs_inode); -} - -static int __init exfat_init_inodecache(void) -{ - exfat_inode_cachep = kmem_cache_create("exfat_inode_cache", - sizeof(struct exfat_inode_info), - 0, - (SLAB_RECLAIM_ACCOUNT | - SLAB_MEM_SPREAD), - init_once); - if (!exfat_inode_cachep) - return -ENOMEM; - return 0; -} - -static void __exit exfat_destroy_inodecache(void) -{ - /* - * Make sure all delayed rcu free inodes are flushed before we - * destroy cache. - */ - rcu_barrier(); - kmem_cache_destroy(exfat_inode_cachep); -} - -#ifdef CONFIG_STAGING_EXFAT_KERNEL_DEBUG -static void exfat_debug_kill_sb(struct super_block *sb) -{ - struct exfat_sb_info *sbi = EXFAT_SB(sb); - struct block_device *bdev = sb->s_bdev; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - - long flags; - - if (sbi) { - flags = sbi->debug_flags; - - if (flags & EXFAT_DEBUGFLAGS_INVALID_UMOUNT) { - /* - * invalidate_bdev drops all device cache include - * dirty. We use this to simulate device removal. - */ - mutex_lock(&p_fs->v_mutex); - exfat_fat_release_all(sb); - exfat_buf_release_all(sb); - mutex_unlock(&p_fs->v_mutex); - - invalidate_bdev(bdev); - } - } - - kill_block_super(sb); -} -#endif /* CONFIG_STAGING_EXFAT_KERNEL_DEBUG */ - -static struct file_system_type exfat_fs_type = { - .owner = THIS_MODULE, - .name = "exfat", - .mount = exfat_fs_mount, -#ifdef CONFIG_STAGING_EXFAT_KERNEL_DEBUG - .kill_sb = exfat_debug_kill_sb, -#else - .kill_sb = kill_block_super, -#endif /* CONFIG_STAGING_EXFAT_KERNEL_DEBUG */ - .fs_flags = FS_REQUIRES_DEV, -}; - -static int __init init_exfat(void) -{ - int err; - - BUILD_BUG_ON(sizeof(struct dentry_t) != DENTRY_SIZE); - BUILD_BUG_ON(sizeof(struct file_dentry_t) != DENTRY_SIZE); - BUILD_BUG_ON(sizeof(struct strm_dentry_t) != DENTRY_SIZE); - BUILD_BUG_ON(sizeof(struct name_dentry_t) != DENTRY_SIZE); - BUILD_BUG_ON(sizeof(struct bmap_dentry_t) != DENTRY_SIZE); - BUILD_BUG_ON(sizeof(struct case_dentry_t) != DENTRY_SIZE); - BUILD_BUG_ON(sizeof(struct volm_dentry_t) != DENTRY_SIZE); - - pr_info("exFAT: Version %s\n", EXFAT_VERSION); - - err = exfat_init_inodecache(); - if (err) - return err; - - err = register_filesystem(&exfat_fs_type); - if (err) - return err; - - return 0; -} - -static void __exit exit_exfat(void) -{ - exfat_destroy_inodecache(); - unregister_filesystem(&exfat_fs_type); -} - -module_init(init_exfat); -module_exit(exit_exfat); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("exFAT Filesystem Driver"); -MODULE_ALIAS_FS("exfat"); diff --git a/drivers/staging/exfat/exfat_upcase.c b/drivers/staging/exfat/exfat_upcase.c deleted file mode 100644 index b91a1faa0e50..000000000000 --- a/drivers/staging/exfat/exfat_upcase.c +++ /dev/null @@ -1,740 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. - */ - -#include -#include "exfat.h" - -const u8 uni_upcase[NUM_UPCASE << 1] = { - 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, - 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, - 0x08, 0x00, 0x09, 0x00, 0x0A, 0x00, 0x0B, 0x00, - 0x0C, 0x00, 0x0D, 0x00, 0x0E, 0x00, 0x0F, 0x00, - 0x10, 0x00, 0x11, 0x00, 0x12, 0x00, 0x13, 0x00, - 0x14, 0x00, 0x15, 0x00, 0x16, 0x00, 0x17, 0x00, - 0x18, 0x00, 0x19, 0x00, 0x1A, 0x00, 0x1B, 0x00, - 0x1C, 0x00, 0x1D, 0x00, 0x1E, 0x00, 0x1F, 0x00, - 0x20, 0x00, 0x21, 0x00, 0x22, 0x00, 0x23, 0x00, - 0x24, 0x00, 0x25, 0x00, 0x26, 0x00, 0x27, 0x00, - 0x28, 0x00, 0x29, 0x00, 0x2A, 0x00, 0x2B, 0x00, - 0x2C, 0x00, 0x2D, 0x00, 0x2E, 0x00, 0x2F, 0x00, - 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, - 0x34, 0x00, 0x35, 0x00, 0x36, 0x00, 0x37, 0x00, - 0x38, 0x00, 0x39, 0x00, 0x3A, 0x00, 0x3B, 0x00, - 0x3C, 0x00, 0x3D, 0x00, 0x3E, 0x00, 0x3F, 0x00, - 0x40, 0x00, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, - 0x44, 0x00, 0x45, 0x00, 0x46, 0x00, 0x47, 0x00, - 0x48, 0x00, 0x49, 0x00, 0x4A, 0x00, 0x4B, 0x00, - 0x4C, 0x00, 0x4D, 0x00, 0x4E, 0x00, 0x4F, 0x00, - 0x50, 0x00, 0x51, 0x00, 0x52, 0x00, 0x53, 0x00, - 0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x57, 0x00, - 0x58, 0x00, 0x59, 0x00, 0x5A, 0x00, 0x5B, 0x00, - 0x5C, 0x00, 0x5D, 0x00, 0x5E, 0x00, 0x5F, 0x00, - 0x60, 0x00, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, - 0x44, 0x00, 0x45, 0x00, 0x46, 0x00, 0x47, 0x00, - 0x48, 0x00, 0x49, 0x00, 0x4A, 0x00, 0x4B, 0x00, - 0x4C, 0x00, 0x4D, 0x00, 0x4E, 0x00, 0x4F, 0x00, - 0x50, 0x00, 0x51, 0x00, 0x52, 0x00, 0x53, 0x00, - 0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x57, 0x00, - 0x58, 0x00, 0x59, 0x00, 0x5A, 0x00, 0x7B, 0x00, - 0x7C, 0x00, 0x7D, 0x00, 0x7E, 0x00, 0x7F, 0x00, - 0x80, 0x00, 0x81, 0x00, 0x82, 0x00, 0x83, 0x00, - 0x84, 0x00, 0x85, 0x00, 0x86, 0x00, 0x87, 0x00, - 0x88, 0x00, 0x89, 0x00, 0x8A, 0x00, 0x8B, 0x00, - 0x8C, 0x00, 0x8D, 0x00, 0x8E, 0x00, 0x8F, 0x00, - 0x90, 0x00, 0x91, 0x00, 0x92, 0x00, 0x93, 0x00, - 0x94, 0x00, 0x95, 0x00, 0x96, 0x00, 0x97, 0x00, - 0x98, 0x00, 0x99, 0x00, 0x9A, 0x00, 0x9B, 0x00, - 0x9C, 0x00, 0x9D, 0x00, 0x9E, 0x00, 0x9F, 0x00, - 0xA0, 0x00, 0xA1, 0x00, 0xA2, 0x00, 0xA3, 0x00, - 0xA4, 0x00, 0xA5, 0x00, 0xA6, 0x00, 0xA7, 0x00, - 0xA8, 0x00, 0xA9, 0x00, 0xAA, 0x00, 0xAB, 0x00, - 0xAC, 0x00, 0xAD, 0x00, 0xAE, 0x00, 0xAF, 0x00, - 0xB0, 0x00, 0xB1, 0x00, 0xB2, 0x00, 0xB3, 0x00, - 0xB4, 0x00, 0xB5, 0x00, 0xB6, 0x00, 0xB7, 0x00, - 0xB8, 0x00, 0xB9, 0x00, 0xBA, 0x00, 0xBB, 0x00, - 0xBC, 0x00, 0xBD, 0x00, 0xBE, 0x00, 0xBF, 0x00, - 0xC0, 0x00, 0xC1, 0x00, 0xC2, 0x00, 0xC3, 0x00, - 0xC4, 0x00, 0xC5, 0x00, 0xC6, 0x00, 0xC7, 0x00, - 0xC8, 0x00, 0xC9, 0x00, 0xCA, 0x00, 0xCB, 0x00, - 0xCC, 0x00, 0xCD, 0x00, 0xCE, 0x00, 0xCF, 0x00, - 0xD0, 0x00, 0xD1, 0x00, 0xD2, 0x00, 0xD3, 0x00, - 0xD4, 0x00, 0xD5, 0x00, 0xD6, 0x00, 0xD7, 0x00, - 0xD8, 0x00, 0xD9, 0x00, 0xDA, 0x00, 0xDB, 0x00, - 0xDC, 0x00, 0xDD, 0x00, 0xDE, 0x00, 0xDF, 0x00, - 0xC0, 0x00, 0xC1, 0x00, 0xC2, 0x00, 0xC3, 0x00, - 0xC4, 0x00, 0xC5, 0x00, 0xC6, 0x00, 0xC7, 0x00, - 0xC8, 0x00, 0xC9, 0x00, 0xCA, 0x00, 0xCB, 0x00, - 0xCC, 0x00, 0xCD, 0x00, 0xCE, 0x00, 0xCF, 0x00, - 0xD0, 0x00, 0xD1, 0x00, 0xD2, 0x00, 0xD3, 0x00, - 0xD4, 0x00, 0xD5, 0x00, 0xD6, 0x00, 0xF7, 0x00, - 0xD8, 0x00, 0xD9, 0x00, 0xDA, 0x00, 0xDB, 0x00, - 0xDC, 0x00, 0xDD, 0x00, 0xDE, 0x00, 0x78, 0x01, - 0x00, 0x01, 0x00, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x04, 0x01, 0x04, 0x01, 0x06, 0x01, 0x06, 0x01, - 0x08, 0x01, 0x08, 0x01, 0x0A, 0x01, 0x0A, 0x01, - 0x0C, 0x01, 0x0C, 0x01, 0x0E, 0x01, 0x0E, 0x01, - 0x10, 0x01, 0x10, 0x01, 0x12, 0x01, 0x12, 0x01, - 0x14, 0x01, 0x14, 0x01, 0x16, 0x01, 0x16, 0x01, - 0x18, 0x01, 0x18, 0x01, 0x1A, 0x01, 0x1A, 0x01, - 0x1C, 0x01, 0x1C, 0x01, 0x1E, 0x01, 0x1E, 0x01, - 0x20, 0x01, 0x20, 0x01, 0x22, 0x01, 0x22, 0x01, - 0x24, 0x01, 0x24, 0x01, 0x26, 0x01, 0x26, 0x01, - 0x28, 0x01, 0x28, 0x01, 0x2A, 0x01, 0x2A, 0x01, - 0x2C, 0x01, 0x2C, 0x01, 0x2E, 0x01, 0x2E, 0x01, - 0x30, 0x01, 0x31, 0x01, 0x32, 0x01, 0x32, 0x01, - 0x34, 0x01, 0x34, 0x01, 0x36, 0x01, 0x36, 0x01, - 0x38, 0x01, 0x39, 0x01, 0x39, 0x01, 0x3B, 0x01, - 0x3B, 0x01, 0x3D, 0x01, 0x3D, 0x01, 0x3F, 0x01, - 0x3F, 0x01, 0x41, 0x01, 0x41, 0x01, 0x43, 0x01, - 0x43, 0x01, 0x45, 0x01, 0x45, 0x01, 0x47, 0x01, - 0x47, 0x01, 0x49, 0x01, 0x4A, 0x01, 0x4A, 0x01, - 0x4C, 0x01, 0x4C, 0x01, 0x4E, 0x01, 0x4E, 0x01, - 0x50, 0x01, 0x50, 0x01, 0x52, 0x01, 0x52, 0x01, - 0x54, 0x01, 0x54, 0x01, 0x56, 0x01, 0x56, 0x01, - 0x58, 0x01, 0x58, 0x01, 0x5A, 0x01, 0x5A, 0x01, - 0x5C, 0x01, 0x5C, 0x01, 0x5E, 0x01, 0x5E, 0x01, - 0x60, 0x01, 0x60, 0x01, 0x62, 0x01, 0x62, 0x01, - 0x64, 0x01, 0x64, 0x01, 0x66, 0x01, 0x66, 0x01, - 0x68, 0x01, 0x68, 0x01, 0x6A, 0x01, 0x6A, 0x01, - 0x6C, 0x01, 0x6C, 0x01, 0x6E, 0x01, 0x6E, 0x01, - 0x70, 0x01, 0x70, 0x01, 0x72, 0x01, 0x72, 0x01, - 0x74, 0x01, 0x74, 0x01, 0x76, 0x01, 0x76, 0x01, - 0x78, 0x01, 0x79, 0x01, 0x79, 0x01, 0x7B, 0x01, - 0x7B, 0x01, 0x7D, 0x01, 0x7D, 0x01, 0x7F, 0x01, - 0x43, 0x02, 0x81, 0x01, 0x82, 0x01, 0x82, 0x01, - 0x84, 0x01, 0x84, 0x01, 0x86, 0x01, 0x87, 0x01, - 0x87, 0x01, 0x89, 0x01, 0x8A, 0x01, 0x8B, 0x01, - 0x8B, 0x01, 0x8D, 0x01, 0x8E, 0x01, 0x8F, 0x01, - 0x90, 0x01, 0x91, 0x01, 0x91, 0x01, 0x93, 0x01, - 0x94, 0x01, 0xF6, 0x01, 0x96, 0x01, 0x97, 0x01, - 0x98, 0x01, 0x98, 0x01, 0x3D, 0x02, 0x9B, 0x01, - 0x9C, 0x01, 0x9D, 0x01, 0x20, 0x02, 0x9F, 0x01, - 0xA0, 0x01, 0xA0, 0x01, 0xA2, 0x01, 0xA2, 0x01, - 0xA4, 0x01, 0xA4, 0x01, 0xA6, 0x01, 0xA7, 0x01, - 0xA7, 0x01, 0xA9, 0x01, 0xAA, 0x01, 0xAB, 0x01, - 0xAC, 0x01, 0xAC, 0x01, 0xAE, 0x01, 0xAF, 0x01, - 0xAF, 0x01, 0xB1, 0x01, 0xB2, 0x01, 0xB3, 0x01, - 0xB3, 0x01, 0xB5, 0x01, 0xB5, 0x01, 0xB7, 0x01, - 0xB8, 0x01, 0xB8, 0x01, 0xBA, 0x01, 0xBB, 0x01, - 0xBC, 0x01, 0xBC, 0x01, 0xBE, 0x01, 0xF7, 0x01, - 0xC0, 0x01, 0xC1, 0x01, 0xC2, 0x01, 0xC3, 0x01, - 0xC4, 0x01, 0xC5, 0x01, 0xC4, 0x01, 0xC7, 0x01, - 0xC8, 0x01, 0xC7, 0x01, 0xCA, 0x01, 0xCB, 0x01, - 0xCA, 0x01, 0xCD, 0x01, 0xCD, 0x01, 0xCF, 0x01, - 0xCF, 0x01, 0xD1, 0x01, 0xD1, 0x01, 0xD3, 0x01, - 0xD3, 0x01, 0xD5, 0x01, 0xD5, 0x01, 0xD7, 0x01, - 0xD7, 0x01, 0xD9, 0x01, 0xD9, 0x01, 0xDB, 0x01, - 0xDB, 0x01, 0x8E, 0x01, 0xDE, 0x01, 0xDE, 0x01, - 0xE0, 0x01, 0xE0, 0x01, 0xE2, 0x01, 0xE2, 0x01, - 0xE4, 0x01, 0xE4, 0x01, 0xE6, 0x01, 0xE6, 0x01, - 0xE8, 0x01, 0xE8, 0x01, 0xEA, 0x01, 0xEA, 0x01, - 0xEC, 0x01, 0xEC, 0x01, 0xEE, 0x01, 0xEE, 0x01, - 0xF0, 0x01, 0xF1, 0x01, 0xF2, 0x01, 0xF1, 0x01, - 0xF4, 0x01, 0xF4, 0x01, 0xF6, 0x01, 0xF7, 0x01, - 0xF8, 0x01, 0xF8, 0x01, 0xFA, 0x01, 0xFA, 0x01, - 0xFC, 0x01, 0xFC, 0x01, 0xFE, 0x01, 0xFE, 0x01, - 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x04, 0x02, 0x04, 0x02, 0x06, 0x02, 0x06, 0x02, - 0x08, 0x02, 0x08, 0x02, 0x0A, 0x02, 0x0A, 0x02, - 0x0C, 0x02, 0x0C, 0x02, 0x0E, 0x02, 0x0E, 0x02, - 0x10, 0x02, 0x10, 0x02, 0x12, 0x02, 0x12, 0x02, - 0x14, 0x02, 0x14, 0x02, 0x16, 0x02, 0x16, 0x02, - 0x18, 0x02, 0x18, 0x02, 0x1A, 0x02, 0x1A, 0x02, - 0x1C, 0x02, 0x1C, 0x02, 0x1E, 0x02, 0x1E, 0x02, - 0x20, 0x02, 0x21, 0x02, 0x22, 0x02, 0x22, 0x02, - 0x24, 0x02, 0x24, 0x02, 0x26, 0x02, 0x26, 0x02, - 0x28, 0x02, 0x28, 0x02, 0x2A, 0x02, 0x2A, 0x02, - 0x2C, 0x02, 0x2C, 0x02, 0x2E, 0x02, 0x2E, 0x02, - 0x30, 0x02, 0x30, 0x02, 0x32, 0x02, 0x32, 0x02, - 0x34, 0x02, 0x35, 0x02, 0x36, 0x02, 0x37, 0x02, - 0x38, 0x02, 0x39, 0x02, 0x65, 0x2C, 0x3B, 0x02, - 0x3B, 0x02, 0x3D, 0x02, 0x66, 0x2C, 0x3F, 0x02, - 0x40, 0x02, 0x41, 0x02, 0x41, 0x02, 0x43, 0x02, - 0x44, 0x02, 0x45, 0x02, 0x46, 0x02, 0x46, 0x02, - 0x48, 0x02, 0x48, 0x02, 0x4A, 0x02, 0x4A, 0x02, - 0x4C, 0x02, 0x4C, 0x02, 0x4E, 0x02, 0x4E, 0x02, - 0x50, 0x02, 0x51, 0x02, 0x52, 0x02, 0x81, 0x01, - 0x86, 0x01, 0x55, 0x02, 0x89, 0x01, 0x8A, 0x01, - 0x58, 0x02, 0x8F, 0x01, 0x5A, 0x02, 0x90, 0x01, - 0x5C, 0x02, 0x5D, 0x02, 0x5E, 0x02, 0x5F, 0x02, - 0x93, 0x01, 0x61, 0x02, 0x62, 0x02, 0x94, 0x01, - 0x64, 0x02, 0x65, 0x02, 0x66, 0x02, 0x67, 0x02, - 0x97, 0x01, 0x96, 0x01, 0x6A, 0x02, 0x62, 0x2C, - 0x6C, 0x02, 0x6D, 0x02, 0x6E, 0x02, 0x9C, 0x01, - 0x70, 0x02, 0x71, 0x02, 0x9D, 0x01, 0x73, 0x02, - 0x74, 0x02, 0x9F, 0x01, 0x76, 0x02, 0x77, 0x02, - 0x78, 0x02, 0x79, 0x02, 0x7A, 0x02, 0x7B, 0x02, - 0x7C, 0x02, 0x64, 0x2C, 0x7E, 0x02, 0x7F, 0x02, - 0xA6, 0x01, 0x81, 0x02, 0x82, 0x02, 0xA9, 0x01, - 0x84, 0x02, 0x85, 0x02, 0x86, 0x02, 0x87, 0x02, - 0xAE, 0x01, 0x44, 0x02, 0xB1, 0x01, 0xB2, 0x01, - 0x45, 0x02, 0x8D, 0x02, 0x8E, 0x02, 0x8F, 0x02, - 0x90, 0x02, 0x91, 0x02, 0xB7, 0x01, 0x93, 0x02, - 0x94, 0x02, 0x95, 0x02, 0x96, 0x02, 0x97, 0x02, - 0x98, 0x02, 0x99, 0x02, 0x9A, 0x02, 0x9B, 0x02, - 0x9C, 0x02, 0x9D, 0x02, 0x9E, 0x02, 0x9F, 0x02, - 0xA0, 0x02, 0xA1, 0x02, 0xA2, 0x02, 0xA3, 0x02, - 0xA4, 0x02, 0xA5, 0x02, 0xA6, 0x02, 0xA7, 0x02, - 0xA8, 0x02, 0xA9, 0x02, 0xAA, 0x02, 0xAB, 0x02, - 0xAC, 0x02, 0xAD, 0x02, 0xAE, 0x02, 0xAF, 0x02, - 0xB0, 0x02, 0xB1, 0x02, 0xB2, 0x02, 0xB3, 0x02, - 0xB4, 0x02, 0xB5, 0x02, 0xB6, 0x02, 0xB7, 0x02, - 0xB8, 0x02, 0xB9, 0x02, 0xBA, 0x02, 0xBB, 0x02, - 0xBC, 0x02, 0xBD, 0x02, 0xBE, 0x02, 0xBF, 0x02, - 0xC0, 0x02, 0xC1, 0x02, 0xC2, 0x02, 0xC3, 0x02, - 0xC4, 0x02, 0xC5, 0x02, 0xC6, 0x02, 0xC7, 0x02, - 0xC8, 0x02, 0xC9, 0x02, 0xCA, 0x02, 0xCB, 0x02, - 0xCC, 0x02, 0xCD, 0x02, 0xCE, 0x02, 0xCF, 0x02, - 0xD0, 0x02, 0xD1, 0x02, 0xD2, 0x02, 0xD3, 0x02, - 0xD4, 0x02, 0xD5, 0x02, 0xD6, 0x02, 0xD7, 0x02, - 0xD8, 0x02, 0xD9, 0x02, 0xDA, 0x02, 0xDB, 0x02, - 0xDC, 0x02, 0xDD, 0x02, 0xDE, 0x02, 0xDF, 0x02, - 0xE0, 0x02, 0xE1, 0x02, 0xE2, 0x02, 0xE3, 0x02, - 0xE4, 0x02, 0xE5, 0x02, 0xE6, 0x02, 0xE7, 0x02, - 0xE8, 0x02, 0xE9, 0x02, 0xEA, 0x02, 0xEB, 0x02, - 0xEC, 0x02, 0xED, 0x02, 0xEE, 0x02, 0xEF, 0x02, - 0xF0, 0x02, 0xF1, 0x02, 0xF2, 0x02, 0xF3, 0x02, - 0xF4, 0x02, 0xF5, 0x02, 0xF6, 0x02, 0xF7, 0x02, - 0xF8, 0x02, 0xF9, 0x02, 0xFA, 0x02, 0xFB, 0x02, - 0xFC, 0x02, 0xFD, 0x02, 0xFE, 0x02, 0xFF, 0x02, - 0x00, 0x03, 0x01, 0x03, 0x02, 0x03, 0x03, 0x03, - 0x04, 0x03, 0x05, 0x03, 0x06, 0x03, 0x07, 0x03, - 0x08, 0x03, 0x09, 0x03, 0x0A, 0x03, 0x0B, 0x03, - 0x0C, 0x03, 0x0D, 0x03, 0x0E, 0x03, 0x0F, 0x03, - 0x10, 0x03, 0x11, 0x03, 0x12, 0x03, 0x13, 0x03, - 0x14, 0x03, 0x15, 0x03, 0x16, 0x03, 0x17, 0x03, - 0x18, 0x03, 0x19, 0x03, 0x1A, 0x03, 0x1B, 0x03, - 0x1C, 0x03, 0x1D, 0x03, 0x1E, 0x03, 0x1F, 0x03, - 0x20, 0x03, 0x21, 0x03, 0x22, 0x03, 0x23, 0x03, - 0x24, 0x03, 0x25, 0x03, 0x26, 0x03, 0x27, 0x03, - 0x28, 0x03, 0x29, 0x03, 0x2A, 0x03, 0x2B, 0x03, - 0x2C, 0x03, 0x2D, 0x03, 0x2E, 0x03, 0x2F, 0x03, - 0x30, 0x03, 0x31, 0x03, 0x32, 0x03, 0x33, 0x03, - 0x34, 0x03, 0x35, 0x03, 0x36, 0x03, 0x37, 0x03, - 0x38, 0x03, 0x39, 0x03, 0x3A, 0x03, 0x3B, 0x03, - 0x3C, 0x03, 0x3D, 0x03, 0x3E, 0x03, 0x3F, 0x03, - 0x40, 0x03, 0x41, 0x03, 0x42, 0x03, 0x43, 0x03, - 0x44, 0x03, 0x45, 0x03, 0x46, 0x03, 0x47, 0x03, - 0x48, 0x03, 0x49, 0x03, 0x4A, 0x03, 0x4B, 0x03, - 0x4C, 0x03, 0x4D, 0x03, 0x4E, 0x03, 0x4F, 0x03, - 0x50, 0x03, 0x51, 0x03, 0x52, 0x03, 0x53, 0x03, - 0x54, 0x03, 0x55, 0x03, 0x56, 0x03, 0x57, 0x03, - 0x58, 0x03, 0x59, 0x03, 0x5A, 0x03, 0x5B, 0x03, - 0x5C, 0x03, 0x5D, 0x03, 0x5E, 0x03, 0x5F, 0x03, - 0x60, 0x03, 0x61, 0x03, 0x62, 0x03, 0x63, 0x03, - 0x64, 0x03, 0x65, 0x03, 0x66, 0x03, 0x67, 0x03, - 0x68, 0x03, 0x69, 0x03, 0x6A, 0x03, 0x6B, 0x03, - 0x6C, 0x03, 0x6D, 0x03, 0x6E, 0x03, 0x6F, 0x03, - 0x70, 0x03, 0x71, 0x03, 0x72, 0x03, 0x73, 0x03, - 0x74, 0x03, 0x75, 0x03, 0x76, 0x03, 0x77, 0x03, - 0x78, 0x03, 0x79, 0x03, 0x7A, 0x03, 0xFD, 0x03, - 0xFE, 0x03, 0xFF, 0x03, 0x7E, 0x03, 0x7F, 0x03, - 0x80, 0x03, 0x81, 0x03, 0x82, 0x03, 0x83, 0x03, - 0x84, 0x03, 0x85, 0x03, 0x86, 0x03, 0x87, 0x03, - 0x88, 0x03, 0x89, 0x03, 0x8A, 0x03, 0x8B, 0x03, - 0x8C, 0x03, 0x8D, 0x03, 0x8E, 0x03, 0x8F, 0x03, - 0x90, 0x03, 0x91, 0x03, 0x92, 0x03, 0x93, 0x03, - 0x94, 0x03, 0x95, 0x03, 0x96, 0x03, 0x97, 0x03, - 0x98, 0x03, 0x99, 0x03, 0x9A, 0x03, 0x9B, 0x03, - 0x9C, 0x03, 0x9D, 0x03, 0x9E, 0x03, 0x9F, 0x03, - 0xA0, 0x03, 0xA1, 0x03, 0xA2, 0x03, 0xA3, 0x03, - 0xA4, 0x03, 0xA5, 0x03, 0xA6, 0x03, 0xA7, 0x03, - 0xA8, 0x03, 0xA9, 0x03, 0xAA, 0x03, 0xAB, 0x03, - 0x86, 0x03, 0x88, 0x03, 0x89, 0x03, 0x8A, 0x03, - 0xB0, 0x03, 0x91, 0x03, 0x92, 0x03, 0x93, 0x03, - 0x94, 0x03, 0x95, 0x03, 0x96, 0x03, 0x97, 0x03, - 0x98, 0x03, 0x99, 0x03, 0x9A, 0x03, 0x9B, 0x03, - 0x9C, 0x03, 0x9D, 0x03, 0x9E, 0x03, 0x9F, 0x03, - 0xA0, 0x03, 0xA1, 0x03, 0xA3, 0x03, 0xA3, 0x03, - 0xA4, 0x03, 0xA5, 0x03, 0xA6, 0x03, 0xA7, 0x03, - 0xA8, 0x03, 0xA9, 0x03, 0xAA, 0x03, 0xAB, 0x03, - 0x8C, 0x03, 0x8E, 0x03, 0x8F, 0x03, 0xCF, 0x03, - 0xD0, 0x03, 0xD1, 0x03, 0xD2, 0x03, 0xD3, 0x03, - 0xD4, 0x03, 0xD5, 0x03, 0xD6, 0x03, 0xD7, 0x03, - 0xD8, 0x03, 0xD8, 0x03, 0xDA, 0x03, 0xDA, 0x03, - 0xDC, 0x03, 0xDC, 0x03, 0xDE, 0x03, 0xDE, 0x03, - 0xE0, 0x03, 0xE0, 0x03, 0xE2, 0x03, 0xE2, 0x03, - 0xE4, 0x03, 0xE4, 0x03, 0xE6, 0x03, 0xE6, 0x03, - 0xE8, 0x03, 0xE8, 0x03, 0xEA, 0x03, 0xEA, 0x03, - 0xEC, 0x03, 0xEC, 0x03, 0xEE, 0x03, 0xEE, 0x03, - 0xF0, 0x03, 0xF1, 0x03, 0xF9, 0x03, 0xF3, 0x03, - 0xF4, 0x03, 0xF5, 0x03, 0xF6, 0x03, 0xF7, 0x03, - 0xF7, 0x03, 0xF9, 0x03, 0xFA, 0x03, 0xFA, 0x03, - 0xFC, 0x03, 0xFD, 0x03, 0xFE, 0x03, 0xFF, 0x03, - 0x00, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x04, - 0x04, 0x04, 0x05, 0x04, 0x06, 0x04, 0x07, 0x04, - 0x08, 0x04, 0x09, 0x04, 0x0A, 0x04, 0x0B, 0x04, - 0x0C, 0x04, 0x0D, 0x04, 0x0E, 0x04, 0x0F, 0x04, - 0x10, 0x04, 0x11, 0x04, 0x12, 0x04, 0x13, 0x04, - 0x14, 0x04, 0x15, 0x04, 0x16, 0x04, 0x17, 0x04, - 0x18, 0x04, 0x19, 0x04, 0x1A, 0x04, 0x1B, 0x04, - 0x1C, 0x04, 0x1D, 0x04, 0x1E, 0x04, 0x1F, 0x04, - 0x20, 0x04, 0x21, 0x04, 0x22, 0x04, 0x23, 0x04, - 0x24, 0x04, 0x25, 0x04, 0x26, 0x04, 0x27, 0x04, - 0x28, 0x04, 0x29, 0x04, 0x2A, 0x04, 0x2B, 0x04, - 0x2C, 0x04, 0x2D, 0x04, 0x2E, 0x04, 0x2F, 0x04, - 0x10, 0x04, 0x11, 0x04, 0x12, 0x04, 0x13, 0x04, - 0x14, 0x04, 0x15, 0x04, 0x16, 0x04, 0x17, 0x04, - 0x18, 0x04, 0x19, 0x04, 0x1A, 0x04, 0x1B, 0x04, - 0x1C, 0x04, 0x1D, 0x04, 0x1E, 0x04, 0x1F, 0x04, - 0x20, 0x04, 0x21, 0x04, 0x22, 0x04, 0x23, 0x04, - 0x24, 0x04, 0x25, 0x04, 0x26, 0x04, 0x27, 0x04, - 0x28, 0x04, 0x29, 0x04, 0x2A, 0x04, 0x2B, 0x04, - 0x2C, 0x04, 0x2D, 0x04, 0x2E, 0x04, 0x2F, 0x04, - 0x00, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x04, - 0x04, 0x04, 0x05, 0x04, 0x06, 0x04, 0x07, 0x04, - 0x08, 0x04, 0x09, 0x04, 0x0A, 0x04, 0x0B, 0x04, - 0x0C, 0x04, 0x0D, 0x04, 0x0E, 0x04, 0x0F, 0x04, - 0x60, 0x04, 0x60, 0x04, 0x62, 0x04, 0x62, 0x04, - 0x64, 0x04, 0x64, 0x04, 0x66, 0x04, 0x66, 0x04, - 0x68, 0x04, 0x68, 0x04, 0x6A, 0x04, 0x6A, 0x04, - 0x6C, 0x04, 0x6C, 0x04, 0x6E, 0x04, 0x6E, 0x04, - 0x70, 0x04, 0x70, 0x04, 0x72, 0x04, 0x72, 0x04, - 0x74, 0x04, 0x74, 0x04, 0x76, 0x04, 0x76, 0x04, - 0x78, 0x04, 0x78, 0x04, 0x7A, 0x04, 0x7A, 0x04, - 0x7C, 0x04, 0x7C, 0x04, 0x7E, 0x04, 0x7E, 0x04, - 0x80, 0x04, 0x80, 0x04, 0x82, 0x04, 0x83, 0x04, - 0x84, 0x04, 0x85, 0x04, 0x86, 0x04, 0x87, 0x04, - 0x88, 0x04, 0x89, 0x04, 0x8A, 0x04, 0x8A, 0x04, - 0x8C, 0x04, 0x8C, 0x04, 0x8E, 0x04, 0x8E, 0x04, - 0x90, 0x04, 0x90, 0x04, 0x92, 0x04, 0x92, 0x04, - 0x94, 0x04, 0x94, 0x04, 0x96, 0x04, 0x96, 0x04, - 0x98, 0x04, 0x98, 0x04, 0x9A, 0x04, 0x9A, 0x04, - 0x9C, 0x04, 0x9C, 0x04, 0x9E, 0x04, 0x9E, 0x04, - 0xA0, 0x04, 0xA0, 0x04, 0xA2, 0x04, 0xA2, 0x04, - 0xA4, 0x04, 0xA4, 0x04, 0xA6, 0x04, 0xA6, 0x04, - 0xA8, 0x04, 0xA8, 0x04, 0xAA, 0x04, 0xAA, 0x04, - 0xAC, 0x04, 0xAC, 0x04, 0xAE, 0x04, 0xAE, 0x04, - 0xB0, 0x04, 0xB0, 0x04, 0xB2, 0x04, 0xB2, 0x04, - 0xB4, 0x04, 0xB4, 0x04, 0xB6, 0x04, 0xB6, 0x04, - 0xB8, 0x04, 0xB8, 0x04, 0xBA, 0x04, 0xBA, 0x04, - 0xBC, 0x04, 0xBC, 0x04, 0xBE, 0x04, 0xBE, 0x04, - 0xC0, 0x04, 0xC1, 0x04, 0xC1, 0x04, 0xC3, 0x04, - 0xC3, 0x04, 0xC5, 0x04, 0xC5, 0x04, 0xC7, 0x04, - 0xC7, 0x04, 0xC9, 0x04, 0xC9, 0x04, 0xCB, 0x04, - 0xCB, 0x04, 0xCD, 0x04, 0xCD, 0x04, 0xC0, 0x04, - 0xD0, 0x04, 0xD0, 0x04, 0xD2, 0x04, 0xD2, 0x04, - 0xD4, 0x04, 0xD4, 0x04, 0xD6, 0x04, 0xD6, 0x04, - 0xD8, 0x04, 0xD8, 0x04, 0xDA, 0x04, 0xDA, 0x04, - 0xDC, 0x04, 0xDC, 0x04, 0xDE, 0x04, 0xDE, 0x04, - 0xE0, 0x04, 0xE0, 0x04, 0xE2, 0x04, 0xE2, 0x04, - 0xE4, 0x04, 0xE4, 0x04, 0xE6, 0x04, 0xE6, 0x04, - 0xE8, 0x04, 0xE8, 0x04, 0xEA, 0x04, 0xEA, 0x04, - 0xEC, 0x04, 0xEC, 0x04, 0xEE, 0x04, 0xEE, 0x04, - 0xF0, 0x04, 0xF0, 0x04, 0xF2, 0x04, 0xF2, 0x04, - 0xF4, 0x04, 0xF4, 0x04, 0xF6, 0x04, 0xF6, 0x04, - 0xF8, 0x04, 0xF8, 0x04, 0xFA, 0x04, 0xFA, 0x04, - 0xFC, 0x04, 0xFC, 0x04, 0xFE, 0x04, 0xFE, 0x04, - 0x00, 0x05, 0x00, 0x05, 0x02, 0x05, 0x02, 0x05, - 0x04, 0x05, 0x04, 0x05, 0x06, 0x05, 0x06, 0x05, - 0x08, 0x05, 0x08, 0x05, 0x0A, 0x05, 0x0A, 0x05, - 0x0C, 0x05, 0x0C, 0x05, 0x0E, 0x05, 0x0E, 0x05, - 0x10, 0x05, 0x10, 0x05, 0x12, 0x05, 0x12, 0x05, - 0x14, 0x05, 0x15, 0x05, 0x16, 0x05, 0x17, 0x05, - 0x18, 0x05, 0x19, 0x05, 0x1A, 0x05, 0x1B, 0x05, - 0x1C, 0x05, 0x1D, 0x05, 0x1E, 0x05, 0x1F, 0x05, - 0x20, 0x05, 0x21, 0x05, 0x22, 0x05, 0x23, 0x05, - 0x24, 0x05, 0x25, 0x05, 0x26, 0x05, 0x27, 0x05, - 0x28, 0x05, 0x29, 0x05, 0x2A, 0x05, 0x2B, 0x05, - 0x2C, 0x05, 0x2D, 0x05, 0x2E, 0x05, 0x2F, 0x05, - 0x30, 0x05, 0x31, 0x05, 0x32, 0x05, 0x33, 0x05, - 0x34, 0x05, 0x35, 0x05, 0x36, 0x05, 0x37, 0x05, - 0x38, 0x05, 0x39, 0x05, 0x3A, 0x05, 0x3B, 0x05, - 0x3C, 0x05, 0x3D, 0x05, 0x3E, 0x05, 0x3F, 0x05, - 0x40, 0x05, 0x41, 0x05, 0x42, 0x05, 0x43, 0x05, - 0x44, 0x05, 0x45, 0x05, 0x46, 0x05, 0x47, 0x05, - 0x48, 0x05, 0x49, 0x05, 0x4A, 0x05, 0x4B, 0x05, - 0x4C, 0x05, 0x4D, 0x05, 0x4E, 0x05, 0x4F, 0x05, - 0x50, 0x05, 0x51, 0x05, 0x52, 0x05, 0x53, 0x05, - 0x54, 0x05, 0x55, 0x05, 0x56, 0x05, 0x57, 0x05, - 0x58, 0x05, 0x59, 0x05, 0x5A, 0x05, 0x5B, 0x05, - 0x5C, 0x05, 0x5D, 0x05, 0x5E, 0x05, 0x5F, 0x05, - 0x60, 0x05, 0x31, 0x05, 0x32, 0x05, 0x33, 0x05, - 0x34, 0x05, 0x35, 0x05, 0x36, 0x05, 0x37, 0x05, - 0x38, 0x05, 0x39, 0x05, 0x3A, 0x05, 0x3B, 0x05, - 0x3C, 0x05, 0x3D, 0x05, 0x3E, 0x05, 0x3F, 0x05, - 0x40, 0x05, 0x41, 0x05, 0x42, 0x05, 0x43, 0x05, - 0x44, 0x05, 0x45, 0x05, 0x46, 0x05, 0x47, 0x05, - 0x48, 0x05, 0x49, 0x05, 0x4A, 0x05, 0x4B, 0x05, - 0x4C, 0x05, 0x4D, 0x05, 0x4E, 0x05, 0x4F, 0x05, - 0x50, 0x05, 0x51, 0x05, 0x52, 0x05, 0x53, 0x05, - 0x54, 0x05, 0x55, 0x05, 0x56, 0x05, 0xFF, 0xFF, - 0xF6, 0x17, 0x63, 0x2C, 0x7E, 0x1D, 0x7F, 0x1D, - 0x80, 0x1D, 0x81, 0x1D, 0x82, 0x1D, 0x83, 0x1D, - 0x84, 0x1D, 0x85, 0x1D, 0x86, 0x1D, 0x87, 0x1D, - 0x88, 0x1D, 0x89, 0x1D, 0x8A, 0x1D, 0x8B, 0x1D, - 0x8C, 0x1D, 0x8D, 0x1D, 0x8E, 0x1D, 0x8F, 0x1D, - 0x90, 0x1D, 0x91, 0x1D, 0x92, 0x1D, 0x93, 0x1D, - 0x94, 0x1D, 0x95, 0x1D, 0x96, 0x1D, 0x97, 0x1D, - 0x98, 0x1D, 0x99, 0x1D, 0x9A, 0x1D, 0x9B, 0x1D, - 0x9C, 0x1D, 0x9D, 0x1D, 0x9E, 0x1D, 0x9F, 0x1D, - 0xA0, 0x1D, 0xA1, 0x1D, 0xA2, 0x1D, 0xA3, 0x1D, - 0xA4, 0x1D, 0xA5, 0x1D, 0xA6, 0x1D, 0xA7, 0x1D, - 0xA8, 0x1D, 0xA9, 0x1D, 0xAA, 0x1D, 0xAB, 0x1D, - 0xAC, 0x1D, 0xAD, 0x1D, 0xAE, 0x1D, 0xAF, 0x1D, - 0xB0, 0x1D, 0xB1, 0x1D, 0xB2, 0x1D, 0xB3, 0x1D, - 0xB4, 0x1D, 0xB5, 0x1D, 0xB6, 0x1D, 0xB7, 0x1D, - 0xB8, 0x1D, 0xB9, 0x1D, 0xBA, 0x1D, 0xBB, 0x1D, - 0xBC, 0x1D, 0xBD, 0x1D, 0xBE, 0x1D, 0xBF, 0x1D, - 0xC0, 0x1D, 0xC1, 0x1D, 0xC2, 0x1D, 0xC3, 0x1D, - 0xC4, 0x1D, 0xC5, 0x1D, 0xC6, 0x1D, 0xC7, 0x1D, - 0xC8, 0x1D, 0xC9, 0x1D, 0xCA, 0x1D, 0xCB, 0x1D, - 0xCC, 0x1D, 0xCD, 0x1D, 0xCE, 0x1D, 0xCF, 0x1D, - 0xD0, 0x1D, 0xD1, 0x1D, 0xD2, 0x1D, 0xD3, 0x1D, - 0xD4, 0x1D, 0xD5, 0x1D, 0xD6, 0x1D, 0xD7, 0x1D, - 0xD8, 0x1D, 0xD9, 0x1D, 0xDA, 0x1D, 0xDB, 0x1D, - 0xDC, 0x1D, 0xDD, 0x1D, 0xDE, 0x1D, 0xDF, 0x1D, - 0xE0, 0x1D, 0xE1, 0x1D, 0xE2, 0x1D, 0xE3, 0x1D, - 0xE4, 0x1D, 0xE5, 0x1D, 0xE6, 0x1D, 0xE7, 0x1D, - 0xE8, 0x1D, 0xE9, 0x1D, 0xEA, 0x1D, 0xEB, 0x1D, - 0xEC, 0x1D, 0xED, 0x1D, 0xEE, 0x1D, 0xEF, 0x1D, - 0xF0, 0x1D, 0xF1, 0x1D, 0xF2, 0x1D, 0xF3, 0x1D, - 0xF4, 0x1D, 0xF5, 0x1D, 0xF6, 0x1D, 0xF7, 0x1D, - 0xF8, 0x1D, 0xF9, 0x1D, 0xFA, 0x1D, 0xFB, 0x1D, - 0xFC, 0x1D, 0xFD, 0x1D, 0xFE, 0x1D, 0xFF, 0x1D, - 0x00, 0x1E, 0x00, 0x1E, 0x02, 0x1E, 0x02, 0x1E, - 0x04, 0x1E, 0x04, 0x1E, 0x06, 0x1E, 0x06, 0x1E, - 0x08, 0x1E, 0x08, 0x1E, 0x0A, 0x1E, 0x0A, 0x1E, - 0x0C, 0x1E, 0x0C, 0x1E, 0x0E, 0x1E, 0x0E, 0x1E, - 0x10, 0x1E, 0x10, 0x1E, 0x12, 0x1E, 0x12, 0x1E, - 0x14, 0x1E, 0x14, 0x1E, 0x16, 0x1E, 0x16, 0x1E, - 0x18, 0x1E, 0x18, 0x1E, 0x1A, 0x1E, 0x1A, 0x1E, - 0x1C, 0x1E, 0x1C, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, - 0x20, 0x1E, 0x20, 0x1E, 0x22, 0x1E, 0x22, 0x1E, - 0x24, 0x1E, 0x24, 0x1E, 0x26, 0x1E, 0x26, 0x1E, - 0x28, 0x1E, 0x28, 0x1E, 0x2A, 0x1E, 0x2A, 0x1E, - 0x2C, 0x1E, 0x2C, 0x1E, 0x2E, 0x1E, 0x2E, 0x1E, - 0x30, 0x1E, 0x30, 0x1E, 0x32, 0x1E, 0x32, 0x1E, - 0x34, 0x1E, 0x34, 0x1E, 0x36, 0x1E, 0x36, 0x1E, - 0x38, 0x1E, 0x38, 0x1E, 0x3A, 0x1E, 0x3A, 0x1E, - 0x3C, 0x1E, 0x3C, 0x1E, 0x3E, 0x1E, 0x3E, 0x1E, - 0x40, 0x1E, 0x40, 0x1E, 0x42, 0x1E, 0x42, 0x1E, - 0x44, 0x1E, 0x44, 0x1E, 0x46, 0x1E, 0x46, 0x1E, - 0x48, 0x1E, 0x48, 0x1E, 0x4A, 0x1E, 0x4A, 0x1E, - 0x4C, 0x1E, 0x4C, 0x1E, 0x4E, 0x1E, 0x4E, 0x1E, - 0x50, 0x1E, 0x50, 0x1E, 0x52, 0x1E, 0x52, 0x1E, - 0x54, 0x1E, 0x54, 0x1E, 0x56, 0x1E, 0x56, 0x1E, - 0x58, 0x1E, 0x58, 0x1E, 0x5A, 0x1E, 0x5A, 0x1E, - 0x5C, 0x1E, 0x5C, 0x1E, 0x5E, 0x1E, 0x5E, 0x1E, - 0x60, 0x1E, 0x60, 0x1E, 0x62, 0x1E, 0x62, 0x1E, - 0x64, 0x1E, 0x64, 0x1E, 0x66, 0x1E, 0x66, 0x1E, - 0x68, 0x1E, 0x68, 0x1E, 0x6A, 0x1E, 0x6A, 0x1E, - 0x6C, 0x1E, 0x6C, 0x1E, 0x6E, 0x1E, 0x6E, 0x1E, - 0x70, 0x1E, 0x70, 0x1E, 0x72, 0x1E, 0x72, 0x1E, - 0x74, 0x1E, 0x74, 0x1E, 0x76, 0x1E, 0x76, 0x1E, - 0x78, 0x1E, 0x78, 0x1E, 0x7A, 0x1E, 0x7A, 0x1E, - 0x7C, 0x1E, 0x7C, 0x1E, 0x7E, 0x1E, 0x7E, 0x1E, - 0x80, 0x1E, 0x80, 0x1E, 0x82, 0x1E, 0x82, 0x1E, - 0x84, 0x1E, 0x84, 0x1E, 0x86, 0x1E, 0x86, 0x1E, - 0x88, 0x1E, 0x88, 0x1E, 0x8A, 0x1E, 0x8A, 0x1E, - 0x8C, 0x1E, 0x8C, 0x1E, 0x8E, 0x1E, 0x8E, 0x1E, - 0x90, 0x1E, 0x90, 0x1E, 0x92, 0x1E, 0x92, 0x1E, - 0x94, 0x1E, 0x94, 0x1E, 0x96, 0x1E, 0x97, 0x1E, - 0x98, 0x1E, 0x99, 0x1E, 0x9A, 0x1E, 0x9B, 0x1E, - 0x9C, 0x1E, 0x9D, 0x1E, 0x9E, 0x1E, 0x9F, 0x1E, - 0xA0, 0x1E, 0xA0, 0x1E, 0xA2, 0x1E, 0xA2, 0x1E, - 0xA4, 0x1E, 0xA4, 0x1E, 0xA6, 0x1E, 0xA6, 0x1E, - 0xA8, 0x1E, 0xA8, 0x1E, 0xAA, 0x1E, 0xAA, 0x1E, - 0xAC, 0x1E, 0xAC, 0x1E, 0xAE, 0x1E, 0xAE, 0x1E, - 0xB0, 0x1E, 0xB0, 0x1E, 0xB2, 0x1E, 0xB2, 0x1E, - 0xB4, 0x1E, 0xB4, 0x1E, 0xB6, 0x1E, 0xB6, 0x1E, - 0xB8, 0x1E, 0xB8, 0x1E, 0xBA, 0x1E, 0xBA, 0x1E, - 0xBC, 0x1E, 0xBC, 0x1E, 0xBE, 0x1E, 0xBE, 0x1E, - 0xC0, 0x1E, 0xC0, 0x1E, 0xC2, 0x1E, 0xC2, 0x1E, - 0xC4, 0x1E, 0xC4, 0x1E, 0xC6, 0x1E, 0xC6, 0x1E, - 0xC8, 0x1E, 0xC8, 0x1E, 0xCA, 0x1E, 0xCA, 0x1E, - 0xCC, 0x1E, 0xCC, 0x1E, 0xCE, 0x1E, 0xCE, 0x1E, - 0xD0, 0x1E, 0xD0, 0x1E, 0xD2, 0x1E, 0xD2, 0x1E, - 0xD4, 0x1E, 0xD4, 0x1E, 0xD6, 0x1E, 0xD6, 0x1E, - 0xD8, 0x1E, 0xD8, 0x1E, 0xDA, 0x1E, 0xDA, 0x1E, - 0xDC, 0x1E, 0xDC, 0x1E, 0xDE, 0x1E, 0xDE, 0x1E, - 0xE0, 0x1E, 0xE0, 0x1E, 0xE2, 0x1E, 0xE2, 0x1E, - 0xE4, 0x1E, 0xE4, 0x1E, 0xE6, 0x1E, 0xE6, 0x1E, - 0xE8, 0x1E, 0xE8, 0x1E, 0xEA, 0x1E, 0xEA, 0x1E, - 0xEC, 0x1E, 0xEC, 0x1E, 0xEE, 0x1E, 0xEE, 0x1E, - 0xF0, 0x1E, 0xF0, 0x1E, 0xF2, 0x1E, 0xF2, 0x1E, - 0xF4, 0x1E, 0xF4, 0x1E, 0xF6, 0x1E, 0xF6, 0x1E, - 0xF8, 0x1E, 0xF8, 0x1E, 0xFA, 0x1E, 0xFB, 0x1E, - 0xFC, 0x1E, 0xFD, 0x1E, 0xFE, 0x1E, 0xFF, 0x1E, - 0x08, 0x1F, 0x09, 0x1F, 0x0A, 0x1F, 0x0B, 0x1F, - 0x0C, 0x1F, 0x0D, 0x1F, 0x0E, 0x1F, 0x0F, 0x1F, - 0x08, 0x1F, 0x09, 0x1F, 0x0A, 0x1F, 0x0B, 0x1F, - 0x0C, 0x1F, 0x0D, 0x1F, 0x0E, 0x1F, 0x0F, 0x1F, - 0x18, 0x1F, 0x19, 0x1F, 0x1A, 0x1F, 0x1B, 0x1F, - 0x1C, 0x1F, 0x1D, 0x1F, 0x16, 0x1F, 0x17, 0x1F, - 0x18, 0x1F, 0x19, 0x1F, 0x1A, 0x1F, 0x1B, 0x1F, - 0x1C, 0x1F, 0x1D, 0x1F, 0x1E, 0x1F, 0x1F, 0x1F, - 0x28, 0x1F, 0x29, 0x1F, 0x2A, 0x1F, 0x2B, 0x1F, - 0x2C, 0x1F, 0x2D, 0x1F, 0x2E, 0x1F, 0x2F, 0x1F, - 0x28, 0x1F, 0x29, 0x1F, 0x2A, 0x1F, 0x2B, 0x1F, - 0x2C, 0x1F, 0x2D, 0x1F, 0x2E, 0x1F, 0x2F, 0x1F, - 0x38, 0x1F, 0x39, 0x1F, 0x3A, 0x1F, 0x3B, 0x1F, - 0x3C, 0x1F, 0x3D, 0x1F, 0x3E, 0x1F, 0x3F, 0x1F, - 0x38, 0x1F, 0x39, 0x1F, 0x3A, 0x1F, 0x3B, 0x1F, - 0x3C, 0x1F, 0x3D, 0x1F, 0x3E, 0x1F, 0x3F, 0x1F, - 0x48, 0x1F, 0x49, 0x1F, 0x4A, 0x1F, 0x4B, 0x1F, - 0x4C, 0x1F, 0x4D, 0x1F, 0x46, 0x1F, 0x47, 0x1F, - 0x48, 0x1F, 0x49, 0x1F, 0x4A, 0x1F, 0x4B, 0x1F, - 0x4C, 0x1F, 0x4D, 0x1F, 0x4E, 0x1F, 0x4F, 0x1F, - 0x50, 0x1F, 0x59, 0x1F, 0x52, 0x1F, 0x5B, 0x1F, - 0x54, 0x1F, 0x5D, 0x1F, 0x56, 0x1F, 0x5F, 0x1F, - 0x58, 0x1F, 0x59, 0x1F, 0x5A, 0x1F, 0x5B, 0x1F, - 0x5C, 0x1F, 0x5D, 0x1F, 0x5E, 0x1F, 0x5F, 0x1F, - 0x68, 0x1F, 0x69, 0x1F, 0x6A, 0x1F, 0x6B, 0x1F, - 0x6C, 0x1F, 0x6D, 0x1F, 0x6E, 0x1F, 0x6F, 0x1F, - 0x68, 0x1F, 0x69, 0x1F, 0x6A, 0x1F, 0x6B, 0x1F, - 0x6C, 0x1F, 0x6D, 0x1F, 0x6E, 0x1F, 0x6F, 0x1F, - 0xBA, 0x1F, 0xBB, 0x1F, 0xC8, 0x1F, 0xC9, 0x1F, - 0xCA, 0x1F, 0xCB, 0x1F, 0xDA, 0x1F, 0xDB, 0x1F, - 0xF8, 0x1F, 0xF9, 0x1F, 0xEA, 0x1F, 0xEB, 0x1F, - 0xFA, 0x1F, 0xFB, 0x1F, 0x7E, 0x1F, 0x7F, 0x1F, - 0x88, 0x1F, 0x89, 0x1F, 0x8A, 0x1F, 0x8B, 0x1F, - 0x8C, 0x1F, 0x8D, 0x1F, 0x8E, 0x1F, 0x8F, 0x1F, - 0x88, 0x1F, 0x89, 0x1F, 0x8A, 0x1F, 0x8B, 0x1F, - 0x8C, 0x1F, 0x8D, 0x1F, 0x8E, 0x1F, 0x8F, 0x1F, - 0x98, 0x1F, 0x99, 0x1F, 0x9A, 0x1F, 0x9B, 0x1F, - 0x9C, 0x1F, 0x9D, 0x1F, 0x9E, 0x1F, 0x9F, 0x1F, - 0x98, 0x1F, 0x99, 0x1F, 0x9A, 0x1F, 0x9B, 0x1F, - 0x9C, 0x1F, 0x9D, 0x1F, 0x9E, 0x1F, 0x9F, 0x1F, - 0xA8, 0x1F, 0xA9, 0x1F, 0xAA, 0x1F, 0xAB, 0x1F, - 0xAC, 0x1F, 0xAD, 0x1F, 0xAE, 0x1F, 0xAF, 0x1F, - 0xA8, 0x1F, 0xA9, 0x1F, 0xAA, 0x1F, 0xAB, 0x1F, - 0xAC, 0x1F, 0xAD, 0x1F, 0xAE, 0x1F, 0xAF, 0x1F, - 0xB8, 0x1F, 0xB9, 0x1F, 0xB2, 0x1F, 0xBC, 0x1F, - 0xB4, 0x1F, 0xB5, 0x1F, 0xB6, 0x1F, 0xB7, 0x1F, - 0xB8, 0x1F, 0xB9, 0x1F, 0xBA, 0x1F, 0xBB, 0x1F, - 0xBC, 0x1F, 0xBD, 0x1F, 0xBE, 0x1F, 0xBF, 0x1F, - 0xC0, 0x1F, 0xC1, 0x1F, 0xC2, 0x1F, 0xC3, 0x1F, - 0xC4, 0x1F, 0xC5, 0x1F, 0xC6, 0x1F, 0xC7, 0x1F, - 0xC8, 0x1F, 0xC9, 0x1F, 0xCA, 0x1F, 0xCB, 0x1F, - 0xC3, 0x1F, 0xCD, 0x1F, 0xCE, 0x1F, 0xCF, 0x1F, - 0xD8, 0x1F, 0xD9, 0x1F, 0xD2, 0x1F, 0xD3, 0x1F, - 0xD4, 0x1F, 0xD5, 0x1F, 0xD6, 0x1F, 0xD7, 0x1F, - 0xD8, 0x1F, 0xD9, 0x1F, 0xDA, 0x1F, 0xDB, 0x1F, - 0xDC, 0x1F, 0xDD, 0x1F, 0xDE, 0x1F, 0xDF, 0x1F, - 0xE8, 0x1F, 0xE9, 0x1F, 0xE2, 0x1F, 0xE3, 0x1F, - 0xE4, 0x1F, 0xEC, 0x1F, 0xE6, 0x1F, 0xE7, 0x1F, - 0xE8, 0x1F, 0xE9, 0x1F, 0xEA, 0x1F, 0xEB, 0x1F, - 0xEC, 0x1F, 0xED, 0x1F, 0xEE, 0x1F, 0xEF, 0x1F, - 0xF0, 0x1F, 0xF1, 0x1F, 0xF2, 0x1F, 0xF3, 0x1F, - 0xF4, 0x1F, 0xF5, 0x1F, 0xF6, 0x1F, 0xF7, 0x1F, - 0xF8, 0x1F, 0xF9, 0x1F, 0xFA, 0x1F, 0xFB, 0x1F, - 0xF3, 0x1F, 0xFD, 0x1F, 0xFE, 0x1F, 0xFF, 0x1F, - 0x00, 0x20, 0x01, 0x20, 0x02, 0x20, 0x03, 0x20, - 0x04, 0x20, 0x05, 0x20, 0x06, 0x20, 0x07, 0x20, - 0x08, 0x20, 0x09, 0x20, 0x0A, 0x20, 0x0B, 0x20, - 0x0C, 0x20, 0x0D, 0x20, 0x0E, 0x20, 0x0F, 0x20, - 0x10, 0x20, 0x11, 0x20, 0x12, 0x20, 0x13, 0x20, - 0x14, 0x20, 0x15, 0x20, 0x16, 0x20, 0x17, 0x20, - 0x18, 0x20, 0x19, 0x20, 0x1A, 0x20, 0x1B, 0x20, - 0x1C, 0x20, 0x1D, 0x20, 0x1E, 0x20, 0x1F, 0x20, - 0x20, 0x20, 0x21, 0x20, 0x22, 0x20, 0x23, 0x20, - 0x24, 0x20, 0x25, 0x20, 0x26, 0x20, 0x27, 0x20, - 0x28, 0x20, 0x29, 0x20, 0x2A, 0x20, 0x2B, 0x20, - 0x2C, 0x20, 0x2D, 0x20, 0x2E, 0x20, 0x2F, 0x20, - 0x30, 0x20, 0x31, 0x20, 0x32, 0x20, 0x33, 0x20, - 0x34, 0x20, 0x35, 0x20, 0x36, 0x20, 0x37, 0x20, - 0x38, 0x20, 0x39, 0x20, 0x3A, 0x20, 0x3B, 0x20, - 0x3C, 0x20, 0x3D, 0x20, 0x3E, 0x20, 0x3F, 0x20, - 0x40, 0x20, 0x41, 0x20, 0x42, 0x20, 0x43, 0x20, - 0x44, 0x20, 0x45, 0x20, 0x46, 0x20, 0x47, 0x20, - 0x48, 0x20, 0x49, 0x20, 0x4A, 0x20, 0x4B, 0x20, - 0x4C, 0x20, 0x4D, 0x20, 0x4E, 0x20, 0x4F, 0x20, - 0x50, 0x20, 0x51, 0x20, 0x52, 0x20, 0x53, 0x20, - 0x54, 0x20, 0x55, 0x20, 0x56, 0x20, 0x57, 0x20, - 0x58, 0x20, 0x59, 0x20, 0x5A, 0x20, 0x5B, 0x20, - 0x5C, 0x20, 0x5D, 0x20, 0x5E, 0x20, 0x5F, 0x20, - 0x60, 0x20, 0x61, 0x20, 0x62, 0x20, 0x63, 0x20, - 0x64, 0x20, 0x65, 0x20, 0x66, 0x20, 0x67, 0x20, - 0x68, 0x20, 0x69, 0x20, 0x6A, 0x20, 0x6B, 0x20, - 0x6C, 0x20, 0x6D, 0x20, 0x6E, 0x20, 0x6F, 0x20, - 0x70, 0x20, 0x71, 0x20, 0x72, 0x20, 0x73, 0x20, - 0x74, 0x20, 0x75, 0x20, 0x76, 0x20, 0x77, 0x20, - 0x78, 0x20, 0x79, 0x20, 0x7A, 0x20, 0x7B, 0x20, - 0x7C, 0x20, 0x7D, 0x20, 0x7E, 0x20, 0x7F, 0x20, - 0x80, 0x20, 0x81, 0x20, 0x82, 0x20, 0x83, 0x20, - 0x84, 0x20, 0x85, 0x20, 0x86, 0x20, 0x87, 0x20, - 0x88, 0x20, 0x89, 0x20, 0x8A, 0x20, 0x8B, 0x20, - 0x8C, 0x20, 0x8D, 0x20, 0x8E, 0x20, 0x8F, 0x20, - 0x90, 0x20, 0x91, 0x20, 0x92, 0x20, 0x93, 0x20, - 0x94, 0x20, 0x95, 0x20, 0x96, 0x20, 0x97, 0x20, - 0x98, 0x20, 0x99, 0x20, 0x9A, 0x20, 0x9B, 0x20, - 0x9C, 0x20, 0x9D, 0x20, 0x9E, 0x20, 0x9F, 0x20, - 0xA0, 0x20, 0xA1, 0x20, 0xA2, 0x20, 0xA3, 0x20, - 0xA4, 0x20, 0xA5, 0x20, 0xA6, 0x20, 0xA7, 0x20, - 0xA8, 0x20, 0xA9, 0x20, 0xAA, 0x20, 0xAB, 0x20, - 0xAC, 0x20, 0xAD, 0x20, 0xAE, 0x20, 0xAF, 0x20, - 0xB0, 0x20, 0xB1, 0x20, 0xB2, 0x20, 0xB3, 0x20, - 0xB4, 0x20, 0xB5, 0x20, 0xB6, 0x20, 0xB7, 0x20, - 0xB8, 0x20, 0xB9, 0x20, 0xBA, 0x20, 0xBB, 0x20, - 0xBC, 0x20, 0xBD, 0x20, 0xBE, 0x20, 0xBF, 0x20, - 0xC0, 0x20, 0xC1, 0x20, 0xC2, 0x20, 0xC3, 0x20, - 0xC4, 0x20, 0xC5, 0x20, 0xC6, 0x20, 0xC7, 0x20, - 0xC8, 0x20, 0xC9, 0x20, 0xCA, 0x20, 0xCB, 0x20, - 0xCC, 0x20, 0xCD, 0x20, 0xCE, 0x20, 0xCF, 0x20, - 0xD0, 0x20, 0xD1, 0x20, 0xD2, 0x20, 0xD3, 0x20, - 0xD4, 0x20, 0xD5, 0x20, 0xD6, 0x20, 0xD7, 0x20, - 0xD8, 0x20, 0xD9, 0x20, 0xDA, 0x20, 0xDB, 0x20, - 0xDC, 0x20, 0xDD, 0x20, 0xDE, 0x20, 0xDF, 0x20, - 0xE0, 0x20, 0xE1, 0x20, 0xE2, 0x20, 0xE3, 0x20, - 0xE4, 0x20, 0xE5, 0x20, 0xE6, 0x20, 0xE7, 0x20, - 0xE8, 0x20, 0xE9, 0x20, 0xEA, 0x20, 0xEB, 0x20, - 0xEC, 0x20, 0xED, 0x20, 0xEE, 0x20, 0xEF, 0x20, - 0xF0, 0x20, 0xF1, 0x20, 0xF2, 0x20, 0xF3, 0x20, - 0xF4, 0x20, 0xF5, 0x20, 0xF6, 0x20, 0xF7, 0x20, - 0xF8, 0x20, 0xF9, 0x20, 0xFA, 0x20, 0xFB, 0x20, - 0xFC, 0x20, 0xFD, 0x20, 0xFE, 0x20, 0xFF, 0x20, - 0x00, 0x21, 0x01, 0x21, 0x02, 0x21, 0x03, 0x21, - 0x04, 0x21, 0x05, 0x21, 0x06, 0x21, 0x07, 0x21, - 0x08, 0x21, 0x09, 0x21, 0x0A, 0x21, 0x0B, 0x21, - 0x0C, 0x21, 0x0D, 0x21, 0x0E, 0x21, 0x0F, 0x21, - 0x10, 0x21, 0x11, 0x21, 0x12, 0x21, 0x13, 0x21, - 0x14, 0x21, 0x15, 0x21, 0x16, 0x21, 0x17, 0x21, - 0x18, 0x21, 0x19, 0x21, 0x1A, 0x21, 0x1B, 0x21, - 0x1C, 0x21, 0x1D, 0x21, 0x1E, 0x21, 0x1F, 0x21, - 0x20, 0x21, 0x21, 0x21, 0x22, 0x21, 0x23, 0x21, - 0x24, 0x21, 0x25, 0x21, 0x26, 0x21, 0x27, 0x21, - 0x28, 0x21, 0x29, 0x21, 0x2A, 0x21, 0x2B, 0x21, - 0x2C, 0x21, 0x2D, 0x21, 0x2E, 0x21, 0x2F, 0x21, - 0x30, 0x21, 0x31, 0x21, 0x32, 0x21, 0x33, 0x21, - 0x34, 0x21, 0x35, 0x21, 0x36, 0x21, 0x37, 0x21, - 0x38, 0x21, 0x39, 0x21, 0x3A, 0x21, 0x3B, 0x21, - 0x3C, 0x21, 0x3D, 0x21, 0x3E, 0x21, 0x3F, 0x21, - 0x40, 0x21, 0x41, 0x21, 0x42, 0x21, 0x43, 0x21, - 0x44, 0x21, 0x45, 0x21, 0x46, 0x21, 0x47, 0x21, - 0x48, 0x21, 0x49, 0x21, 0x4A, 0x21, 0x4B, 0x21, - 0x4C, 0x21, 0x4D, 0x21, 0x32, 0x21, 0x4F, 0x21, - 0x50, 0x21, 0x51, 0x21, 0x52, 0x21, 0x53, 0x21, - 0x54, 0x21, 0x55, 0x21, 0x56, 0x21, 0x57, 0x21, - 0x58, 0x21, 0x59, 0x21, 0x5A, 0x21, 0x5B, 0x21, - 0x5C, 0x21, 0x5D, 0x21, 0x5E, 0x21, 0x5F, 0x21, - 0x60, 0x21, 0x61, 0x21, 0x62, 0x21, 0x63, 0x21, - 0x64, 0x21, 0x65, 0x21, 0x66, 0x21, 0x67, 0x21, - 0x68, 0x21, 0x69, 0x21, 0x6A, 0x21, 0x6B, 0x21, - 0x6C, 0x21, 0x6D, 0x21, 0x6E, 0x21, 0x6F, 0x21, - 0x60, 0x21, 0x61, 0x21, 0x62, 0x21, 0x63, 0x21, - 0x64, 0x21, 0x65, 0x21, 0x66, 0x21, 0x67, 0x21, - 0x68, 0x21, 0x69, 0x21, 0x6A, 0x21, 0x6B, 0x21, - 0x6C, 0x21, 0x6D, 0x21, 0x6E, 0x21, 0x6F, 0x21, - 0x80, 0x21, 0x81, 0x21, 0x82, 0x21, 0x83, 0x21, - 0x83, 0x21, 0xFF, 0xFF, 0x4B, 0x03, 0xB6, 0x24, - 0xB7, 0x24, 0xB8, 0x24, 0xB9, 0x24, 0xBA, 0x24, - 0xBB, 0x24, 0xBC, 0x24, 0xBD, 0x24, 0xBE, 0x24, - 0xBF, 0x24, 0xC0, 0x24, 0xC1, 0x24, 0xC2, 0x24, - 0xC3, 0x24, 0xC4, 0x24, 0xC5, 0x24, 0xC6, 0x24, - 0xC7, 0x24, 0xC8, 0x24, 0xC9, 0x24, 0xCA, 0x24, - 0xCB, 0x24, 0xCC, 0x24, 0xCD, 0x24, 0xCE, 0x24, - 0xCF, 0x24, 0xFF, 0xFF, 0x46, 0x07, 0x00, 0x2C, - 0x01, 0x2C, 0x02, 0x2C, 0x03, 0x2C, 0x04, 0x2C, - 0x05, 0x2C, 0x06, 0x2C, 0x07, 0x2C, 0x08, 0x2C, - 0x09, 0x2C, 0x0A, 0x2C, 0x0B, 0x2C, 0x0C, 0x2C, - 0x0D, 0x2C, 0x0E, 0x2C, 0x0F, 0x2C, 0x10, 0x2C, - 0x11, 0x2C, 0x12, 0x2C, 0x13, 0x2C, 0x14, 0x2C, - 0x15, 0x2C, 0x16, 0x2C, 0x17, 0x2C, 0x18, 0x2C, - 0x19, 0x2C, 0x1A, 0x2C, 0x1B, 0x2C, 0x1C, 0x2C, - 0x1D, 0x2C, 0x1E, 0x2C, 0x1F, 0x2C, 0x20, 0x2C, - 0x21, 0x2C, 0x22, 0x2C, 0x23, 0x2C, 0x24, 0x2C, - 0x25, 0x2C, 0x26, 0x2C, 0x27, 0x2C, 0x28, 0x2C, - 0x29, 0x2C, 0x2A, 0x2C, 0x2B, 0x2C, 0x2C, 0x2C, - 0x2D, 0x2C, 0x2E, 0x2C, 0x5F, 0x2C, 0x60, 0x2C, - 0x60, 0x2C, 0x62, 0x2C, 0x63, 0x2C, 0x64, 0x2C, - 0x65, 0x2C, 0x66, 0x2C, 0x67, 0x2C, 0x67, 0x2C, - 0x69, 0x2C, 0x69, 0x2C, 0x6B, 0x2C, 0x6B, 0x2C, - 0x6D, 0x2C, 0x6E, 0x2C, 0x6F, 0x2C, 0x70, 0x2C, - 0x71, 0x2C, 0x72, 0x2C, 0x73, 0x2C, 0x74, 0x2C, - 0x75, 0x2C, 0x75, 0x2C, 0x77, 0x2C, 0x78, 0x2C, - 0x79, 0x2C, 0x7A, 0x2C, 0x7B, 0x2C, 0x7C, 0x2C, - 0x7D, 0x2C, 0x7E, 0x2C, 0x7F, 0x2C, 0x80, 0x2C, - 0x80, 0x2C, 0x82, 0x2C, 0x82, 0x2C, 0x84, 0x2C, - 0x84, 0x2C, 0x86, 0x2C, 0x86, 0x2C, 0x88, 0x2C, - 0x88, 0x2C, 0x8A, 0x2C, 0x8A, 0x2C, 0x8C, 0x2C, - 0x8C, 0x2C, 0x8E, 0x2C, 0x8E, 0x2C, 0x90, 0x2C, - 0x90, 0x2C, 0x92, 0x2C, 0x92, 0x2C, 0x94, 0x2C, - 0x94, 0x2C, 0x96, 0x2C, 0x96, 0x2C, 0x98, 0x2C, - 0x98, 0x2C, 0x9A, 0x2C, 0x9A, 0x2C, 0x9C, 0x2C, - 0x9C, 0x2C, 0x9E, 0x2C, 0x9E, 0x2C, 0xA0, 0x2C, - 0xA0, 0x2C, 0xA2, 0x2C, 0xA2, 0x2C, 0xA4, 0x2C, - 0xA4, 0x2C, 0xA6, 0x2C, 0xA6, 0x2C, 0xA8, 0x2C, - 0xA8, 0x2C, 0xAA, 0x2C, 0xAA, 0x2C, 0xAC, 0x2C, - 0xAC, 0x2C, 0xAE, 0x2C, 0xAE, 0x2C, 0xB0, 0x2C, - 0xB0, 0x2C, 0xB2, 0x2C, 0xB2, 0x2C, 0xB4, 0x2C, - 0xB4, 0x2C, 0xB6, 0x2C, 0xB6, 0x2C, 0xB8, 0x2C, - 0xB8, 0x2C, 0xBA, 0x2C, 0xBA, 0x2C, 0xBC, 0x2C, - 0xBC, 0x2C, 0xBE, 0x2C, 0xBE, 0x2C, 0xC0, 0x2C, - 0xC0, 0x2C, 0xC2, 0x2C, 0xC2, 0x2C, 0xC4, 0x2C, - 0xC4, 0x2C, 0xC6, 0x2C, 0xC6, 0x2C, 0xC8, 0x2C, - 0xC8, 0x2C, 0xCA, 0x2C, 0xCA, 0x2C, 0xCC, 0x2C, - 0xCC, 0x2C, 0xCE, 0x2C, 0xCE, 0x2C, 0xD0, 0x2C, - 0xD0, 0x2C, 0xD2, 0x2C, 0xD2, 0x2C, 0xD4, 0x2C, - 0xD4, 0x2C, 0xD6, 0x2C, 0xD6, 0x2C, 0xD8, 0x2C, - 0xD8, 0x2C, 0xDA, 0x2C, 0xDA, 0x2C, 0xDC, 0x2C, - 0xDC, 0x2C, 0xDE, 0x2C, 0xDE, 0x2C, 0xE0, 0x2C, - 0xE0, 0x2C, 0xE2, 0x2C, 0xE2, 0x2C, 0xE4, 0x2C, - 0xE5, 0x2C, 0xE6, 0x2C, 0xE7, 0x2C, 0xE8, 0x2C, - 0xE9, 0x2C, 0xEA, 0x2C, 0xEB, 0x2C, 0xEC, 0x2C, - 0xED, 0x2C, 0xEE, 0x2C, 0xEF, 0x2C, 0xF0, 0x2C, - 0xF1, 0x2C, 0xF2, 0x2C, 0xF3, 0x2C, 0xF4, 0x2C, - 0xF5, 0x2C, 0xF6, 0x2C, 0xF7, 0x2C, 0xF8, 0x2C, - 0xF9, 0x2C, 0xFA, 0x2C, 0xFB, 0x2C, 0xFC, 0x2C, - 0xFD, 0x2C, 0xFE, 0x2C, 0xFF, 0x2C, 0xA0, 0x10, - 0xA1, 0x10, 0xA2, 0x10, 0xA3, 0x10, 0xA4, 0x10, - 0xA5, 0x10, 0xA6, 0x10, 0xA7, 0x10, 0xA8, 0x10, - 0xA9, 0x10, 0xAA, 0x10, 0xAB, 0x10, 0xAC, 0x10, - 0xAD, 0x10, 0xAE, 0x10, 0xAF, 0x10, 0xB0, 0x10, - 0xB1, 0x10, 0xB2, 0x10, 0xB3, 0x10, 0xB4, 0x10, - 0xB5, 0x10, 0xB6, 0x10, 0xB7, 0x10, 0xB8, 0x10, - 0xB9, 0x10, 0xBA, 0x10, 0xBB, 0x10, 0xBC, 0x10, - 0xBD, 0x10, 0xBE, 0x10, 0xBF, 0x10, 0xC0, 0x10, - 0xC1, 0x10, 0xC2, 0x10, 0xC3, 0x10, 0xC4, 0x10, - 0xC5, 0x10, 0xFF, 0xFF, 0x1B, 0xD2, 0x21, 0xFF, - 0x22, 0xFF, 0x23, 0xFF, 0x24, 0xFF, 0x25, 0xFF, - 0x26, 0xFF, 0x27, 0xFF, 0x28, 0xFF, 0x29, 0xFF, - 0x2A, 0xFF, 0x2B, 0xFF, 0x2C, 0xFF, 0x2D, 0xFF, - 0x2E, 0xFF, 0x2F, 0xFF, 0x30, 0xFF, 0x31, 0xFF, - 0x32, 0xFF, 0x33, 0xFF, 0x34, 0xFF, 0x35, 0xFF, - 0x36, 0xFF, 0x37, 0xFF, 0x38, 0xFF, 0x39, 0xFF, - 0x3A, 0xFF, 0x5B, 0xFF, 0x5C, 0xFF, 0x5D, 0xFF, - 0x5E, 0xFF, 0x5F, 0xFF, 0x60, 0xFF, 0x61, 0xFF, - 0x62, 0xFF, 0x63, 0xFF, 0x64, 0xFF, 0x65, 0xFF, - 0x66, 0xFF, 0x67, 0xFF, 0x68, 0xFF, 0x69, 0xFF, - 0x6A, 0xFF, 0x6B, 0xFF, 0x6C, 0xFF, 0x6D, 0xFF, - 0x6E, 0xFF, 0x6F, 0xFF, 0x70, 0xFF, 0x71, 0xFF, - 0x72, 0xFF, 0x73, 0xFF, 0x74, 0xFF, 0x75, 0xFF, - 0x76, 0xFF, 0x77, 0xFF, 0x78, 0xFF, 0x79, 0xFF, - 0x7A, 0xFF, 0x7B, 0xFF, 0x7C, 0xFF, 0x7D, 0xFF, - 0x7E, 0xFF, 0x7F, 0xFF, 0x80, 0xFF, 0x81, 0xFF, - 0x82, 0xFF, 0x83, 0xFF, 0x84, 0xFF, 0x85, 0xFF, - 0x86, 0xFF, 0x87, 0xFF, 0x88, 0xFF, 0x89, 0xFF, - 0x8A, 0xFF, 0x8B, 0xFF, 0x8C, 0xFF, 0x8D, 0xFF, - 0x8E, 0xFF, 0x8F, 0xFF, 0x90, 0xFF, 0x91, 0xFF, - 0x92, 0xFF, 0x93, 0xFF, 0x94, 0xFF, 0x95, 0xFF, - 0x96, 0xFF, 0x97, 0xFF, 0x98, 0xFF, 0x99, 0xFF, - 0x9A, 0xFF, 0x9B, 0xFF, 0x9C, 0xFF, 0x9D, 0xFF, - 0x9E, 0xFF, 0x9F, 0xFF, 0xA0, 0xFF, 0xA1, 0xFF, - 0xA2, 0xFF, 0xA3, 0xFF, 0xA4, 0xFF, 0xA5, 0xFF, - 0xA6, 0xFF, 0xA7, 0xFF, 0xA8, 0xFF, 0xA9, 0xFF, - 0xAA, 0xFF, 0xAB, 0xFF, 0xAC, 0xFF, 0xAD, 0xFF, - 0xAE, 0xFF, 0xAF, 0xFF, 0xB0, 0xFF, 0xB1, 0xFF, - 0xB2, 0xFF, 0xB3, 0xFF, 0xB4, 0xFF, 0xB5, 0xFF, - 0xB6, 0xFF, 0xB7, 0xFF, 0xB8, 0xFF, 0xB9, 0xFF, - 0xBA, 0xFF, 0xBB, 0xFF, 0xBC, 0xFF, 0xBD, 0xFF, - 0xBE, 0xFF, 0xBF, 0xFF, 0xC0, 0xFF, 0xC1, 0xFF, - 0xC2, 0xFF, 0xC3, 0xFF, 0xC4, 0xFF, 0xC5, 0xFF, - 0xC6, 0xFF, 0xC7, 0xFF, 0xC8, 0xFF, 0xC9, 0xFF, - 0xCA, 0xFF, 0xCB, 0xFF, 0xCC, 0xFF, 0xCD, 0xFF, - 0xCE, 0xFF, 0xCF, 0xFF, 0xD0, 0xFF, 0xD1, 0xFF, - 0xD2, 0xFF, 0xD3, 0xFF, 0xD4, 0xFF, 0xD5, 0xFF, - 0xD6, 0xFF, 0xD7, 0xFF, 0xD8, 0xFF, 0xD9, 0xFF, - 0xDA, 0xFF, 0xDB, 0xFF, 0xDC, 0xFF, 0xDD, 0xFF, - 0xDE, 0xFF, 0xDF, 0xFF, 0xE0, 0xFF, 0xE1, 0xFF, - 0xE2, 0xFF, 0xE3, 0xFF, 0xE4, 0xFF, 0xE5, 0xFF, - 0xE6, 0xFF, 0xE7, 0xFF, 0xE8, 0xFF, 0xE9, 0xFF, - 0xEA, 0xFF, 0xEB, 0xFF, 0xEC, 0xFF, 0xED, 0xFF, - 0xEE, 0xFF, 0xEF, 0xFF, 0xF0, 0xFF, 0xF1, 0xFF, - 0xF2, 0xFF, 0xF3, 0xFF, 0xF4, 0xFF, 0xF5, 0xFF, - 0xF6, 0xFF, 0xF7, 0xFF, 0xF8, 0xFF, 0xF9, 0xFF, - 0xFA, 0xFF, 0xFB, 0xFF, 0xFC, 0xFF, 0xFD, 0xFF, - 0xFE, 0xFF, 0xFF, 0xFF -}; From fe53efd1f228267067ce20ff6970f27966bed7c3 Mon Sep 17 00:00:00 2001 From: UtsavBalar1231 Date: Mon, 17 Aug 2020 09:16:20 +0530 Subject: [PATCH 534/592] fs: include exfat fs Signed-off-by: UtsavBalar1231 --- fs/Kconfig | 2 ++ fs/Makefile | 1 + 2 files changed, 3 insertions(+) diff --git a/fs/Kconfig b/fs/Kconfig index 45bdb320743f..a1f9a02733b5 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -316,4 +316,6 @@ config FILE_TABLE_DEBUG help This option enables debug of the open files using a global filetable +source "fs/exfat/Kconfig" + endmenu diff --git a/fs/Makefile b/fs/Makefile index b27c7bb26d51..67a46cf408b4 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -136,3 +136,4 @@ obj-y += exofs/ # Multiple modules obj-$(CONFIG_CEPH_FS) += ceph/ obj-$(CONFIG_PSTORE) += pstore/ obj-$(CONFIG_EFIVAR_FS) += efivarfs/ +obj-$(CONFIG_EXFAT_FS) += exfat/ From da54656f76c8a4936b10ac60ebe49dfe458bac04 Mon Sep 17 00:00:00 2001 From: UtsavBalar1231 Date: Mon, 17 Aug 2020 10:06:41 +0530 Subject: [PATCH 535/592] exfat: allow new i_version api for 4.14 - required after commit: 305634cd15c1a4e06eb9ad469b5694d475e73e1c Signed-off-by: UtsavBalar1231 --- fs/exfat/compat.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/exfat/compat.h b/fs/exfat/compat.h index ca207327bb26..29e022917d2b 100644 --- a/fs/exfat/compat.h +++ b/fs/exfat/compat.h @@ -18,7 +18,7 @@ "please use the driver from https://github.com/arter97/exfat-linux/tree/old" #endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) #include #else #define inode_inc_iversion(inode) (inode->i_version++) From dd431922940d14babcf140dc71ded87b1bcd3b03 Mon Sep 17 00:00:00 2001 From: UtsavBalar1231 Date: Mon, 17 Aug 2020 09:18:13 +0530 Subject: [PATCH 536/592] ARM64: configs: raphael: sync for exfat-linux Signed-off-by: UtsavBalar1231 --- arch/arm64/configs/raphael_defconfig | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/arch/arm64/configs/raphael_defconfig b/arch/arm64/configs/raphael_defconfig index e9b2930fc06f..f15437ed2f05 100644 --- a/arch/arm64/configs/raphael_defconfig +++ b/arch/arm64/configs/raphael_defconfig @@ -3915,13 +3915,6 @@ CONFIG_ALLOC_BUFFERS_IN_4K_CHUNKS=y # CONFIG_QCA_CLD_WLAN=y CONFIG_QCA_CLD_WLAN_PROFILE="default" -CONFIG_STAGING_EXFAT_FS=y -CONFIG_STAGING_EXFAT_DISCARD=y -# CONFIG_STAGING_EXFAT_DELAYED_SYNC is not set -# CONFIG_STAGING_EXFAT_KERNEL_DEBUG is not set -# CONFIG_STAGING_EXFAT_DEBUG_MSG is not set -CONFIG_STAGING_EXFAT_DEFAULT_CODEPAGE=437 -CONFIG_STAGING_EXFAT_DEFAULT_IOCHARSET="utf8" # CONFIG_GOLDFISH is not set # CONFIG_CHROME_PLATFORMS is not set @@ -4930,6 +4923,10 @@ CONFIG_NLS_UTF8=y # CONFIG_DLM is not set # CONFIG_UNICODE is not set # CONFIG_FILE_TABLE_DEBUG is not set +CONFIG_EXFAT_FS=y +CONFIG_EXFAT_DEFAULT_IOCHARSET="utf8" +CONFIG_EXFAT_VIRTUAL_XATTR=y +CONFIG_EXFAT_VIRTUAL_XATTR_SELINUX_LABEL="u:object_r:exfat:s0" # CONFIG_VIRTUALIZATION is not set # From fe708336d43275363c8ecd64a9a8016e0dd63725 Mon Sep 17 00:00:00 2001 From: Demon000 Date: Tue, 11 Aug 2020 06:30:54 +0300 Subject: [PATCH 537/592] sde: interrupts: optimize interrupt dispatching routines Signed-off-by: UtsavBalar1231 --- drivers/gpu/drm/msm/sde/sde_core_irq.c | 37 ++--------- drivers/gpu/drm/msm/sde/sde_hw_interrupts.c | 71 +++++---------------- drivers/gpu/drm/msm/sde/sde_hw_interrupts.h | 10 --- drivers/gpu/drm/msm/sde/sde_kms.h | 1 - 4 files changed, 20 insertions(+), 99 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_core_irq.c b/drivers/gpu/drm/msm/sde/sde_core_irq.c index b082778a4590..2fe931e12c32 100644 --- a/drivers/gpu/drm/msm/sde/sde_core_irq.c +++ b/drivers/gpu/drm/msm/sde/sde_core_irq.c @@ -44,8 +44,6 @@ static void sde_core_irq_callback_handler(void *arg, int irq_idx) &sde_kms->irq_obj.enable_counts[irq_idx]); } - atomic_inc(&irq_obj->irq_counts[irq_idx]); - /* * Perform registered function callback */ @@ -72,15 +70,6 @@ static void sde_core_irq_callback_handler(void *arg, int irq_idx) SDE_EVT32_IRQ(irq_idx, enable_counts, SDE_EVTLOG_ERROR); } } - - /* - * Clear pending interrupt status in HW. - * NOTE: sde_core_irq_callback_handler is protected by top-level - * spinlock, so it is safe to clear any interrupt status here. - */ - sde_kms->hw_intr->ops.clear_intr_status_nolock( - sde_kms->hw_intr, - irq_idx); } int sde_core_irq_idx_lookup(struct sde_kms *sde_kms, @@ -105,8 +94,7 @@ static int _sde_core_irq_enable(struct sde_kms *sde_kms, int irq_idx) int ret = 0; if (!sde_kms || !sde_kms->hw_intr || - !sde_kms->irq_obj.enable_counts || - !sde_kms->irq_obj.irq_counts) { + !sde_kms->irq_obj.enable_counts) { SDE_ERROR("invalid params\n"); return -EINVAL; } @@ -412,15 +400,14 @@ static int sde_debugfs_core_irq_show(struct seq_file *s, void *v) for (i = 0; i < irq_obj->total_irqs; i++) { spin_lock_irqsave(&irq_obj->cb_lock, irq_flags); cb_count = 0; - irq_count = atomic_read(&irq_obj->irq_counts[i]); enable_count = atomic_read(&irq_obj->enable_counts[i]); list_for_each_entry(cb, &irq_obj->irq_cb_tbl[i], list) cb_count++; spin_unlock_irqrestore(&irq_obj->cb_lock, irq_flags); if (irq_count || enable_count || cb_count) - seq_printf(s, "idx:%d irq:%d enable:%d cb:%d\n", - i, irq_count, enable_count, cb_count); + seq_printf(s, "idx:%d enable:%d cb:%d\n", + i, enable_count, cb_count); } return 0; @@ -494,10 +481,7 @@ void sde_core_irq_preinstall(struct sde_kms *sde_kms) sizeof(struct list_head), GFP_KERNEL); sde_kms->irq_obj.enable_counts = kcalloc(sde_kms->irq_obj.total_irqs, sizeof(atomic_t), GFP_KERNEL); - sde_kms->irq_obj.irq_counts = kcalloc(sde_kms->irq_obj.total_irqs, - sizeof(atomic_t), GFP_KERNEL); - if (!sde_kms->irq_obj.irq_cb_tbl || !sde_kms->irq_obj.enable_counts - || !sde_kms->irq_obj.irq_counts) + if (!sde_kms->irq_obj.irq_cb_tbl || !sde_kms->irq_obj.enable_counts) return; for (i = 0; i < sde_kms->irq_obj.total_irqs; i++) { @@ -505,8 +489,6 @@ void sde_core_irq_preinstall(struct sde_kms *sde_kms) INIT_LIST_HEAD(&sde_kms->irq_obj.irq_cb_tbl[i]); if (sde_kms->irq_obj.enable_counts) atomic_set(&sde_kms->irq_obj.enable_counts[i], 0); - if (sde_kms->irq_obj.irq_counts) - atomic_set(&sde_kms->irq_obj.irq_counts[i], 0); } } @@ -554,10 +536,8 @@ void sde_core_irq_uninstall(struct sde_kms *sde_kms) spin_lock_irqsave(&sde_kms->irq_obj.cb_lock, irq_flags); kfree(sde_kms->irq_obj.irq_cb_tbl); kfree(sde_kms->irq_obj.enable_counts); - kfree(sde_kms->irq_obj.irq_counts); sde_kms->irq_obj.irq_cb_tbl = NULL; sde_kms->irq_obj.enable_counts = NULL; - sde_kms->irq_obj.irq_counts = NULL; sde_kms->irq_obj.total_irqs = 0; spin_unlock_irqrestore(&sde_kms->irq_obj.cb_lock, irq_flags); } @@ -661,15 +641,6 @@ int sde_core_irq_domain_fini(struct sde_kms *sde_kms) irqreturn_t sde_core_irq(struct sde_kms *sde_kms) { - /* - * Read interrupt status from all sources. Interrupt status are - * stored within hw_intr. - * Function will also clear the interrupt status after reading. - * Individual interrupt status bit will only get stored if it - * is enabled. - */ - sde_kms->hw_intr->ops.get_interrupt_statuses(sde_kms->hw_intr); - /* * Dispatch to HW driver to handle interrupt lookup that is being * fired. When matching interrupt is located, HW driver will call to diff --git a/drivers/gpu/drm/msm/sde/sde_hw_interrupts.c b/drivers/gpu/drm/msm/sde/sde_hw_interrupts.c index c34aed434dca..d6b4f8a462fc 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_interrupts.c +++ b/drivers/gpu/drm/msm/sde/sde_hw_interrupts.c @@ -880,13 +880,17 @@ static void sde_hw_intr_dispatch_irq(struct sde_hw_intr *intr, return; /* - * The dispatcher will save the IRQ status before calling here. * Now need to go through each IRQ status and find matching * irq lookup index. */ spin_lock_irqsave(&intr->irq_lock, irq_flags); for (reg_idx = 0; reg_idx < intr->sde_irq_size; reg_idx++) { - irq_status = intr->save_irq_status[reg_idx]; + /* Read interrupt status */ + irq_status = SDE_REG_READ(&intr->hw, + intr->sde_irq_tbl[reg_idx].status_off); + + if (!irq_status) + continue; /* get the global offset in 'sde_irq_map' */ sde_irq_idx = intr->sde_irq_tbl[reg_idx].sde_irq_idx; @@ -912,20 +916,13 @@ static void sde_hw_intr_dispatch_irq(struct sde_hw_intr *intr, for (irq_idx = start_idx; (irq_idx < end_idx) && irq_status; irq_idx++) - if ((irq_status & sde_irq_map[irq_idx].irq_mask) && - (sde_irq_map[irq_idx].reg_idx == reg_idx)) { + if (irq_status & sde_irq_map[irq_idx].irq_mask) { /* * Once a match on irq mask, perform a callback - * to the given cbfunc. cbfunc will take care - * the interrupt status clearing. If cbfunc is - * not provided, then the interrupt clearing - * is here. + * to the given cbfunc. */ if (cbfunc) cbfunc(arg, irq_idx); - else - intr->ops.clear_intr_status_nolock( - intr, irq_idx); /* * When callback finish, clear the irq_status @@ -934,7 +931,15 @@ static void sde_hw_intr_dispatch_irq(struct sde_hw_intr *intr, */ irq_status &= ~sde_irq_map[irq_idx].irq_mask; } + + /* Clear the interrupt */ + SDE_REG_WRITE(&intr->hw, intr->sde_irq_tbl[reg_idx].clr_off, + 0xffffffff); } + + /* ensure register writes go through */ + wmb(); + spin_unlock_irqrestore(&intr->irq_lock, irq_flags); } @@ -1115,40 +1120,6 @@ static int sde_hw_intr_get_interrupt_sources(struct sde_hw_intr *intr, return 0; } -static void sde_hw_intr_get_interrupt_statuses(struct sde_hw_intr *intr) -{ - int i; - u32 enable_mask; - unsigned long irq_flags; - - if (!intr) - return; - - spin_lock_irqsave(&intr->irq_lock, irq_flags); - for (i = 0; i < intr->sde_irq_size; i++) { - /* Read interrupt status */ - intr->save_irq_status[i] = SDE_REG_READ(&intr->hw, - intr->sde_irq_tbl[i].status_off); - - /* Read enable mask */ - enable_mask = SDE_REG_READ(&intr->hw, - intr->sde_irq_tbl[i].en_off); - - /* and clear the interrupt */ - if (intr->save_irq_status[i]) - SDE_REG_WRITE(&intr->hw, intr->sde_irq_tbl[i].clr_off, - intr->save_irq_status[i]); - - /* Finally update IRQ status based on enable mask */ - intr->save_irq_status[i] &= enable_mask; - } - - /* ensure register writes go through */ - wmb(); - - spin_unlock_irqrestore(&intr->irq_lock, irq_flags); -} - static void sde_hw_intr_clear_intr_status_force_mask(struct sde_hw_intr *intr, int irq_idx, u32 irq_mask) { @@ -1321,7 +1292,6 @@ static void __setup_intr_ops(struct sde_hw_intr_ops *ops) ops->disable_all_irqs = sde_hw_intr_disable_irqs; ops->get_valid_interrupts = sde_hw_intr_get_valid_interrupts; ops->get_interrupt_sources = sde_hw_intr_get_interrupt_sources; - ops->get_interrupt_statuses = sde_hw_intr_get_interrupt_statuses; ops->clear_interrupt_status = sde_hw_intr_clear_interrupt_status; ops->clear_intr_status_nolock = sde_hw_intr_clear_intr_status_nolock; ops->clear_intr_status_force_mask = @@ -1469,7 +1439,6 @@ void sde_hw_intr_destroy(struct sde_hw_intr *intr) if (intr) { kfree(intr->sde_irq_tbl); kfree(intr->cache_irq_mask); - kfree(intr->save_irq_status); kfree(intr); } } @@ -1578,13 +1547,6 @@ struct sde_hw_intr *sde_hw_intr_init(void __iomem *addr, goto exit; } - intr->save_irq_status = kcalloc(intr->sde_irq_size, sizeof(u32), - GFP_KERNEL); - if (intr->save_irq_status == NULL) { - ret = -ENOMEM; - goto exit; - } - spin_lock_init(&intr->irq_lock); return intr; @@ -1592,7 +1554,6 @@ struct sde_hw_intr *sde_hw_intr_init(void __iomem *addr, exit: kfree(intr->sde_irq_tbl); kfree(intr->cache_irq_mask); - kfree(intr->save_irq_status); kfree(intr); return ERR_PTR(ret); } diff --git a/drivers/gpu/drm/msm/sde/sde_hw_interrupts.h b/drivers/gpu/drm/msm/sde/sde_hw_interrupts.h index 1d5a8427d0aa..e2de0e33bd59 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_interrupts.h +++ b/drivers/gpu/drm/msm/sde/sde_hw_interrupts.h @@ -188,14 +188,6 @@ struct sde_hw_intr_ops { void (*cbfunc)(void *arg, int irq_idx), void *arg); - /** - * get_interrupt_statuses - Gets and store value from all interrupt - * status registers that are currently fired. - * @intr: HW interrupt handle - */ - void (*get_interrupt_statuses)( - struct sde_hw_intr *intr); - /** * clear_interrupt_status - Clears HW interrupt status based on given * lookup IRQ index. @@ -292,7 +284,6 @@ struct sde_hw_intr_ops { * @hw: virtual address mapping * @ops: function pointer mapping for IRQ handling * @cache_irq_mask: array of IRQ enable masks reg storage created during init - * @save_irq_status: array of IRQ status reg storage created during init * @irq_idx_tbl_size: total number of irq_idx mapped in the hw_interrupts * @irq_lock: spinlock for accessing IRQ resources * @sde_irq_size: total number of elements of the sde_irq_tbl @@ -303,7 +294,6 @@ struct sde_hw_intr { struct sde_hw_blk_reg_map hw; struct sde_hw_intr_ops ops; u32 *cache_irq_mask; - u32 *save_irq_status; u32 irq_idx_tbl_size; u32 sde_irq_size; struct sde_intr_reg *sde_irq_tbl; diff --git a/drivers/gpu/drm/msm/sde/sde_kms.h b/drivers/gpu/drm/msm/sde/sde_kms.h index f01624a1c9a1..38a1f3cfb1c9 100644 --- a/drivers/gpu/drm/msm/sde/sde_kms.h +++ b/drivers/gpu/drm/msm/sde/sde_kms.h @@ -204,7 +204,6 @@ struct sde_irq { u32 total_irqs; struct list_head *irq_cb_tbl; atomic_t *enable_counts; - atomic_t *irq_counts; spinlock_t cb_lock; struct dentry *debugfs_file; }; From b4a9912426c9e8215b3951c17c19c51d4a135adc Mon Sep 17 00:00:00 2001 From: UtsavBalar1231 Date: Mon, 17 Aug 2020 09:37:19 +0530 Subject: [PATCH 538/592] ion: Remove hibernation support for secure heaps Revert "ion: Add hibernation support for secure cma heap" Revert "ion: Add hibernation support for secure carveout heap" Revert "ion: Add hibernation support for system secure heap" Revert "ion: Add pm_ops for msm_ion driver" Revert "ion: msm: Assume devicetree support" Signed-off-by: UtsavBalar1231 --- drivers/staging/android/ion/ion.h | 7 -- .../staging/android/ion/ion_carveout_heap.c | 34 ------- drivers/staging/android/ion/ion_cma_heap.c | 17 ---- .../android/ion/ion_system_secure_heap.c | 38 -------- drivers/staging/android/ion/msm/msm_ion_of.c | 90 ++++++------------- 5 files changed, 27 insertions(+), 159 deletions(-) diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index e5b293dc8889..20536e0e1c0b 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -160,12 +160,6 @@ struct ion_device { int heap_cnt; }; -/* refer to include/linux/pm.h */ -struct ion_pm_ops { - int (*freeze)(struct ion_heap *heap); - int (*restore)(struct ion_heap *heap); -}; - /** * struct ion_heap_ops - ops to operate on a given heap * @allocate: allocate memory @@ -191,7 +185,6 @@ struct ion_heap_ops { int (*map_user)(struct ion_heap *mapper, struct ion_buffer *buffer, struct vm_area_struct *vma); int (*shrink)(struct ion_heap *heap, gfp_t gfp_mask, int nr_to_scan); - struct ion_pm_ops pm; }; /** diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c index 19c8ad23cf06..b9e1d63303be 100644 --- a/drivers/staging/android/ion/ion_carveout_heap.c +++ b/drivers/staging/android/ion/ion_carveout_heap.c @@ -186,8 +186,6 @@ struct ion_sc_entry { struct list_head list; struct ion_heap *heap; u32 token; - u64 base; - u64 size; }; struct ion_sc_heap { @@ -244,39 +242,9 @@ static void ion_sc_heap_free(struct ion_buffer *buffer) kfree(table); } -static int ion_secure_carveout_pm_freeze(struct ion_heap *heap) -{ - long sz; - - sz = atomic_long_read(&heap->total_allocated); - if (sz) { - pr_err("%s: %lx bytes won't be saved across hibernation. Aborting.", - __func__, sz); - return -EINVAL; - } - return 0; -} - -static int ion_secure_carveout_pm_restore(struct ion_heap *heap) -{ - struct ion_sc_heap *manager; - struct ion_sc_entry *child; - - manager = container_of(heap, struct ion_sc_heap, heap); - - list_for_each_entry(child, &manager->children, list) - ion_hyp_assign_from_flags( - child->base, child->size, child->token); - return 0; -} - static struct ion_heap_ops ion_sc_heap_ops = { .allocate = ion_sc_heap_allocate, .free = ion_sc_heap_free, - .pm = { - .freeze = ion_secure_carveout_pm_freeze, - .restore = ion_secure_carveout_pm_restore, - } }; static int ion_sc_get_dt_token(struct ion_sc_entry *entry, @@ -330,8 +298,6 @@ static int ion_sc_add_child(struct ion_sc_heap *manager, heap_data.priv = dev; heap_data.base = base; heap_data.size = size; - entry->base = base; - entry->size = size; /* This will zero memory initially */ entry->heap = __ion_carveout_heap_create(&heap_data, false); diff --git a/drivers/staging/android/ion/ion_cma_heap.c b/drivers/staging/android/ion/ion_cma_heap.c index 658571d13d34..63a6a94a933a 100644 --- a/drivers/staging/android/ion/ion_cma_heap.c +++ b/drivers/staging/android/ion/ion_cma_heap.c @@ -276,29 +276,12 @@ static int ion_secure_cma_map_user(struct ion_heap *mapper, return ion_heap_map_user(mapper, buffer, vma); } -static int ion_secure_cma_pm_freeze(struct ion_heap *heap) -{ - long sz; - - sz = atomic_long_read(&heap->total_allocated); - if (sz) { - pr_err("%s: %lx bytes won't be saved across hibernation. Aborting.", - __func__, sz); - return -EINVAL; - } - - return 0; -} - static struct ion_heap_ops ion_secure_cma_ops = { .allocate = ion_secure_cma_allocate, .free = ion_secure_cma_free, .map_user = ion_secure_cma_map_user, .map_kernel = ion_secure_cma_map_kernel, .unmap_kernel = ion_heap_unmap_kernel, - .pm = { - .freeze = ion_secure_cma_pm_freeze, - } }; struct ion_heap *ion_cma_secure_heap_create(struct ion_platform_heap *data) diff --git a/drivers/staging/android/ion/ion_system_secure_heap.c b/drivers/staging/android/ion/ion_system_secure_heap.c index 64c3c14e78c2..050765fb0187 100644 --- a/drivers/staging/android/ion/ion_system_secure_heap.c +++ b/drivers/staging/android/ion/ion_system_secure_heap.c @@ -352,41 +352,6 @@ static int ion_system_secure_heap_shrink(struct ion_heap *heap, gfp_t gfp_mask, gfp_mask, nr_to_scan); } -static int ion_system_secure_heap_pm_freeze(struct ion_heap *heap) -{ - struct ion_system_secure_heap *secure_heap; - unsigned long count; - long sz; - struct shrink_control sc = { - .gfp_mask = GFP_HIGHUSER, - }; - - secure_heap = container_of(heap, struct ion_system_secure_heap, heap); - - sz = atomic_long_read(&heap->total_allocated); - if (sz) { - pr_err("%s: %lx bytes won't be saved across hibernation. Aborting.", - __func__, sz); - return -EINVAL; - } - - /* Since userspace is frozen, no more requests will be queued */ - cancel_delayed_work_sync(&secure_heap->prefetch_work); - - count = heap->shrinker.count_objects(&heap->shrinker, &sc); - sc.nr_to_scan = count; - heap->shrinker.scan_objects(&heap->shrinker, &sc); - - count = heap->shrinker.count_objects(&heap->shrinker, &sc); - if (count) { - pr_err("%s: Failed to free all objects - %ld remaining", - __func__, count); - return -EINVAL; - } - - return 0; -} - static struct ion_heap_ops system_secure_heap_ops = { .allocate = ion_system_secure_heap_allocate, .free = ion_system_secure_heap_free, @@ -394,9 +359,6 @@ static struct ion_heap_ops system_secure_heap_ops = { .unmap_kernel = ion_system_secure_heap_unmap_kernel, .map_user = ion_system_secure_heap_map_user, .shrink = ion_system_secure_heap_shrink, - .pm = { - .freeze = ion_system_secure_heap_pm_freeze, - } }; struct ion_heap *ion_system_secure_heap_create(struct ion_platform_heap *unused) diff --git a/drivers/staging/android/ion/msm/msm_ion_of.c b/drivers/staging/android/ion/msm/msm_ion_of.c index 96b5f4f3e633..e1fbe941f892 100644 --- a/drivers/staging/android/ion/msm/msm_ion_of.c +++ b/drivers/staging/android/ion/msm/msm_ion_of.c @@ -34,6 +34,7 @@ struct ion_heap_desc { const char *name; }; +#ifdef CONFIG_OF static struct ion_heap_desc ion_heap_meta[] = { { .id = ION_SYSTEM_HEAP_ID, @@ -84,7 +85,9 @@ static struct ion_heap_desc ion_heap_meta[] = { .name = ION_SECURE_CARVEOUT_HEAP_NAME, } }; +#endif +#ifdef CONFIG_OF #define MAKE_HEAP_TYPE_MAPPING(h) { .name = #h, \ .heap_type = ION_HEAP_TYPE_##h, } @@ -262,6 +265,16 @@ free_heaps: free_pdata(pdata); return ERR_PTR(ret); } +#else +static struct ion_platform_data *msm_ion_parse_dt(struct platform_device *pdev) +{ + return NULL; +} + +static void free_pdata(const struct ion_platform_data *pdata) +{ +} +#endif struct ion_heap *get_ion_heap(int heap_id) { @@ -282,13 +295,19 @@ static int msm_ion_probe(struct platform_device *pdev) { static struct ion_device *new_dev; struct ion_platform_data *pdata; + unsigned int pdata_needs_to_be_freed; int err = -1; int i; - pdata = msm_ion_parse_dt(pdev); - if (IS_ERR(pdata)) - return PTR_ERR(pdata); - + if (pdev->dev.of_node) { + pdata = msm_ion_parse_dt(pdev); + if (IS_ERR(pdata)) + return PTR_ERR(pdata); + pdata_needs_to_be_freed = 1; + } else { + pdata = pdev->dev.platform_data; + pdata_needs_to_be_freed = 0; + } num_heaps = pdata->nr; @@ -331,7 +350,8 @@ static int msm_ion_probe(struct platform_device *pdev) ion_device_add_heap(new_dev, heaps[i]); } - free_pdata(pdata); + if (pdata_needs_to_be_freed) + free_pdata(pdata); platform_set_drvdata(pdev, new_dev); /* @@ -344,66 +364,11 @@ static int msm_ion_probe(struct platform_device *pdev) out: kfree(heaps); - free_pdata(pdata); + if (pdata_needs_to_be_freed) + free_pdata(pdata); return err; } -static int msm_ion_pm_freeze(struct device *dev) -{ - struct ion_device *ion_dev = dev_get_drvdata(dev); - struct ion_heap *heap; - int ret; - - plist_for_each_entry(heap, &ion_dev->heaps, node) { - if (heap->ops->pm.freeze) { - ret = heap->ops->pm.freeze(heap); - if (ret) { - dev_err(dev, "%s freeze callback failed\n", - heap->name); - goto undo; - } - } - } - - return 0; - -undo: - list_for_each_entry_continue_reverse(heap, &ion_dev->heaps.node_list, - node.node_list) - if (heap->ops->pm.restore) - heap->ops->pm.restore(heap); - - return ret; -} - -static int msm_ion_pm_restore(struct device *dev) -{ - struct ion_device *ion_dev = dev_get_drvdata(dev); - struct ion_heap *heap; - int ret = 0; - - plist_for_each_entry(heap, &ion_dev->heaps, node) { - int rc; - - if (heap->ops->pm.restore) { - rc = heap->ops->pm.restore(heap); - if (rc) { - dev_err(dev, "%s restore callback failed.\n", - heap->name); - if (!ret) - ret = rc; - } - } - } - - return ret; -} - -static const struct dev_pm_ops msm_ion_pm_ops = { - .freeze_late = msm_ion_pm_freeze, - .restore_early = msm_ion_pm_restore, -}; - static const struct of_device_id msm_ion_match_table[] = { {.compatible = ION_COMPAT_STR}, {}, @@ -414,7 +379,6 @@ static struct platform_driver msm_ion_driver = { .driver = { .name = "ion-msm", .of_match_table = msm_ion_match_table, - .pm = &msm_ion_pm_ops, .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, }; From 074e71cfbcaee9ec37913c18981157afa7bc4047 Mon Sep 17 00:00:00 2001 From: UtsavBalar1231 Date: Mon, 17 Aug 2020 09:44:59 +0530 Subject: [PATCH 539/592] Revert "ANDROID: staging: android: ion: Expose total heap and pool sizes via sysfs" This reverts commit 30b38df5ef833255911749ac580409b5234adca9. Signed-off-by: UtsavBalar1231 --- Documentation/ABI/testing/sysfs-kernel-ion | 27 -------- drivers/staging/android/ion/ion.c | 68 +-------------------- drivers/staging/android/ion/ion.h | 6 -- drivers/staging/android/ion/ion_page_pool.c | 19 ------ 4 files changed, 2 insertions(+), 118 deletions(-) delete mode 100644 Documentation/ABI/testing/sysfs-kernel-ion diff --git a/Documentation/ABI/testing/sysfs-kernel-ion b/Documentation/ABI/testing/sysfs-kernel-ion deleted file mode 100644 index f57f970574ae..000000000000 --- a/Documentation/ABI/testing/sysfs-kernel-ion +++ /dev/null @@ -1,27 +0,0 @@ -What: /sys/kernel/ion -Date: Dec 2019 -KernelVersion: 4.14.158 -Contact: Suren Baghdasaryan , - Sandeep Patil -Description: - The /sys/kernel/ion directory contains a snapshot of the - internal state of ION memory heaps and pools. -Users: kernel memory tuning tools - -What: /sys/kernel/ion/total_heaps_kb -Date: Dec 2019 -KernelVersion: 4.14.158 -Contact: Suren Baghdasaryan , - Sandeep Patil -Description: - The total_heaps_kb file is read-only and specifies how much - memory in Kb is allocated to ION heaps. - -What: /sys/kernel/ion/total_pools_kb -Date: Dec 2019 -KernelVersion: 4.14.158 -Contact: Suren Baghdasaryan , - Sandeep Patil -Description: - The total_pools_kb file is read-only and specifies how much - memory in Kb is allocated to ION pools. diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index bc0679ec4d20..19f813e7aa61 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -48,7 +48,6 @@ #include "ion_secure_util.h" static struct ion_device *internal_dev; -static atomic_long_t total_heap_bytes; int ion_walk_heaps(int heap_id, enum ion_heap_type type, void *data, int (*f)(struct ion_heap *heap, void *data)) @@ -173,7 +172,6 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, ion_buffer_add(dev, buffer); mutex_unlock(&dev->buffer_lock); atomic_long_add(len, &heap->total_allocated); - atomic_long_add(len, &total_heap_bytes); return buffer; err1: @@ -203,7 +201,6 @@ static void _ion_buffer_destroy(struct ion_buffer *buffer) mutex_lock(&dev->buffer_lock); rb_erase(&buffer->node, &dev->buffers); mutex_unlock(&dev->buffer_lock); - atomic_long_sub(buffer->size, &total_heap_bytes); atomic_long_sub(buffer->size, &buffer->heap->total_allocated); if (heap->flags & ION_HEAP_FLAG_DEFER_FREE) @@ -1302,56 +1299,6 @@ void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap) } EXPORT_SYMBOL(ion_device_add_heap); -static ssize_t -total_heaps_kb_show(struct kobject *kobj, struct kobj_attribute *attr, - char *buf) -{ - u64 size_in_bytes = atomic_long_read(&total_heap_bytes); - - return sprintf(buf, "%llu\n", div_u64(size_in_bytes, 1024)); -} - -static ssize_t -total_pools_kb_show(struct kobject *kobj, struct kobj_attribute *attr, - char *buf) -{ - u64 size_in_bytes = ion_page_pool_nr_pages() * PAGE_SIZE; - - return sprintf(buf, "%llu\n", div_u64(size_in_bytes, 1024)); -} - -static struct kobj_attribute total_heaps_kb_attr = - __ATTR_RO(total_heaps_kb); - -static struct kobj_attribute total_pools_kb_attr = - __ATTR_RO(total_pools_kb); - -static struct attribute *ion_device_attrs[] = { - &total_heaps_kb_attr.attr, - &total_pools_kb_attr.attr, - NULL, -}; - -ATTRIBUTE_GROUPS(ion_device); - -static int ion_init_sysfs(void) -{ - struct kobject *ion_kobj; - int ret; - - ion_kobj = kobject_create_and_add("ion", kernel_kobj); - if (!ion_kobj) - return -ENOMEM; - - ret = sysfs_create_groups(ion_kobj, ion_device_groups); - if (ret) { - kobject_put(ion_kobj); - return ret; - } - - return 0; -} - struct ion_device *ion_device_create(void) { struct ion_device *idev; @@ -1368,13 +1315,8 @@ struct ion_device *ion_device_create(void) ret = misc_register(&idev->dev); if (ret) { pr_err("ion: failed to register misc device.\n"); - goto err_reg; - } - - ret = ion_init_sysfs(); - if (ret) { - pr_err("ion: failed to add sysfs attributes.\n"); - goto err_sysfs; + kfree(idev); + return ret; } idev->debug_root = debugfs_create_dir("ion", NULL); @@ -1391,11 +1333,5 @@ debugfs_done: plist_head_init(&idev->heaps); internal_dev = idev; return idev; - -err_sysfs: - misc_deregister(&idev->dev); -err_reg: - kfree(idev); - return ERR_PTR(ret); } EXPORT_SYMBOL(ion_device_create); diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index 20536e0e1c0b..9a532298c627 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -457,12 +457,6 @@ void ion_page_pool_free_immediate(struct ion_page_pool *pool, int ion_page_pool_total(struct ion_page_pool *pool, bool high); size_t ion_system_heap_secure_page_pool_total(struct ion_heap *heap, int vmid); -#ifdef CONFIG_ION_SYSTEM_HEAP -long ion_page_pool_nr_pages(void); -#else -static inline long ion_page_pool_nr_pages(void) { return 0; } -#endif - /** ion_page_pool_shrink - shrinks the size of the memory cached in the pool * @pool: the pool * @gfp_mask: the memory type to reclaim diff --git a/drivers/staging/android/ion/ion_page_pool.c b/drivers/staging/android/ion/ion_page_pool.c index 82e5007b45b4..b95a7ce2e20b 100644 --- a/drivers/staging/android/ion/ion_page_pool.c +++ b/drivers/staging/android/ion/ion_page_pool.c @@ -26,13 +26,6 @@ #include "ion.h" -/* - * We avoid atomic_long_t to minimize cache flushes at the cost of possible - * race which would result in a small accounting inaccuracy that we can - * tolerate. - */ -static long nr_total_pages; - static void *ion_page_pool_alloc_pages(struct ion_page_pool *pool) { struct page *page = alloc_pages(pool->gfp_mask, pool->order); @@ -57,7 +50,6 @@ static int ion_page_pool_add(struct ion_page_pool *pool, struct page *page) pool->low_count++; } - nr_total_pages += 1 << pool->order; mod_node_page_state(page_pgdat(page), NR_KERNEL_MISC_RECLAIMABLE, 1 << pool->order); mutex_unlock(&pool->mutex); @@ -79,7 +71,6 @@ static struct page *ion_page_pool_remove(struct ion_page_pool *pool, bool high) } list_del(&page->lru); - nr_total_pages -= 1 << pool->order; mod_node_page_state(page_pgdat(page), NR_KERNEL_MISC_RECLAIMABLE, -(1 << pool->order)); return page; @@ -158,16 +149,6 @@ int ion_page_pool_total(struct ion_page_pool *pool, bool high) return count << pool->order; } -#ifdef CONFIG_ION_SYSTEM_HEAP -long ion_page_pool_nr_pages(void) -{ - /* Correct possible overflow caused by racing writes */ - if (nr_total_pages < 0) - nr_total_pages = 0; - return nr_total_pages; -} -#endif - int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask, int nr_to_scan) { From c011639ec6b0f24e8a16e238e8f2efa7c1dc5e42 Mon Sep 17 00:00:00 2001 From: Sultan Alsawaf Date: Mon, 17 Aug 2020 09:48:53 +0530 Subject: [PATCH 540/592] ion: Rewrite for improved clarity and performance The ION driver suffers from massive code bloat caused by excessive debug features, as well as poor lock usage as a result of that. Multiple locks in ION exist to make the debug features thread-safe, which hurts ION's actual performance when doing its job. There are numerous code paths in ION that hold mutexes for no reason and hold them for longer than necessary. This results in not only unwanted lock contention, but also long delays when a mutex lock results in the calling thread getting preempted for a while. All lock usage in ION follows this pattern, which causes poor performance across the board. Furthermore, a single big lock is used mostly everywhere rather than multiple fine-grained locks. Most of the mutex locks can be replaced with simple atomic operations. Where a mutex lock can't be eliminated completely, a spinlock or rwlock can be used instead for quick operations, thereby avoiding long delays due to preemption. Fine-grained locks are also now used in place of the single big lock that was used before. Additionally, ion_dupe_sg_table is called very frequently, and lies within the rendering path for the display. Speed it up by reserving caches for its sg_table and page-sized scatterlist allocations, as well as by improving the sg copy process. Note that sg_alloc_table zeroes out `table`, so there's no need to zero it out using the memory allocator. Overall, just rewrite ION entirely to fix its deficiencies. This optimizes ION for excellent performance and discards its rarely-used debug bloat. Signed-off-by: Sultan Alsawaf [kdrag0n: Forward-ported from k4.4 to k4.14 and updated to patch some newer ION code] Signed-off-by: Danny Lin [UtsavBalar1231: adapt for auto-kernel base] Signed-off-by: UtsavBalar1231 --- drivers/staging/android/ion/Kconfig | 12 - drivers/staging/android/ion/ion-ioctl.c | 42 +- drivers/staging/android/ion/ion.c | 922 ++++-------------- drivers/staging/android/ion/ion.h | 66 +- drivers/staging/android/ion/ion_cma_heap.c | 3 +- drivers/staging/android/ion/ion_heap.c | 24 +- drivers/staging/android/ion/ion_page_pool.c | 20 +- drivers/staging/android/ion/ion_system_heap.c | 103 +- drivers/staging/android/ion/msm_ion_priv.h | 17 - 9 files changed, 261 insertions(+), 948 deletions(-) diff --git a/drivers/staging/android/ion/Kconfig b/drivers/staging/android/ion/Kconfig index 2781d2f92356..6a27fb8cfe34 100644 --- a/drivers/staging/android/ion/Kconfig +++ b/drivers/staging/android/ion/Kconfig @@ -44,18 +44,6 @@ config ION_CMA_HEAP by the Contiguous Memory Allocator (CMA). If your system has these regions, you should say Y here. -config ION_FORCE_DMA_SYNC - bool "Force ION to always DMA sync buffer memory" - depends on ION - help - Force ION to DMA sync buffer memory when it is allocated and to - always DMA sync the buffer memory on calls to begin/end cpu - access. This makes ION DMA sync behavior similar to that of the - older version of ION. - We generally don't want to enable this config as it breaks the - cache maintenance model. - If you're not sure say N here. - config ION_DEFER_FREE_NO_SCHED_IDLE bool "Increases the priority of ION defer free thead" depends on ION diff --git a/drivers/staging/android/ion/ion-ioctl.c b/drivers/staging/android/ion/ion-ioctl.c index 83cbcc0dcd8c..3f970b5e2b58 100644 --- a/drivers/staging/android/ion/ion-ioctl.c +++ b/drivers/staging/android/ion/ion-ioctl.c @@ -44,22 +44,11 @@ static int validate_ioctl_arg(unsigned int cmd, union ion_ioctl_arg *arg) return ret ? -EINVAL : 0; } -/* fix up the cases where the ioctl direction bits are incorrect */ -static unsigned int ion_ioctl_dir(unsigned int cmd) -{ - switch (cmd) { - default: - return _IOC_DIR(cmd); - } -} - long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { - int ret = 0; - unsigned int dir; + unsigned int dir = _IOC_DIR(cmd); union ion_ioctl_arg data; - - dir = ion_ioctl_dir(cmd); + int ret = 0; if (_IOC_SIZE(cmd) > sizeof(data)) return -EINVAL; @@ -73,10 +62,8 @@ long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return -EFAULT; ret = validate_ioctl_arg(cmd, &data); - if (ret) { - pr_warn_once("%s: ioctl validate failed\n", __func__); + if (ret) return ret; - } if (!(dir & _IOC_WRITE)) memset(&data, 0, sizeof(data)); @@ -84,25 +71,19 @@ long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) switch (cmd) { case ION_IOC_ALLOC: { - int fd; - - fd = ion_alloc_fd(data.allocation.len, - data.allocation.heap_id_mask, - data.allocation.flags); + int fd = ion_alloc_fd(data.allocation.len, + data.allocation.heap_id_mask, + data.allocation.flags); if (fd < 0) return fd; data.allocation.fd = fd; - break; } case ION_IOC_HEAP_QUERY: ret = ion_query_heaps(&data.query); break; case ION_IOC_PREFETCH: - { - int ret; - ret = ion_walk_heaps(data.prefetch_data.heap_id, (enum ion_heap_type) ION_HEAP_TYPE_SYSTEM_SECURE, @@ -110,22 +91,18 @@ long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ion_system_secure_heap_prefetch); if (ret) return ret; - break; - } - case ION_IOC_DRAIN: - { - int ret; + break; + case ION_IOC_DRAIN: ret = ion_walk_heaps(data.prefetch_data.heap_id, (enum ion_heap_type) ION_HEAP_TYPE_SYSTEM_SECURE, (void *)&data.prefetch_data, ion_system_secure_heap_drain); - if (ret) return ret; + break; - } default: return -ENOTTY; } @@ -134,5 +111,6 @@ long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (copy_to_user((void __user *)arg, &data, _IOC_SIZE(cmd))) return -EFAULT; } + return ret; } diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 19f813e7aa61..5d0aafa787ef 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -1,109 +1,43 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * - * drivers/staging/android/ion/ion.c - * * Copyright (C) 2011 Google, Inc. - * Copyright (c) 2011-2020, The Linux Foundation. All rights reserved. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * + * Copyright (c) 2011-2018, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 Sultan Alsawaf . */ -#include -#include -#include -#include -#include -#include -#include -#include +#include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include -#define CREATE_TRACE_POINTS -#include -#include +#include +#include +#include #include "ion.h" #include "ion_secure_util.h" static struct ion_device *internal_dev; +static struct kmem_cache *ion_sg_table_pool; int ion_walk_heaps(int heap_id, enum ion_heap_type type, void *data, int (*f)(struct ion_heap *heap, void *data)) { - int ret_val = 0; - struct ion_heap *heap; struct ion_device *dev = internal_dev; - /* - * traverse the list of heaps available in this system - * and find the heap that is specified. - */ - down_write(&dev->lock); + struct ion_heap *heap; + int ret = 0; + + down_write(&dev->heap_lock); plist_for_each_entry(heap, &dev->heaps, node) { - if (ION_HEAP(heap->id) != heap_id || - type != heap->type) - continue; - ret_val = f(heap, data); - break; - } - up_write(&dev->lock); - return ret_val; -} -EXPORT_SYMBOL(ion_walk_heaps); - -bool ion_buffer_cached(struct ion_buffer *buffer) -{ - return !!(buffer->flags & ION_FLAG_CACHED); -} - -/* this function should only be called while dev->lock is held */ -static void ion_buffer_add(struct ion_device *dev, - struct ion_buffer *buffer) -{ - struct rb_node **p = &dev->buffers.rb_node; - struct rb_node *parent = NULL; - struct ion_buffer *entry; - - while (*p) { - parent = *p; - entry = rb_entry(parent, struct ion_buffer, node); - - if (buffer < entry) { - p = &(*p)->rb_left; - } else if (buffer > entry) { - p = &(*p)->rb_right; - } else { - pr_err("%s: buffer already found.", __func__); - BUG(); + if (heap->type == type && ION_HEAP(heap->id) == heap_id) { + ret = f(heap, data); + break; } } + up_write(&dev->heap_lock); - rb_link_node(&buffer->node, parent, p); - rb_insert_color(&buffer->node, &dev->buffers); + return ret; } -/* this function should only be called while dev->lock is held */ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, struct ion_device *dev, unsigned long len, @@ -113,80 +47,51 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, struct sg_table *table; int ret; - buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); + buffer = kmalloc(sizeof(*buffer), GFP_KERNEL); if (!buffer) return ERR_PTR(-ENOMEM); - buffer->heap = heap; - buffer->flags = flags; + *buffer = (typeof(*buffer)){ + .dev = dev, + .heap = heap, + .flags = flags, + .size = len, + .attachments = LIST_HEAD_INIT(buffer->attachments), + .vmas = LIST_HEAD_INIT(buffer->vmas), + .attachment_lock = __MUTEX_INITIALIZER(buffer->attachment_lock), + .kmap_lock = __MUTEX_INITIALIZER(buffer->kmap_lock), + .vma_lock = __MUTEX_INITIALIZER(buffer->vma_lock) + }; ret = heap->ops->allocate(heap, buffer, len, flags); - if (ret) { if (!(heap->flags & ION_HEAP_FLAG_DEFER_FREE)) - goto err2; + goto free_buffer; if (ret == -EINTR) - goto err2; + goto free_buffer; ion_heap_freelist_drain(heap, 0); ret = heap->ops->allocate(heap, buffer, len, flags); if (ret) - goto err2; + goto free_buffer; } - if (buffer->sg_table == NULL) { - WARN_ONCE(1, "This heap needs to set the sgtable"); - ret = -EINVAL; - goto err1; - } + if (buffer->sg_table == NULL) + goto free_heap; table = buffer->sg_table; - buffer->dev = dev; - buffer->size = len; - - buffer->dev = dev; - buffer->size = len; - INIT_LIST_HEAD(&buffer->attachments); - INIT_LIST_HEAD(&buffer->vmas); - mutex_init(&buffer->lock); - - if (IS_ENABLED(CONFIG_ION_FORCE_DMA_SYNC)) { - int i; - struct scatterlist *sg; - - /* - * this will set up dma addresses for the sglist -- it is not - * technically correct as per the dma api -- a specific - * device isn't really taking ownership here. However, in - * practice on our systems the only dma_address space is - * physical addresses. - */ - for_each_sg(table->sgl, sg, table->nents, i) { - sg_dma_address(sg) = sg_phys(sg); - sg_dma_len(sg) = sg->length; - } - } - - mutex_lock(&dev->buffer_lock); - ion_buffer_add(dev, buffer); - mutex_unlock(&dev->buffer_lock); - atomic_long_add(len, &heap->total_allocated); return buffer; -err1: +free_heap: heap->ops->free(buffer); -err2: +free_buffer: kfree(buffer); - return ERR_PTR(ret); + return ERR_PTR(-EINVAL); } void ion_buffer_destroy(struct ion_buffer *buffer) { - if (buffer->kmap_cnt > 0) { - pr_warn_ratelimited("ION client likely missing a call to dma_buf_kunmap or dma_buf_vunmap\n"); - buffer->heap->ops->unmap_kernel(buffer->heap, buffer); - } buffer->heap->ops->free(buffer); kfree(buffer); } @@ -194,15 +99,9 @@ void ion_buffer_destroy(struct ion_buffer *buffer) static void _ion_buffer_destroy(struct ion_buffer *buffer) { struct ion_heap *heap = buffer->heap; - struct ion_device *dev = buffer->dev; msm_dma_buf_freed(buffer); - mutex_lock(&dev->buffer_lock); - rb_erase(&buffer->node, &dev->buffers); - mutex_unlock(&dev->buffer_lock); - - atomic_long_sub(buffer->size, &buffer->heap->total_allocated); if (heap->flags & ION_HEAP_FLAG_DEFER_FREE) ion_heap_freelist_add(heap, buffer); else @@ -213,58 +112,60 @@ static void *ion_buffer_kmap_get(struct ion_buffer *buffer) { void *vaddr; + mutex_lock(&buffer->kmap_lock); if (buffer->kmap_cnt) { + vaddr = buffer->vaddr; buffer->kmap_cnt++; - return buffer->vaddr; + } else { + vaddr = buffer->heap->ops->map_kernel(buffer->heap, buffer); + if (IS_ERR_OR_NULL(vaddr)) { + vaddr = ERR_PTR(-EINVAL); + } else { + buffer->vaddr = vaddr; + buffer->kmap_cnt++; + } } - vaddr = buffer->heap->ops->map_kernel(buffer->heap, buffer); - if (WARN_ONCE(vaddr == NULL, - "heap->ops->map_kernel should return ERR_PTR on error")) - return ERR_PTR(-EINVAL); - if (IS_ERR(vaddr)) - return vaddr; - buffer->vaddr = vaddr; - buffer->kmap_cnt++; + mutex_unlock(&buffer->kmap_lock); + return vaddr; } static void ion_buffer_kmap_put(struct ion_buffer *buffer) { - if (buffer->kmap_cnt == 0) { - pr_warn_ratelimited("ION client likely missing a call to dma_buf_kmap or dma_buf_vmap, pid:%d\n", - current->pid); - return; - } - - buffer->kmap_cnt--; - if (!buffer->kmap_cnt) { + mutex_lock(&buffer->kmap_lock); + if (!--buffer->kmap_cnt) buffer->heap->ops->unmap_kernel(buffer->heap, buffer); - buffer->vaddr = NULL; - } + mutex_unlock(&buffer->kmap_lock); } static struct sg_table *dup_sg_table(struct sg_table *table) { + struct scatterlist *sg, *new_sg; struct sg_table *new_table; int ret, i; - struct scatterlist *sg, *new_sg; - new_table = kzalloc(sizeof(*new_table), GFP_KERNEL); + new_table = kmem_cache_alloc(ion_sg_table_pool, GFP_KERNEL); if (!new_table) return ERR_PTR(-ENOMEM); ret = sg_alloc_table(new_table, table->nents, GFP_KERNEL); if (ret) { - kfree(new_table); + kmem_cache_free(ion_sg_table_pool, new_table); return ERR_PTR(-ENOMEM); } new_sg = new_table->sgl; - for_each_sg(table->sgl, sg, table->nents, i) { - memcpy(new_sg, sg, sizeof(*sg)); + if (new_table->nents <= SG_MAX_SINGLE_ALLOC) { + memcpy(new_sg, table->sgl, new_table->nents * sizeof(*new_sg)); sg_dma_address(new_sg) = 0; sg_dma_len(new_sg) = 0; - new_sg = sg_next(new_sg); + } else { + for_each_sg(table->sgl, sg, table->nents, i) { + *new_sg = *sg; + sg_dma_address(new_sg) = 0; + sg_dma_len(new_sg) = 0; + new_sg = sg_next(new_sg); + } } return new_table; @@ -273,7 +174,7 @@ static struct sg_table *dup_sg_table(struct sg_table *table) static void free_duped_table(struct sg_table *table) { sg_free_table(table); - kfree(table); + kmem_cache_free(ion_sg_table_pool, table); } struct ion_dma_buf_attachment { @@ -300,31 +201,35 @@ static int ion_dma_buf_attach(struct dma_buf *dmabuf, struct device *dev, return -ENOMEM; } - a->table = table; - a->dev = dev; - a->dma_mapped = false; - INIT_LIST_HEAD(&a->list); + *a = (typeof(*a)){ + .table = table, + .dev = dev + }; attachment->priv = a; - mutex_lock(&buffer->lock); - list_add(&a->list, &buffer->attachments); - mutex_unlock(&buffer->lock); + if (buffer->flags & ION_FLAG_CACHED) { + mutex_lock(&buffer->attachment_lock); + list_add(&a->list, &buffer->attachments); + mutex_unlock(&buffer->attachment_lock); + } return 0; } -static void ion_dma_buf_detatch(struct dma_buf *dmabuf, +static void ion_dma_buf_detach(struct dma_buf *dmabuf, struct dma_buf_attachment *attachment) { struct ion_dma_buf_attachment *a = attachment->priv; struct ion_buffer *buffer = dmabuf->priv; - mutex_lock(&buffer->lock); - list_del(&a->list); - mutex_unlock(&buffer->lock); - free_duped_table(a->table); + if (buffer->flags & ION_FLAG_CACHED) { + mutex_lock(&buffer->attachment_lock); + list_del(&a->list); + mutex_unlock(&buffer->attachment_lock); + } + free_duped_table(a->table); kfree(a); } @@ -344,22 +249,6 @@ static struct sg_table *ion_map_dma_buf(struct dma_buf_attachment *attachment, !hlos_accessible_buffer(buffer)) map_attrs |= DMA_ATTR_SKIP_CPU_SYNC; - mutex_lock(&buffer->lock); - if (map_attrs & DMA_ATTR_SKIP_CPU_SYNC) - trace_ion_dma_map_cmo_skip(attachment->dev, - attachment->dmabuf->buf_name, - ion_buffer_cached(buffer), - hlos_accessible_buffer(buffer), - attachment->dma_map_attrs, - direction); - else - trace_ion_dma_map_cmo_apply(attachment->dev, - attachment->dmabuf->buf_name, - ion_buffer_cached(buffer), - hlos_accessible_buffer(buffer), - attachment->dma_map_attrs, - direction); - if (map_attrs & DMA_ATTR_DELAYED_UNMAP) { count = msm_dma_map_sg_attrs(attachment->dev, table->sgl, table->nents, direction, @@ -370,13 +259,10 @@ static struct sg_table *ion_map_dma_buf(struct dma_buf_attachment *attachment, map_attrs); } - if (count <= 0) { - mutex_unlock(&buffer->lock); + if (count <= 0) return ERR_PTR(-ENOMEM); - } a->dma_mapped = true; - mutex_unlock(&buffer->lock); return table; } @@ -393,22 +279,6 @@ static void ion_unmap_dma_buf(struct dma_buf_attachment *attachment, !hlos_accessible_buffer(buffer)) map_attrs |= DMA_ATTR_SKIP_CPU_SYNC; - mutex_lock(&buffer->lock); - if (map_attrs & DMA_ATTR_SKIP_CPU_SYNC) - trace_ion_dma_unmap_cmo_skip(attachment->dev, - attachment->dmabuf->buf_name, - ion_buffer_cached(buffer), - hlos_accessible_buffer(buffer), - attachment->dma_map_attrs, - direction); - else - trace_ion_dma_unmap_cmo_apply(attachment->dev, - attachment->dmabuf->buf_name, - ion_buffer_cached(buffer), - hlos_accessible_buffer(buffer), - attachment->dma_map_attrs, - direction); - if (map_attrs & DMA_ATTR_DELAYED_UNMAP) msm_dma_unmap_sg_attrs(attachment->dev, table->sgl, table->nents, direction, @@ -418,7 +288,6 @@ static void ion_unmap_dma_buf(struct dma_buf_attachment *attachment, dma_unmap_sg_attrs(attachment->dev, table->sgl, table->nents, direction, map_attrs); a->dma_mapped = false; - mutex_unlock(&buffer->lock); } void ion_pages_sync_for_device(struct device *dev, struct page *page, @@ -428,11 +297,6 @@ void ion_pages_sync_for_device(struct device *dev, struct page *page, sg_init_table(&sg, 1); sg_set_page(&sg, page, size, 0); - /* - * This is not correct - sg_dma_address needs a dma_addr_t that is valid - * for the targeted device, but this works on the currently targeted - * hardware. - */ sg_dma_address(&sg) = page_to_phys(page); dma_sync_sg_for_device(dev, &sg, 1, dir); } @@ -445,43 +309,42 @@ static void ion_vm_open(struct vm_area_struct *vma) vma_list = kmalloc(sizeof(*vma_list), GFP_KERNEL); if (!vma_list) return; + vma_list->vma = vma; - mutex_lock(&buffer->lock); + + mutex_lock(&buffer->vma_lock); list_add(&vma_list->list, &buffer->vmas); - mutex_unlock(&buffer->lock); + mutex_unlock(&buffer->vma_lock); } static void ion_vm_close(struct vm_area_struct *vma) { struct ion_buffer *buffer = vma->vm_private_data; - struct ion_vma_list *vma_list, *tmp; + struct ion_vma_list *vma_list; - mutex_lock(&buffer->lock); - list_for_each_entry_safe(vma_list, tmp, &buffer->vmas, list) { - if (vma_list->vma != vma) - continue; - list_del(&vma_list->list); - kfree(vma_list); - break; + mutex_lock(&buffer->vma_lock); + list_for_each_entry(vma_list, &buffer->vmas, list) { + if (vma_list->vma == vma) { + list_del(&vma_list->list); + break; + } } - mutex_unlock(&buffer->lock); + mutex_unlock(&buffer->vma_lock); + + kfree(vma_list); } static const struct vm_operations_struct ion_vma_ops = { .open = ion_vm_open, - .close = ion_vm_close, + .close = ion_vm_close }; static int ion_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) { struct ion_buffer *buffer = dmabuf->priv; - int ret = 0; - if (!buffer->heap->ops->map_user) { - pr_err("%s: this heap does not define a method for mapping to userspace\n", - __func__); + if (!buffer->heap->ops->map_user) return -EINVAL; - } if (!(buffer->flags & ION_FLAG_CACHED)) vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); @@ -490,16 +353,7 @@ static int ion_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) vma->vm_ops = &ion_vma_ops; ion_vm_open(vma); - mutex_lock(&buffer->lock); - /* now map it to userspace */ - ret = buffer->heap->ops->map_user(buffer->heap, buffer, vma); - mutex_unlock(&buffer->lock); - - if (ret) - pr_err("%s: failure mapping buffer to userspace\n", - __func__); - - return ret; + return buffer->heap->ops->map_user(buffer->heap, buffer, vma); } static void ion_dma_buf_release(struct dma_buf *dmabuf) @@ -507,35 +361,23 @@ static void ion_dma_buf_release(struct dma_buf *dmabuf) struct ion_buffer *buffer = dmabuf->priv; _ion_buffer_destroy(buffer); - kfree(dmabuf->exp_name); } static void *ion_dma_buf_vmap(struct dma_buf *dmabuf) { struct ion_buffer *buffer = dmabuf->priv; - void *vaddr = ERR_PTR(-EINVAL); - if (buffer->heap->ops->map_kernel) { - mutex_lock(&buffer->lock); - vaddr = ion_buffer_kmap_get(buffer); - mutex_unlock(&buffer->lock); - } else { - pr_warn_ratelimited("heap %s doesn't support map_kernel\n", - buffer->heap->name); - } + if (!buffer->heap->ops->map_kernel) + return ERR_PTR(-EINVAL); - return vaddr; + return ion_buffer_kmap_get(buffer); } static void ion_dma_buf_vunmap(struct dma_buf *dmabuf, void *vaddr) { struct ion_buffer *buffer = dmabuf->priv; - if (buffer->heap->ops->map_kernel) { - mutex_lock(&buffer->lock); - ion_buffer_kmap_put(buffer); - mutex_unlock(&buffer->lock); - } + ion_buffer_kmap_put(buffer); } static void *ion_dma_buf_kmap(struct dma_buf *dmabuf, unsigned long offset) @@ -649,63 +491,18 @@ static int __ion_dma_buf_begin_cpu_access(struct dma_buf *dmabuf, struct ion_dma_buf_attachment *a; int ret = 0; - if (!hlos_accessible_buffer(buffer)) { - trace_ion_begin_cpu_access_cmo_skip(NULL, dmabuf->buf_name, - ion_buffer_cached(buffer), - false, direction, - sync_only_mapped); - ret = -EPERM; - goto out; - } + if (!hlos_accessible_buffer(buffer)) + return -EPERM; - if (!(buffer->flags & ION_FLAG_CACHED)) { - trace_ion_begin_cpu_access_cmo_skip(NULL, dmabuf->buf_name, - false, true, direction, - sync_only_mapped); - goto out; - } - - mutex_lock(&buffer->lock); - - if (IS_ENABLED(CONFIG_ION_FORCE_DMA_SYNC)) { - struct device *dev = buffer->heap->priv; - struct sg_table *table = buffer->sg_table; - - if (sync_only_mapped) - ret = ion_sgl_sync_mapped(dev, table->sgl, - table->nents, &buffer->vmas, - direction, true); - else - dma_sync_sg_for_cpu(dev, table->sgl, - table->nents, direction); - - if (!ret) - trace_ion_begin_cpu_access_cmo_apply(dev, - dmabuf->buf_name, - true, true, - direction, - sync_only_mapped); - else - trace_ion_begin_cpu_access_cmo_skip(dev, - dmabuf->buf_name, - true, true, - direction, - sync_only_mapped); - mutex_unlock(&buffer->lock); - goto out; - } + if (!(buffer->flags & ION_FLAG_CACHED)) + return 0; + mutex_lock(&buffer->attachment_lock); list_for_each_entry(a, &buffer->attachments, list) { int tmp = 0; - if (!a->dma_mapped) { - trace_ion_begin_cpu_access_notmapped(a->dev, - dmabuf->buf_name, - true, true, - direction, - sync_only_mapped); + if (!a->dma_mapped) continue; - } if (sync_only_mapped) tmp = ion_sgl_sync_mapped(a->dev, a->table->sgl, @@ -716,25 +513,11 @@ static int __ion_dma_buf_begin_cpu_access(struct dma_buf *dmabuf, dma_sync_sg_for_cpu(a->dev, a->table->sgl, a->table->nents, direction); - if (!tmp) { - trace_ion_begin_cpu_access_cmo_apply(a->dev, - dmabuf->buf_name, - true, true, - direction, - sync_only_mapped); - } else { - trace_ion_begin_cpu_access_cmo_skip(a->dev, - dmabuf->buf_name, - true, true, - direction, - sync_only_mapped); + if (tmp) ret = tmp; - } - } - mutex_unlock(&buffer->lock); + mutex_unlock(&buffer->attachment_lock); -out: return ret; } @@ -746,60 +529,18 @@ static int __ion_dma_buf_end_cpu_access(struct dma_buf *dmabuf, struct ion_dma_buf_attachment *a; int ret = 0; - if (!hlos_accessible_buffer(buffer)) { - trace_ion_end_cpu_access_cmo_skip(NULL, dmabuf->buf_name, - ion_buffer_cached(buffer), - false, direction, - sync_only_mapped); - ret = -EPERM; - goto out; - } + if (!hlos_accessible_buffer(buffer)) + return -EPERM; - if (!(buffer->flags & ION_FLAG_CACHED)) { - trace_ion_end_cpu_access_cmo_skip(NULL, dmabuf->buf_name, false, - true, direction, - sync_only_mapped); - goto out; - } - - mutex_lock(&buffer->lock); - if (IS_ENABLED(CONFIG_ION_FORCE_DMA_SYNC)) { - struct device *dev = buffer->heap->priv; - struct sg_table *table = buffer->sg_table; - - if (sync_only_mapped) - ret = ion_sgl_sync_mapped(dev, table->sgl, - table->nents, &buffer->vmas, - direction, false); - else - dma_sync_sg_for_device(dev, table->sgl, - table->nents, direction); - - if (!ret) - trace_ion_end_cpu_access_cmo_apply(dev, - dmabuf->buf_name, - true, true, - direction, - sync_only_mapped); - else - trace_ion_end_cpu_access_cmo_skip(dev, dmabuf->buf_name, - true, true, direction, - sync_only_mapped); - mutex_unlock(&buffer->lock); - goto out; - } + if (!(buffer->flags & ION_FLAG_CACHED)) + return 0; + mutex_lock(&buffer->attachment_lock); list_for_each_entry(a, &buffer->attachments, list) { int tmp = 0; - if (!a->dma_mapped) { - trace_ion_end_cpu_access_notmapped(a->dev, - dmabuf->buf_name, - true, true, - direction, - sync_only_mapped); + if (!a->dma_mapped) continue; - } if (sync_only_mapped) tmp = ion_sgl_sync_mapped(a->dev, a->table->sgl, @@ -810,23 +551,11 @@ static int __ion_dma_buf_end_cpu_access(struct dma_buf *dmabuf, dma_sync_sg_for_device(a->dev, a->table->sgl, a->table->nents, direction); - if (!tmp) { - trace_ion_end_cpu_access_cmo_apply(a->dev, - dmabuf->buf_name, - true, true, - direction, - sync_only_mapped); - } else { - trace_ion_end_cpu_access_cmo_skip(a->dev, - dmabuf->buf_name, - true, true, direction, - sync_only_mapped); + if (tmp) ret = tmp; - } } - mutex_unlock(&buffer->lock); + mutex_unlock(&buffer->attachment_lock); -out: return ret; } @@ -863,76 +592,27 @@ static int ion_dma_buf_begin_cpu_access_partial(struct dma_buf *dmabuf, struct ion_dma_buf_attachment *a; int ret = 0; - if (!hlos_accessible_buffer(buffer)) { - trace_ion_begin_cpu_access_cmo_skip(NULL, dmabuf->buf_name, - ion_buffer_cached(buffer), - false, dir, - false); - ret = -EPERM; - goto out; - } + if (!hlos_accessible_buffer(buffer)) + return -EPERM; - if (!(buffer->flags & ION_FLAG_CACHED)) { - trace_ion_begin_cpu_access_cmo_skip(NULL, dmabuf->buf_name, - false, true, dir, - false); - goto out; - } - - mutex_lock(&buffer->lock); - if (IS_ENABLED(CONFIG_ION_FORCE_DMA_SYNC)) { - struct device *dev = buffer->heap->priv; - struct sg_table *table = buffer->sg_table; - - ret = ion_sgl_sync_range(dev, table->sgl, table->nents, - offset, len, dir, true); - - if (!ret) - trace_ion_begin_cpu_access_cmo_apply(dev, - dmabuf->buf_name, - true, true, dir, - false); - else - trace_ion_begin_cpu_access_cmo_skip(dev, - dmabuf->buf_name, - true, true, dir, - false); - mutex_unlock(&buffer->lock); - goto out; - } + if (!(buffer->flags & ION_FLAG_CACHED)) + return 0; + mutex_lock(&buffer->attachment_lock); list_for_each_entry(a, &buffer->attachments, list) { int tmp = 0; - if (!a->dma_mapped) { - trace_ion_begin_cpu_access_notmapped(a->dev, - dmabuf->buf_name, - true, true, - dir, - false); + if (!a->dma_mapped) continue; - } - tmp = ion_sgl_sync_range(a->dev, a->table->sgl, a->table->nents, + ret = ion_sgl_sync_range(a->dev, a->table->sgl, a->table->nents, offset, len, dir, true); - if (!tmp) { - trace_ion_begin_cpu_access_cmo_apply(a->dev, - dmabuf->buf_name, - true, true, dir, - false); - } else { - trace_ion_begin_cpu_access_cmo_skip(a->dev, - dmabuf->buf_name, - true, true, dir, - false); + if (tmp) ret = tmp; - } - } - mutex_unlock(&buffer->lock); + mutex_unlock(&buffer->attachment_lock); -out: return ret; } @@ -945,76 +625,27 @@ static int ion_dma_buf_end_cpu_access_partial(struct dma_buf *dmabuf, struct ion_dma_buf_attachment *a; int ret = 0; - if (!hlos_accessible_buffer(buffer)) { - trace_ion_end_cpu_access_cmo_skip(NULL, dmabuf->buf_name, - ion_buffer_cached(buffer), - false, direction, - false); - ret = -EPERM; - goto out; - } + if (!hlos_accessible_buffer(buffer)) + return -EPERM; - if (!(buffer->flags & ION_FLAG_CACHED)) { - trace_ion_end_cpu_access_cmo_skip(NULL, dmabuf->buf_name, false, - true, direction, - false); - goto out; - } - - mutex_lock(&buffer->lock); - if (IS_ENABLED(CONFIG_ION_FORCE_DMA_SYNC)) { - struct device *dev = buffer->heap->priv; - struct sg_table *table = buffer->sg_table; - - ret = ion_sgl_sync_range(dev, table->sgl, table->nents, - offset, len, direction, false); - - if (!ret) - trace_ion_end_cpu_access_cmo_apply(dev, - dmabuf->buf_name, - true, true, - direction, false); - else - trace_ion_end_cpu_access_cmo_skip(dev, dmabuf->buf_name, - true, true, - direction, false); - - mutex_unlock(&buffer->lock); - goto out; - } + if (!(buffer->flags & ION_FLAG_CACHED)) + return 0; + mutex_lock(&buffer->attachment_lock); list_for_each_entry(a, &buffer->attachments, list) { int tmp = 0; - if (!a->dma_mapped) { - trace_ion_end_cpu_access_notmapped(a->dev, - dmabuf->buf_name, - true, true, - direction, - false); + if (!a->dma_mapped) continue; - } - tmp = ion_sgl_sync_range(a->dev, a->table->sgl, a->table->nents, + ret = ion_sgl_sync_range(a->dev, a->table->sgl, a->table->nents, offset, len, direction, false); - if (!tmp) { - trace_ion_end_cpu_access_cmo_apply(a->dev, - dmabuf->buf_name, - true, true, - direction, false); - - } else { - trace_ion_end_cpu_access_cmo_skip(a->dev, - dmabuf->buf_name, - true, true, direction, - false); + if (tmp) ret = tmp; - } } - mutex_unlock(&buffer->lock); + mutex_unlock(&buffer->attachment_lock); -out: return ret; } @@ -1022,8 +653,8 @@ static int ion_dma_buf_get_flags(struct dma_buf *dmabuf, unsigned long *flags) { struct ion_buffer *buffer = dmabuf->priv; - *flags = buffer->flags; + *flags = buffer->flags; return 0; } @@ -1033,7 +664,7 @@ static const struct dma_buf_ops dma_buf_ops = { .mmap = ion_mmap, .release = ion_dma_buf_release, .attach = ion_dma_buf_attach, - .detach = ion_dma_buf_detatch, + .detach = ion_dma_buf_detach, .begin_cpu_access = ion_dma_buf_begin_cpu_access, .end_cpu_access = ion_dma_buf_end_cpu_access, .begin_cpu_access_umapped = ion_dma_buf_begin_cpu_access_umapped, @@ -1046,116 +677,59 @@ static const struct dma_buf_ops dma_buf_ops = { .unmap = ion_dma_buf_kunmap, .vmap = ion_dma_buf_vmap, .vunmap = ion_dma_buf_vunmap, - .get_flags = ion_dma_buf_get_flags, + .get_flags = ion_dma_buf_get_flags }; -struct dma_buf *ion_alloc_dmabuf(size_t len, unsigned int heap_id_mask, - unsigned int flags) -{ - struct ion_device *dev = internal_dev; - struct ion_buffer *buffer = NULL; - struct ion_heap *heap; - DEFINE_DMA_BUF_EXPORT_INFO(exp_info); - struct dma_buf *dmabuf; - char task_comm[TASK_COMM_LEN]; - - pr_debug("%s: len %zu heap_id_mask %u flags %x\n", __func__, - len, heap_id_mask, flags); - /* - * traverse the list of heaps available in this system in priority - * order. If the heap type is supported by the client, and matches the - * request of the caller allocate from it. Repeat until allocate has - * succeeded or all heaps have been tried - */ - len = PAGE_ALIGN(len); - - if (!len) - return ERR_PTR(-EINVAL); - - down_read(&dev->lock); - plist_for_each_entry(heap, &dev->heaps, node) { - /* if the caller didn't specify this heap id */ - if (!((1 << heap->id) & heap_id_mask)) - continue; - buffer = ion_buffer_create(heap, dev, len, flags); - if (!IS_ERR(buffer) || PTR_ERR(buffer) == -EINTR) - break; - } - up_read(&dev->lock); - - if (!buffer) - return ERR_PTR(-ENODEV); - - if (IS_ERR(buffer)) - return ERR_CAST(buffer); - - get_task_comm(task_comm, current->group_leader); - - exp_info.ops = &dma_buf_ops; - exp_info.size = buffer->size; - exp_info.flags = O_RDWR; - exp_info.priv = buffer; - exp_info.exp_name = kasprintf(GFP_KERNEL, "%s-%s-%d-%s", KBUILD_MODNAME, - heap->name, current->tgid, task_comm); - - dmabuf = dma_buf_export(&exp_info); - if (IS_ERR(dmabuf)) { - _ion_buffer_destroy(buffer); - kfree(exp_info.exp_name); - } - - return dmabuf; -} - struct dma_buf *ion_alloc(size_t len, unsigned int heap_id_mask, unsigned int flags) { struct ion_device *dev = internal_dev; + struct dma_buf_export_info exp_info; + struct ion_buffer *buffer = NULL; + struct dma_buf *dmabuf; struct ion_heap *heap; - bool type_valid = false; - pr_debug("%s: len %zu heap_id_mask %u flags %x\n", __func__, - len, heap_id_mask, flags); - /* - * traverse the list of heaps available in this system in priority - * order. Check the heap type is supported. - */ - - down_read(&dev->lock); - plist_for_each_entry(heap, &dev->heaps, node) { - /* if the caller didn't specify this heap id */ - if (!((1 << heap->id) & heap_id_mask)) - continue; - if (heap->type == ION_HEAP_TYPE_SYSTEM || - heap->type == ION_HEAP_TYPE_CARVEOUT || - heap->type == (enum ion_heap_type)ION_HEAP_TYPE_HYP_CMA || - heap->type == - (enum ion_heap_type)ION_HEAP_TYPE_SYSTEM_SECURE) { - type_valid = true; - } else { - pr_warn("%s: heap type not supported, type:%d\n", - __func__, heap->type); - } - break; - } - up_read(&dev->lock); - - if (!type_valid) + len = PAGE_ALIGN(len); + if (!len) return ERR_PTR(-EINVAL); - return ion_alloc_dmabuf(len, heap_id_mask, flags); + down_read(&dev->heap_lock); + plist_for_each_entry(heap, &dev->heaps, node) { + if (!(BIT(heap->id) & heap_id_mask)) + continue; + + buffer = ion_buffer_create(heap, dev, len, flags); + if (!IS_ERR(buffer) || PTR_ERR(buffer) == -EINTR) + break; + } + up_read(&dev->heap_lock); + + if (IS_ERR_OR_NULL(buffer)) + return ERR_PTR(-EINVAL); + + exp_info = (typeof(exp_info)){ + .ops = &dma_buf_ops, + .flags = O_RDWR, + .size = buffer->size, + .priv = buffer + }; + + dmabuf = dma_buf_export(&exp_info); + if (IS_ERR(dmabuf)) + _ion_buffer_destroy(buffer); + + return dmabuf; } EXPORT_SYMBOL(ion_alloc); int ion_alloc_fd(size_t len, unsigned int heap_id_mask, unsigned int flags) { - int fd; struct dma_buf *dmabuf; + int fd; - dmabuf = ion_alloc_dmabuf(len, heap_id_mask, flags); - if (IS_ERR(dmabuf)) { + dmabuf = ion_alloc(len, heap_id_mask, flags); + if (IS_ERR(dmabuf)) return PTR_ERR(dmabuf); - } fd = dma_buf_fd(dmabuf, O_CLOEXEC); if (fd < 0) @@ -1166,47 +740,47 @@ int ion_alloc_fd(size_t len, unsigned int heap_id_mask, unsigned int flags) int ion_query_heaps(struct ion_heap_query *query) { + struct ion_heap_data __user *ubuf = u64_to_user_ptr(query->heaps); struct ion_device *dev = internal_dev; - struct ion_heap_data __user *buffer = u64_to_user_ptr(query->heaps); - int ret = -EINVAL, cnt = 0, max_cnt; - struct ion_heap *heap; struct ion_heap_data hdata; + struct ion_heap *heap; + int cnt = 0, max_cnt; memset(&hdata, 0, sizeof(hdata)); - down_read(&dev->lock); - if (!buffer) { + if (!ubuf) { + down_read(&dev->heap_lock); query->cnt = dev->heap_cnt; - ret = 0; - goto out; + up_read(&dev->heap_lock); + + return 0; } if (query->cnt <= 0) - goto out; + return -EINVAL; max_cnt = query->cnt; + down_read(&dev->heap_lock); plist_for_each_entry(heap, &dev->heaps, node) { strlcpy(hdata.name, heap->name, sizeof(hdata.name)); hdata.name[sizeof(hdata.name) - 1] = '\0'; hdata.type = heap->type; hdata.heap_id = heap->id; - if (copy_to_user(&buffer[cnt], &hdata, sizeof(hdata))) { - ret = -EFAULT; - goto out; + if (copy_to_user(&ubuf[cnt], &hdata, sizeof(hdata))) { + up_read(&dev->heap_lock); + return -EFAULT; } cnt++; if (cnt >= max_cnt) break; } + up_read(&dev->heap_lock); query->cnt = cnt; - ret = 0; -out: - up_read(&dev->lock); - return ret; + return 0; } static const struct file_operations ion_fops = { @@ -1217,121 +791,55 @@ static const struct file_operations ion_fops = { #endif }; -static int debug_shrink_set(void *data, u64 val) -{ - struct ion_heap *heap = data; - struct shrink_control sc; - int objs; - - sc.gfp_mask = GFP_HIGHUSER; - sc.nr_to_scan = val; - - if (!val) { - objs = heap->shrinker.count_objects(&heap->shrinker, &sc); - sc.nr_to_scan = objs; - } - - heap->shrinker.scan_objects(&heap->shrinker, &sc); - return 0; -} - -static int debug_shrink_get(void *data, u64 *val) -{ - struct ion_heap *heap = data; - struct shrink_control sc; - int objs; - - sc.gfp_mask = GFP_HIGHUSER; - sc.nr_to_scan = 0; - - objs = heap->shrinker.count_objects(&heap->shrinker, &sc); - *val = objs; - return 0; -} - -DEFINE_SIMPLE_ATTRIBUTE(debug_shrink_fops, debug_shrink_get, - debug_shrink_set, "%llu\n"); - void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap) { - struct dentry *debug_file; - - if (!heap->ops->allocate || !heap->ops->free) - pr_err("%s: can not add heap with invalid ops struct.\n", - __func__); - spin_lock_init(&heap->free_lock); heap->free_list_size = 0; if (heap->flags & ION_HEAP_FLAG_DEFER_FREE) ion_heap_init_deferred_free(heap); - if ((heap->flags & ION_HEAP_FLAG_DEFER_FREE) || heap->ops->shrink) + if (heap->flags & ION_HEAP_FLAG_DEFER_FREE || heap->ops->shrink) ion_heap_init_shrinker(heap); heap->dev = dev; - down_write(&dev->lock); - /* - * use negative heap->id to reverse the priority -- when traversing - * the list later attempt higher id numbers first - */ plist_node_init(&heap->node, -heap->id); + + down_write(&dev->heap_lock); plist_add(&heap->node, &dev->heaps); - - if (heap->shrinker.count_objects && heap->shrinker.scan_objects) { - char debug_name[64]; - - snprintf(debug_name, 64, "%s_shrink", heap->name); - debug_file = debugfs_create_file( - debug_name, 0644, dev->debug_root, heap, - &debug_shrink_fops); - if (!debug_file) { - char buf[256], *path; - - path = dentry_path(dev->debug_root, buf, 256); - pr_err("Failed to create heap shrinker debugfs at %s/%s\n", - path, debug_name); - } - } - dev->heap_cnt++; - up_write(&dev->lock); + up_write(&dev->heap_lock); } -EXPORT_SYMBOL(ion_device_add_heap); struct ion_device *ion_device_create(void) { - struct ion_device *idev; + struct ion_device *dev; int ret; - idev = kzalloc(sizeof(*idev), GFP_KERNEL); - if (!idev) + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) return ERR_PTR(-ENOMEM); - idev->dev.minor = MISC_DYNAMIC_MINOR; - idev->dev.name = "ion"; - idev->dev.fops = &ion_fops; - idev->dev.parent = NULL; - ret = misc_register(&idev->dev); - if (ret) { - pr_err("ion: failed to register misc device.\n"); - kfree(idev); - return ret; - } + ion_sg_table_pool = KMEM_CACHE(sg_table, SLAB_HWCACHE_ALIGN); + if (!ion_sg_table_pool) + goto free_dev; - idev->debug_root = debugfs_create_dir("ion", NULL); - if (!idev->debug_root) { - pr_err("ion: failed to create debugfs root directory.\n"); - goto debugfs_done; - } + dev->dev.minor = MISC_DYNAMIC_MINOR; + dev->dev.name = "ion"; + dev->dev.fops = &ion_fops; + dev->dev.parent = NULL; + ret = misc_register(&dev->dev); + if (ret) + goto free_table_pool; -debugfs_done: + init_rwsem(&dev->heap_lock); + plist_head_init(&dev->heaps); + internal_dev = dev; + return dev; - idev->buffers = RB_ROOT; - mutex_init(&idev->buffer_lock); - init_rwsem(&idev->lock); - plist_head_init(&idev->heaps); - internal_dev = idev; - return idev; +free_table_pool: + kmem_cache_destroy(ion_sg_table_pool); +free_dev: + kfree(dev); + return ERR_PTR(-ENOMEM); } -EXPORT_SYMBOL(ion_device_create); diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index 9a532298c627..cdd02b5a0f0d 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -48,21 +48,6 @@ #define ION_IS_CACHED(__flags) ((__flags) & ION_FLAG_CACHED) -/** - * Debug feature. Make ION allocations DMA - * ready to help identify clients who are wrongly - * dependending on ION allocations being DMA - * ready. - * - * As default set to 'false' since ION allocations - * are no longer required to be DMA ready - */ -#ifdef CONFIG_ION_FORCE_DMA_SYNC -#define MAKE_ION_ALLOC_DMA_READY 1 -#else -#define MAKE_ION_ALLOC_DMA_READY 0 -#endif - /** * struct ion_platform_heap - defines a heap in the given platform * @type: type of the heap from ion_heap_type enum @@ -121,18 +106,16 @@ struct ion_vma_list { * @vmas: list of vma's mapping this buffer */ struct ion_buffer { - union { - struct rb_node node; - struct list_head list; - }; + struct list_head list; struct ion_device *dev; struct ion_heap *heap; unsigned long flags; unsigned long private_flags; size_t size; void *priv_virt; - /* Protect ion buffer */ - struct mutex lock; + struct mutex attachment_lock; + struct mutex kmap_lock; + struct mutex vma_lock; int kmap_cnt; void *vaddr; struct sg_table *sg_table; @@ -142,21 +125,10 @@ struct ion_buffer { void ion_buffer_destroy(struct ion_buffer *buffer); -/** - * struct ion_device - the metadata of the ion device node - * @dev: the actual misc device - * @buffers: an rb tree of all the existing buffers - * @buffer_lock: lock protecting the tree of buffers - * @lock: rwsem protecting the tree of heaps and clients - */ struct ion_device { struct miscdevice dev; - struct rb_root buffers; - /* buffer_lock used for adding and removing buffers */ - struct mutex buffer_lock; - struct rw_semaphore lock; struct plist_head heaps; - struct dentry *debug_root; + struct rw_semaphore heap_lock; int heap_cnt; }; @@ -221,8 +193,6 @@ struct ion_heap_ops { * @lock: protects the free list * @waitqueue: queue to wait on from deferred free thread * @task: task struct of deferred free thread - * @debug_show: called when heap debug file is read to add any - * heap specific debug info to output * * Represents a pool of memory from which buffers can be made. In some * systems the only heap is regular system memory allocated via vmalloc. @@ -244,28 +214,12 @@ struct ion_heap { /* Protect the free list */ spinlock_t free_lock; wait_queue_head_t waitqueue; - struct task_struct *task; - atomic_long_t total_allocated; - - int (*debug_show)(struct ion_heap *heap, struct seq_file *, void *); }; -/** - * ion_buffer_cached - this ion buffer is cached - * @buffer: buffer - * - * indicates whether this ion buffer is cached - */ -bool ion_buffer_cached(struct ion_buffer *buffer); - -/** - * ion_buffer_fault_user_mappings - fault in user mappings of this buffer - * @buffer: buffer - * - * indicates whether userspace mappings of this buffer will be faulted - * in, this can affect how buffers are allocated from the heap. - */ -bool ion_buffer_fault_user_mappings(struct ion_buffer *buffer); +static inline bool ion_buffer_cached(struct ion_buffer *buffer) +{ + return buffer->flags & ION_FLAG_CACHED; +} /** * ion_device_create - allocates and returns an ion device @@ -438,7 +392,7 @@ struct ion_page_pool { struct list_head high_items; struct list_head low_items; /* Protect the pool */ - struct mutex mutex; + spinlock_t lock; gfp_t gfp_mask; unsigned int order; struct plist_node list; diff --git a/drivers/staging/android/ion/ion_cma_heap.c b/drivers/staging/android/ion/ion_cma_heap.c index 63a6a94a933a..de1123e16602 100644 --- a/drivers/staging/android/ion/ion_cma_heap.c +++ b/drivers/staging/android/ion/ion_cma_heap.c @@ -124,8 +124,7 @@ static int ion_cma_allocate(struct ion_heap *heap, struct ion_buffer *buffer, } } - if (MAKE_ION_ALLOC_DMA_READY || - (!hlos_accessible_buffer(buffer)) || + if ((!hlos_accessible_buffer(buffer)) || !ion_buffer_cached(buffer)) ion_pages_sync_for_device(dev, pages, size, DMA_BIDIRECTIONAL); diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index c682f1ea745c..bc60ee81225f 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -224,8 +224,17 @@ size_t ion_heap_freelist_shrink(struct ion_heap *heap, size_t size) static int ion_heap_deferred_free(void *data) { +#ifndef CONFIG_ION_DEFER_FREE_NO_SCHED_IDLE + static const struct sched_param param = { + .sched_priority = 0 + }; +#endif struct ion_heap *heap = data; +#ifndef CONFIG_ION_DEFER_FREE_NO_SCHED_IDLE + sched_setscheduler(current, SCHED_IDLE, ¶m); +#endif + while (true) { struct ion_buffer *buffer; @@ -250,21 +259,16 @@ static int ion_heap_deferred_free(void *data) int ion_heap_init_deferred_free(struct ion_heap *heap) { -#ifndef CONFIG_ION_DEFER_FREE_NO_SCHED_IDLE - struct sched_param param = { .sched_priority = 0 }; -#endif + struct task_struct *thread; + INIT_LIST_HEAD(&heap->free_list); init_waitqueue_head(&heap->waitqueue); - heap->task = kthread_run(ion_heap_deferred_free, heap, - "%s", heap->name); - if (IS_ERR(heap->task)) { + thread = kthread_run(ion_heap_deferred_free, heap, "%s", heap->name); + if (IS_ERR(thread)) { pr_err("%s: creating thread for deferred free failed\n", __func__); - return PTR_ERR_OR_ZERO(heap->task); + return PTR_ERR_OR_ZERO(thread); } -#ifndef CONFIG_ION_DEFER_FREE_NO_SCHED_IDLE - sched_setscheduler(heap->task, SCHED_IDLE, ¶m); -#endif return 0; } diff --git a/drivers/staging/android/ion/ion_page_pool.c b/drivers/staging/android/ion/ion_page_pool.c index b95a7ce2e20b..180cb231aff9 100644 --- a/drivers/staging/android/ion/ion_page_pool.c +++ b/drivers/staging/android/ion/ion_page_pool.c @@ -41,7 +41,7 @@ static void ion_page_pool_free_pages(struct ion_page_pool *pool, static int ion_page_pool_add(struct ion_page_pool *pool, struct page *page) { - mutex_lock(&pool->mutex); + spin_lock(&pool->lock); if (PageHighMem(page)) { list_add_tail(&page->lru, &pool->high_items); pool->high_count++; @@ -52,7 +52,7 @@ static int ion_page_pool_add(struct ion_page_pool *pool, struct page *page) mod_node_page_state(page_pgdat(page), NR_KERNEL_MISC_RECLAIMABLE, 1 << pool->order); - mutex_unlock(&pool->mutex); + spin_unlock(&pool->lock); return 0; } @@ -85,12 +85,12 @@ struct page *ion_page_pool_alloc(struct ion_page_pool *pool, bool *from_pool) if (fatal_signal_pending(current)) return ERR_PTR(-EINTR); - if (*from_pool && mutex_trylock(&pool->mutex)) { + if (*from_pool && spin_trylock(&pool->lock)) { if (pool->high_count) page = ion_page_pool_remove(pool, true); else if (pool->low_count) page = ion_page_pool_remove(pool, false); - mutex_unlock(&pool->mutex); + spin_unlock(&pool->lock); } if (!page) { page = ion_page_pool_alloc_pages(pool); @@ -112,12 +112,12 @@ struct page *ion_page_pool_alloc_pool_only(struct ion_page_pool *pool) if (!pool) return ERR_PTR(-EINVAL); - if (mutex_trylock(&pool->mutex)) { + if (spin_trylock(&pool->lock)) { if (pool->high_count) page = ion_page_pool_remove(pool, true); else if (pool->low_count) page = ion_page_pool_remove(pool, false); - mutex_unlock(&pool->mutex); + spin_unlock(&pool->lock); } if (!page) @@ -166,16 +166,16 @@ int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask, while (freed < nr_to_scan) { struct page *page; - mutex_lock(&pool->mutex); + spin_lock(&pool->lock); if (pool->low_count) { page = ion_page_pool_remove(pool, false); } else if (high && pool->high_count) { page = ion_page_pool_remove(pool, true); } else { - mutex_unlock(&pool->mutex); + spin_unlock(&pool->lock); break; } - mutex_unlock(&pool->mutex); + spin_unlock(&pool->lock); ion_page_pool_free_pages(pool, page); freed += (1 << pool->order); } @@ -196,7 +196,7 @@ struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order, INIT_LIST_HEAD(&pool->high_items); pool->gfp_mask = gfp_mask; pool->order = order; - mutex_init(&pool->mutex); + spin_lock_init(&pool->lock); plist_node_init(&pool->list, order); if (cached) pool->cached = true; diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 8f57416b930f..614144927da9 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -86,7 +86,7 @@ static struct page *alloc_buffer_page(struct ion_system_heap *heap, if (IS_ERR(page)) return page; - if ((MAKE_ION_ALLOC_DMA_READY && vmid <= 0) || !(*from_pool)) + if (!(*from_pool)) ion_pages_sync_for_device(dev, page, PAGE_SIZE << order, DMA_BIDIRECTIONAL); @@ -525,106 +525,6 @@ static struct ion_heap_ops system_heap_ops = { .shrink = ion_system_heap_shrink, }; -static int ion_system_heap_debug_show(struct ion_heap *heap, struct seq_file *s, - void *unused) -{ - - struct ion_system_heap *sys_heap = container_of( - heap, struct ion_system_heap, heap); - bool use_seq = s; - unsigned long uncached_total = 0; - unsigned long cached_total = 0; - unsigned long secure_total = 0; - struct ion_page_pool *pool; - int i, j; - - for (i = 0; i < NUM_ORDERS; i++) { - pool = sys_heap->uncached_pools[i]; - if (use_seq) { - seq_printf(s, - "%d order %u highmem pages in uncached pool = %lu total\n", - pool->high_count, pool->order, - (1 << pool->order) * PAGE_SIZE * - pool->high_count); - seq_printf(s, - "%d order %u lowmem pages in uncached pool = %lu total\n", - pool->low_count, pool->order, - (1 << pool->order) * PAGE_SIZE * - pool->low_count); - } - - uncached_total += (1 << pool->order) * PAGE_SIZE * - pool->high_count; - uncached_total += (1 << pool->order) * PAGE_SIZE * - pool->low_count; - } - - for (i = 0; i < NUM_ORDERS; i++) { - pool = sys_heap->cached_pools[i]; - if (use_seq) { - seq_printf(s, - "%d order %u highmem pages in cached pool = %lu total\n", - pool->high_count, pool->order, - (1 << pool->order) * PAGE_SIZE * - pool->high_count); - seq_printf(s, - "%d order %u lowmem pages in cached pool = %lu total\n", - pool->low_count, pool->order, - (1 << pool->order) * PAGE_SIZE * - pool->low_count); - } - - cached_total += (1 << pool->order) * PAGE_SIZE * - pool->high_count; - cached_total += (1 << pool->order) * PAGE_SIZE * - pool->low_count; - } - - for (i = 0; i < NUM_ORDERS; i++) { - for (j = 0; j < VMID_LAST; j++) { - if (!is_secure_vmid_valid(j)) - continue; - pool = sys_heap->secure_pools[j][i]; - - if (use_seq) { - seq_printf(s, - "VMID %d: %d order %u highmem pages in secure pool = %lu total\n", - j, pool->high_count, pool->order, - (1 << pool->order) * PAGE_SIZE * - pool->high_count); - seq_printf(s, - "VMID %d: %d order %u lowmem pages in secure pool = %lu total\n", - j, pool->low_count, pool->order, - (1 << pool->order) * PAGE_SIZE * - pool->low_count); - } - - secure_total += (1 << pool->order) * PAGE_SIZE * - pool->high_count; - secure_total += (1 << pool->order) * PAGE_SIZE * - pool->low_count; - } - } - - if (use_seq) { - seq_puts(s, "--------------------------------------------\n"); - seq_printf(s, "uncached pool = %lu cached pool = %lu secure pool = %lu\n", - uncached_total, cached_total, secure_total); - seq_printf(s, "pool total (uncached + cached + secure) = %lu\n", - uncached_total + cached_total + secure_total); - seq_puts(s, "--------------------------------------------\n"); - } else { - pr_info("-------------------------------------------------\n"); - pr_info("uncached pool = %lu cached pool = %lu secure pool = %lu\n", - uncached_total, cached_total, secure_total); - pr_info("pool total (uncached + cached + secure) = %lu\n", - uncached_total + cached_total + secure_total); - pr_info("-------------------------------------------------\n"); - } - - return 0; -} - static void ion_system_heap_destroy_pools(struct ion_page_pool **pools) { int i; @@ -695,7 +595,6 @@ struct ion_heap *ion_system_heap_create(struct ion_platform_heap *data) mutex_init(&heap->split_page_mutex); - heap->heap.debug_show = ion_system_heap_debug_show; return &heap->heap; destroy_uncached_pools: diff --git a/drivers/staging/android/ion/msm_ion_priv.h b/drivers/staging/android/ion/msm_ion_priv.h index 181ae1cc2c05..11baa424aa6d 100644 --- a/drivers/staging/android/ion/msm_ion_priv.h +++ b/drivers/staging/android/ion/msm_ion_priv.h @@ -40,10 +40,6 @@ int ion_system_secure_heap_drain(struct ion_heap *heap, void *data); struct ion_heap *ion_cma_secure_heap_create(struct ion_platform_heap *heap); void ion_cma_secure_heap_destroy(struct ion_heap *heap); -long msm_ion_custom_ioctl(struct ion_client *client, - unsigned int cmd, - unsigned long arg); - #ifdef CONFIG_CMA struct ion_heap *ion_secure_cma_heap_create(struct ion_platform_heap *heap); void ion_secure_cma_heap_destroy(struct ion_heap *heap); @@ -95,18 +91,5 @@ bool is_secure_vmid_valid(int vmid); int ion_system_secure_heap_unassign_sg(struct sg_table *sgt, int source_vmid); int ion_system_secure_heap_assign_sg(struct sg_table *sgt, int dest_vmid); -/** - * ion_create_chunked_sg_table - helper function to create sg table - * with specified chunk size - * @buffer_base: The starting address used for the sg dma address - * @chunk_size: The size of each entry in the sg table - * @total_size: The total size of the sg table (i.e. the sum of the - * entries). This will be rounded up to the nearest - * multiple of `chunk_size' - */ -struct sg_table *ion_create_chunked_sg_table(phys_addr_t buffer_base, - size_t chunk_size, - size_t total_size); - void show_ion_usage(struct ion_device *dev); #endif /* _MSM_ION_PRIV_H */ From df9553cc7264e335acf45686f9df5762d93f2b14 Mon Sep 17 00:00:00 2001 From: Sultan Alsawaf Date: Wed, 21 Aug 2019 21:49:35 -0700 Subject: [PATCH 541/592] iommu: msm: Rewrite to improve clarity and performance This scope of this driver's lock usage is extremely wide, leading to excessively long lock hold times. Additionally, an entire linked list is traversed for the sole purpose of trying to find a reason to invoke a BUG. These are the two most significant contributors to poor performance in this driver. Fix all of this by greatly reducing the scope of the locks used and by using atomic reader/writer locks. The superfluous linked list traversal is also gone, and the entire driver's code is refactored and improved for better cleanliness and performance. Note that ION must be modified to pass a known structure via the private dma_buf pointer, so that the iommu driver can prevent races when operating on the same buffer concurrently. This is the only way to eliminate said buffer races without hurting the iommu driver's performance. Signed-off-by: Sultan Alsawaf [kdrag0n: Forward-ported from k4.4 to k4.14] Signed-off-by: Danny Lin Signed-off-by: UtsavBalar1231 --- drivers/iommu/msm_dma_iommu_mapping.c | 568 +++++++------------------- drivers/staging/android/ion/ion.c | 42 +- drivers/staging/android/ion/ion.h | 2 + include/linux/msm_dma_iommu_mapping.h | 10 +- 4 files changed, 197 insertions(+), 425 deletions(-) diff --git a/drivers/iommu/msm_dma_iommu_mapping.c b/drivers/iommu/msm_dma_iommu_mapping.c index bc64c06d2be8..8ff0b8955340 100644 --- a/drivers/iommu/msm_dma_iommu_mapping.c +++ b/drivers/iommu/msm_dma_iommu_mapping.c @@ -1,481 +1,231 @@ -/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2015-2018, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 Sultan Alsawaf . */ -#include -#include +#include +#include +#include #include -#include -#include -#include #include -#include - -/** - * struct msm_iommu_map - represents a mapping of an ion buffer to an iommu - * @lnode - list node to exist in the buffer's list of iommu mappings - * @dev - Device this is mapped to. Used as key - * @sgl - The scatterlist for this mapping - * @nents - Number of entries in sgl - * @dir - The direction for the map. - * @meta - Backpointer to the meta this guy belongs to. - * @ref - for reference counting this mapping - * @attrs - dma mapping attributes - * @buf_start_addr - address of start of buffer - * - * Represents a mapping of one dma_buf buffer to a particular device - * and address range. There may exist other mappings of this buffer in - * different devices. All mappings will have the same cacheability and security. - */ -struct msm_iommu_map { - struct list_head lnode; - struct rb_node node; - struct device *dev; - struct scatterlist *sgl; - unsigned int nents; - enum dma_data_direction dir; - struct msm_iommu_meta *meta; - struct kref ref; - unsigned long attrs; - dma_addr_t buf_start_addr; -}; - struct msm_iommu_meta { - struct rb_node node; - struct list_head iommu_maps; - struct kref ref; - struct mutex lock; - void *buffer; + struct msm_iommu_data *data; + struct list_head lnode; + struct list_head map_list; + int refcount; }; -static struct rb_root iommu_root; -static DEFINE_MUTEX(msm_iommu_map_mutex); +struct msm_iommu_map { + struct device *dev; + struct list_head lnode; + struct scatterlist *sgl; + enum dma_data_direction dir; + unsigned int nents; + int refcount; + unsigned long attrs; +}; -static void msm_iommu_meta_add(struct msm_iommu_meta *meta) +static LIST_HEAD(meta_list); +static DEFINE_SPINLOCK(meta_list_lock); +static DECLARE_RWSEM(unmap_all_rwsem); + +static struct msm_iommu_map *msm_iommu_map_lookup(struct msm_iommu_meta *meta, + struct device *dev) { - struct rb_root *root = &iommu_root; - struct rb_node **p = &root->rb_node; - struct rb_node *parent = NULL; - struct msm_iommu_meta *entry; + struct msm_iommu_map *map; - while (*p) { - parent = *p; - entry = rb_entry(parent, struct msm_iommu_meta, node); - - if (meta->buffer < entry->buffer) - p = &(*p)->rb_left; - else if (meta->buffer > entry->buffer) - p = &(*p)->rb_right; - else - pr_err("%s: dma_buf %p already exists\n", __func__, - entry->buffer); - } - - rb_link_node(&meta->node, parent, p); - rb_insert_color(&meta->node, root); -} - -static struct msm_iommu_meta *msm_iommu_meta_lookup(void *buffer) -{ - struct rb_root *root = &iommu_root; - struct rb_node **p = &root->rb_node; - struct rb_node *parent = NULL; - struct msm_iommu_meta *entry = NULL; - - while (*p) { - parent = *p; - entry = rb_entry(parent, struct msm_iommu_meta, node); - - if (buffer < entry->buffer) - p = &(*p)->rb_left; - else if (buffer > entry->buffer) - p = &(*p)->rb_right; - else - return entry; + list_for_each_entry(map, &meta->map_list, lnode) { + if (map->dev == dev) + return map; } return NULL; } -static void msm_iommu_add(struct msm_iommu_meta *meta, - struct msm_iommu_map *iommu) +static void msm_iommu_map_free(struct msm_iommu_meta *meta, + struct msm_iommu_map *map) { - INIT_LIST_HEAD(&iommu->lnode); - list_add(&iommu->lnode, &meta->iommu_maps); -} + struct msm_iommu_data *data = meta->data; + struct sg_table table = { + .nents = map->nents, + .orig_nents = map->nents, + .sgl = map->sgl + }; + if (--meta->refcount) { + list_del(&map->lnode); + } else { + spin_lock(&meta_list_lock); + list_del(&meta->lnode); + spin_unlock(&meta_list_lock); -static struct msm_iommu_map *msm_iommu_lookup(struct msm_iommu_meta *meta, - struct device *dev) -{ - struct msm_iommu_map *entry; - - list_for_each_entry(entry, &meta->iommu_maps, lnode) { - if (entry->dev == dev) - return entry; + data->meta = NULL; + kfree(meta); } - return NULL; + /* Skip an additional cache maintenance on the dma unmap path */ + if (!(map->attrs & DMA_ATTR_SKIP_CPU_SYNC)) + map->attrs |= DMA_ATTR_SKIP_CPU_SYNC; + + dma_unmap_sg_attrs(map->dev, map->sgl, map->nents, map->dir, + map->attrs); + sg_free_table(&table); + kfree(map); } -static struct msm_iommu_meta *msm_iommu_meta_create(struct dma_buf *dma_buf) -{ - struct msm_iommu_meta *meta; - - meta = kzalloc(sizeof(*meta), GFP_KERNEL); - - if (!meta) - return ERR_PTR(-ENOMEM); - - INIT_LIST_HEAD(&meta->iommu_maps); - meta->buffer = dma_buf->priv; - kref_init(&meta->ref); - mutex_init(&meta->lock); - msm_iommu_meta_add(meta); - - return meta; -} - -static void msm_iommu_meta_put(struct msm_iommu_meta *meta); - static struct scatterlist *clone_sgl(struct scatterlist *sg, int nents) { struct scatterlist *next, *s; - int i; struct sg_table table; + int i; if (sg_alloc_table(&table, nents, GFP_KERNEL)) return NULL; + next = table.sgl; for_each_sg(sg, s, nents, i) { *next = *s; next = sg_next(next); } + return table.sgl; } -static inline int __msm_dma_map_sg(struct device *dev, struct scatterlist *sg, - int nents, enum dma_data_direction dir, - struct dma_buf *dma_buf, - unsigned long attrs) -{ - struct msm_iommu_map *iommu_map; - struct msm_iommu_meta *iommu_meta = NULL; - int ret = 0; - bool extra_meta_ref_taken = false; - int late_unmap = !(attrs & DMA_ATTR_NO_DELAYED_UNMAP); - - mutex_lock(&msm_iommu_map_mutex); - iommu_meta = msm_iommu_meta_lookup(dma_buf->priv); - - if (!iommu_meta) { - iommu_meta = msm_iommu_meta_create(dma_buf); - - if (IS_ERR(iommu_meta)) { - mutex_unlock(&msm_iommu_map_mutex); - ret = PTR_ERR(iommu_meta); - goto out; - } - if (late_unmap) { - kref_get(&iommu_meta->ref); - extra_meta_ref_taken = true; - } - } else { - kref_get(&iommu_meta->ref); - } - - mutex_unlock(&msm_iommu_map_mutex); - - mutex_lock(&iommu_meta->lock); - iommu_map = msm_iommu_lookup(iommu_meta, dev); - if (!iommu_map) { - iommu_map = kmalloc(sizeof(*iommu_map), GFP_KERNEL); - - if (!iommu_map) { - ret = -ENOMEM; - goto out_unlock; - } - - ret = dma_map_sg_attrs(dev, sg, nents, dir, attrs); - if (!ret) { - kfree(iommu_map); - goto out_unlock; - } - - iommu_map->sgl = clone_sgl(sg, nents); - if (!iommu_map->sgl) { - kfree(iommu_map); - ret = -ENOMEM; - goto out_unlock; - } - iommu_map->nents = nents; - iommu_map->dev = dev; - iommu_map->dir = dir; - iommu_map->attrs = attrs; - iommu_map->buf_start_addr = sg_phys(sg); - - kref_init(&iommu_map->ref); - if (late_unmap) - kref_get(&iommu_map->ref); - iommu_map->meta = iommu_meta; - msm_iommu_add(iommu_meta, iommu_map); - - } else { - if (nents == iommu_map->nents && - dir == iommu_map->dir && - (attrs & ~DMA_ATTR_SKIP_CPU_SYNC) == - (iommu_map->attrs & ~DMA_ATTR_SKIP_CPU_SYNC) && - sg_phys(sg) == iommu_map->buf_start_addr) { - struct scatterlist *sg_tmp = sg; - struct scatterlist *map_sg; - int i; - - for_each_sg(iommu_map->sgl, map_sg, nents, i) { - sg_dma_address(sg_tmp) = sg_dma_address(map_sg); - sg_dma_len(sg_tmp) = sg_dma_len(map_sg); - if (sg_dma_len(map_sg) == 0) - break; - - sg_tmp = sg_next(sg_tmp); - if (sg_tmp == NULL) - break; - } - - kref_get(&iommu_map->ref); - - if ((attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0) - dma_sync_sg_for_device(dev, iommu_map->sgl, - iommu_map->nents, iommu_map->dir); - - if (is_device_dma_coherent(dev)) - /* - * Ensure all outstanding changes for coherent - * buffers are applied to the cache before any - * DMA occurs. - */ - dmb(ish); - ret = nents; - } else { - bool start_diff = (sg_phys(sg) != - iommu_map->buf_start_addr); - - dev_err(dev, "lazy map request differs:\n" - "req dir:%d, original dir:%d\n" - "req nents:%d, original nents:%d\n" - "req map attrs:%lu, original map attrs:%lu\n" - "req buffer start address differs:%d\n", - dir, iommu_map->dir, nents, - iommu_map->nents, attrs, iommu_map->attrs, - start_diff); - ret = -EINVAL; - } - } - mutex_unlock(&iommu_meta->lock); - return ret; - -out_unlock: - mutex_unlock(&iommu_meta->lock); -out: - if (!IS_ERR(iommu_meta)) { - if (extra_meta_ref_taken) - msm_iommu_meta_put(iommu_meta); - msm_iommu_meta_put(iommu_meta); - } - return ret; - -} - -/* - * We are not taking a reference to the dma_buf here. It is expected that - * clients hold reference to the dma_buf until they are done with mapping and - * unmapping. - */ int msm_dma_map_sg_attrs(struct device *dev, struct scatterlist *sg, int nents, - enum dma_data_direction dir, struct dma_buf *dma_buf, - unsigned long attrs) + enum dma_data_direction dir, struct dma_buf *dma_buf, + unsigned long attrs) { + static const gfp_t gfp_flags_nofail = GFP_KERNEL | __GFP_NOFAIL; + int not_lazy = attrs & DMA_ATTR_NO_DELAYED_UNMAP; + struct msm_iommu_data *data = dma_buf->priv; + struct msm_iommu_meta *meta; + struct msm_iommu_map *map; int ret; - if (IS_ERR_OR_NULL(dev)) { - pr_err("%s: dev pointer is invalid\n", __func__); - return -EINVAL; + mutex_lock(&data->lock); + down_read(&unmap_all_rwsem); + meta = data->meta; + map = meta ? msm_iommu_map_lookup(meta, dev) : NULL; + if (map) { + struct scatterlist *sg_tmp = sg; + struct scatterlist *map_sg; + int i; + + map->refcount++; + + for_each_sg(map->sgl, map_sg, nents, i) { + sg_dma_address(sg_tmp) = sg_dma_address(map_sg); + sg_dma_len(sg_tmp) = sg_dma_len(map_sg); + if (sg_dma_len(map_sg) == 0) + break; + + sg_tmp = sg_next(sg_tmp); + if (sg_tmp == NULL) + break; + } + + if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC)) + dma_sync_sg_for_device(dev, map->sgl, map->nents, + map->dir); + + if (is_device_dma_coherent(dev)) + dmb(ish); + } else { + ret = dma_map_sg_attrs(dev, sg, nents, dir, attrs); + if (ret) { + map = kmalloc(sizeof(*map), gfp_flags_nofail); + map->dev = dev; + map->dir = dir; + map->nents = nents; + map->attrs = attrs; + map->refcount = 2 - not_lazy; + map->sgl = clone_sgl(sg, nents); + if (!map->sgl) { + kfree(map); + ret = -ENOMEM; + goto out_unlock; + } + + if (meta) { + meta->refcount++; + } else { + meta = kmalloc(sizeof(*meta), gfp_flags_nofail); + meta->data = data; + meta->refcount = 1; + INIT_LIST_HEAD(&meta->map_list); + data->meta = meta; + + spin_lock(&meta_list_lock); + list_add(&meta->lnode, &meta_list); + spin_unlock(&meta_list_lock); + } + list_add(&map->lnode, &meta->map_list); + } } + ret = nents; - if (IS_ERR_OR_NULL(sg)) { - pr_err("%s: sg table pointer is invalid\n", __func__); - return -EINVAL; - } - - if (IS_ERR_OR_NULL(dma_buf)) { - pr_err("%s: dma_buf pointer is invalid\n", __func__); - return -EINVAL; - } - - ret = __msm_dma_map_sg(dev, sg, nents, dir, dma_buf, attrs); - +out_unlock: + up_read(&unmap_all_rwsem); + mutex_unlock(&data->lock); return ret; } -EXPORT_SYMBOL(msm_dma_map_sg_attrs); - -static void msm_iommu_meta_destroy(struct kref *kref) -{ - struct msm_iommu_meta *meta = container_of(kref, struct msm_iommu_meta, - ref); - - if (!list_empty(&meta->iommu_maps)) { - WARN(1, "%s: DMA Buffer %p being destroyed with outstanding iommu mappins!\n", - __func__, meta->buffer); - } - rb_erase(&meta->node, &iommu_root); - kfree(meta); -} - -static void msm_iommu_meta_put(struct msm_iommu_meta *meta) -{ - /* - * Need to lock here to prevent race against map/unmap - */ - mutex_lock(&msm_iommu_map_mutex); - kref_put(&meta->ref, msm_iommu_meta_destroy); - mutex_unlock(&msm_iommu_map_mutex); -} - -static void msm_iommu_map_release(struct kref *kref) -{ - struct msm_iommu_map *map = container_of(kref, struct msm_iommu_map, - ref); - struct sg_table table; - - table.nents = table.orig_nents = map->nents; - table.sgl = map->sgl; - list_del(&map->lnode); - - /* Skip an additional cache maintenance on the dma unmap path */ - if (!(map->attrs & DMA_ATTR_SKIP_CPU_SYNC)) - map->attrs |= DMA_ATTR_SKIP_CPU_SYNC; - dma_unmap_sg_attrs(map->dev, map->sgl, map->nents, map->dir, - map->attrs); - sg_free_table(&table); - kfree(map); -} void msm_dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sgl, int nents, enum dma_data_direction dir, struct dma_buf *dma_buf, unsigned long attrs) { - struct msm_iommu_map *iommu_map; + struct msm_iommu_data *data = dma_buf->priv; struct msm_iommu_meta *meta; + struct msm_iommu_map *map; - mutex_lock(&msm_iommu_map_mutex); - meta = msm_iommu_meta_lookup(dma_buf->priv); - if (!meta) { - WARN(1, "%s: (%p) was never mapped\n", __func__, dma_buf); - mutex_unlock(&msm_iommu_map_mutex); - goto out; + if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC)) + dma_sync_sg_for_cpu(dev, map->sgl, map->nents, dir); + mutex_lock(&data->lock); + down_read(&unmap_all_rwsem); + meta = data->meta; + if (meta) { + map = msm_iommu_map_lookup(meta, dev); + if (map && !--map->refcount) + msm_iommu_map_free(meta, map); } - mutex_unlock(&msm_iommu_map_mutex); - - mutex_lock(&meta->lock); - iommu_map = msm_iommu_lookup(meta, dev); - - if (!iommu_map) { - WARN(1, "%s: (%p) was never mapped for device %p\n", __func__, - dma_buf, dev); - mutex_unlock(&meta->lock); - goto out; - } - - if (dir != iommu_map->dir) - WARN(1, "%s: (%pK) dir:%d differs from original dir:%d\n", - __func__, dma_buf, dir, iommu_map->dir); - - if (attrs && ((attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0)) - dma_sync_sg_for_cpu(dev, iommu_map->sgl, iommu_map->nents, dir); - - iommu_map->attrs = attrs; - kref_put(&iommu_map->ref, msm_iommu_map_release); - mutex_unlock(&meta->lock); - - msm_iommu_meta_put(meta); - -out: - return; + up_read(&unmap_all_rwsem); + mutex_unlock(&data->lock); } -EXPORT_SYMBOL(msm_dma_unmap_sg_attrs); int msm_dma_unmap_all_for_dev(struct device *dev) { - int ret = 0; - struct msm_iommu_meta *meta; - struct rb_root *root; - struct rb_node *meta_node; + struct msm_iommu_meta *meta, *tmp_meta; + struct msm_iommu_map *map; - mutex_lock(&msm_iommu_map_mutex); - root = &iommu_root; - meta_node = rb_first(root); - while (meta_node) { - struct msm_iommu_map *iommu_map; - struct msm_iommu_map *iommu_map_next; - - meta = rb_entry(meta_node, struct msm_iommu_meta, node); - mutex_lock(&meta->lock); - list_for_each_entry_safe(iommu_map, iommu_map_next, - &meta->iommu_maps, lnode) - if (iommu_map->dev == dev) - if (!kref_put(&iommu_map->ref, - msm_iommu_map_release)) - ret = -EINVAL; - - mutex_unlock(&meta->lock); - meta_node = rb_next(meta_node); + down_write(&unmap_all_rwsem); + list_for_each_entry_safe(meta, tmp_meta, &meta_list, lnode) { + map = msm_iommu_map_lookup(meta, dev); + if (map) + msm_iommu_map_free(meta, map); } - mutex_unlock(&msm_iommu_map_mutex); + up_write(&unmap_all_rwsem); - return ret; + return 0; } /* * Only to be called by ION code when a buffer is freed */ -void msm_dma_buf_freed(void *buffer) +void msm_dma_buf_freed(struct msm_iommu_data *data) { - struct msm_iommu_map *iommu_map; - struct msm_iommu_map *iommu_map_next; + struct msm_iommu_map *map, *tmp_map; struct msm_iommu_meta *meta; - mutex_lock(&msm_iommu_map_mutex); - meta = msm_iommu_meta_lookup(buffer); - if (!meta) { - /* Already unmapped (assuming no late unmapping) */ - mutex_unlock(&msm_iommu_map_mutex); - return; + mutex_lock(&data->lock); + down_read(&unmap_all_rwsem); + meta = data->meta; + if (meta) { + list_for_each_entry_safe(map, tmp_map, &meta->map_list, lnode) + msm_iommu_map_free(meta, map); } - mutex_unlock(&msm_iommu_map_mutex); - - mutex_lock(&meta->lock); - - list_for_each_entry_safe(iommu_map, iommu_map_next, &meta->iommu_maps, - lnode) - kref_put(&iommu_map->ref, msm_iommu_map_release); - - if (!list_empty(&meta->iommu_maps)) { - WARN(1, "%s: DMA buffer %p destroyed with outstanding iommu mappings\n", - __func__, meta->buffer); - } - - INIT_LIST_HEAD(&meta->iommu_maps); - mutex_unlock(&meta->lock); - - msm_iommu_meta_put(meta); + up_read(&unmap_all_rwsem); + mutex_unlock(&data->lock); } diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 5d0aafa787ef..7d72de29d7a3 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -60,7 +60,10 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, .vmas = LIST_HEAD_INIT(buffer->vmas), .attachment_lock = __MUTEX_INITIALIZER(buffer->attachment_lock), .kmap_lock = __MUTEX_INITIALIZER(buffer->kmap_lock), - .vma_lock = __MUTEX_INITIALIZER(buffer->vma_lock) + .vma_lock = __MUTEX_INITIALIZER(buffer->vma_lock), + .iommu_data = { + .lock = __MUTEX_INITIALIZER(buffer->iommu_data.lock) + } }; ret = heap->ops->allocate(heap, buffer, len, flags); @@ -100,7 +103,7 @@ static void _ion_buffer_destroy(struct ion_buffer *buffer) { struct ion_heap *heap = buffer->heap; - msm_dma_buf_freed(buffer); + msm_dma_buf_freed(&buffer->iommu_data); if (heap->flags & ION_HEAP_FLAG_DEFER_FREE) ion_heap_freelist_add(heap, buffer); @@ -187,9 +190,10 @@ struct ion_dma_buf_attachment { static int ion_dma_buf_attach(struct dma_buf *dmabuf, struct device *dev, struct dma_buf_attachment *attachment) { + struct ion_buffer *buffer = container_of(dmabuf->priv, typeof(*buffer), + iommu_data); struct ion_dma_buf_attachment *a; struct sg_table *table; - struct ion_buffer *buffer = dmabuf->priv; a = kzalloc(sizeof(*a), GFP_KERNEL); if (!a) @@ -220,8 +224,9 @@ static int ion_dma_buf_attach(struct dma_buf *dmabuf, struct device *dev, static void ion_dma_buf_detach(struct dma_buf *dmabuf, struct dma_buf_attachment *attachment) { + struct ion_buffer *buffer = container_of(dmabuf->priv, typeof(*buffer), + iommu_data); struct ion_dma_buf_attachment *a = attachment->priv; - struct ion_buffer *buffer = dmabuf->priv; if (buffer->flags & ION_FLAG_CACHED) { mutex_lock(&buffer->attachment_lock); @@ -341,7 +346,8 @@ static const struct vm_operations_struct ion_vma_ops = { static int ion_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) { - struct ion_buffer *buffer = dmabuf->priv; + struct ion_buffer *buffer = container_of(dmabuf->priv, typeof(*buffer), + iommu_data); if (!buffer->heap->ops->map_user) return -EINVAL; @@ -358,14 +364,16 @@ static int ion_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) static void ion_dma_buf_release(struct dma_buf *dmabuf) { - struct ion_buffer *buffer = dmabuf->priv; + struct ion_buffer *buffer = container_of(dmabuf->priv, typeof(*buffer), + iommu_data); _ion_buffer_destroy(buffer); } static void *ion_dma_buf_vmap(struct dma_buf *dmabuf) { - struct ion_buffer *buffer = dmabuf->priv; + struct ion_buffer *buffer = container_of(dmabuf->priv, typeof(*buffer), + iommu_data); if (!buffer->heap->ops->map_kernel) return ERR_PTR(-EINVAL); @@ -375,7 +383,8 @@ static void *ion_dma_buf_vmap(struct dma_buf *dmabuf) static void ion_dma_buf_vunmap(struct dma_buf *dmabuf, void *vaddr) { - struct ion_buffer *buffer = dmabuf->priv; + struct ion_buffer *buffer = container_of(dmabuf->priv, typeof(*buffer), + iommu_data); ion_buffer_kmap_put(buffer); } @@ -487,7 +496,8 @@ static int __ion_dma_buf_begin_cpu_access(struct dma_buf *dmabuf, enum dma_data_direction direction, bool sync_only_mapped) { - struct ion_buffer *buffer = dmabuf->priv; + struct ion_buffer *buffer = container_of(dmabuf->priv, typeof(*buffer), + iommu_data); struct ion_dma_buf_attachment *a; int ret = 0; @@ -525,7 +535,8 @@ static int __ion_dma_buf_end_cpu_access(struct dma_buf *dmabuf, enum dma_data_direction direction, bool sync_only_mapped) { - struct ion_buffer *buffer = dmabuf->priv; + struct ion_buffer *buffer = container_of(dmabuf->priv, typeof(*buffer), + iommu_data); struct ion_dma_buf_attachment *a; int ret = 0; @@ -588,7 +599,8 @@ static int ion_dma_buf_begin_cpu_access_partial(struct dma_buf *dmabuf, unsigned int offset, unsigned int len) { - struct ion_buffer *buffer = dmabuf->priv; + struct ion_buffer *buffer = container_of(dmabuf->priv, typeof(*buffer), + iommu_data); struct ion_dma_buf_attachment *a; int ret = 0; @@ -621,7 +633,8 @@ static int ion_dma_buf_end_cpu_access_partial(struct dma_buf *dmabuf, unsigned int offset, unsigned int len) { - struct ion_buffer *buffer = dmabuf->priv; + struct ion_buffer *buffer = container_of(dmabuf->priv, typeof(*buffer), + iommu_data); struct ion_dma_buf_attachment *a; int ret = 0; @@ -652,7 +665,8 @@ static int ion_dma_buf_end_cpu_access_partial(struct dma_buf *dmabuf, static int ion_dma_buf_get_flags(struct dma_buf *dmabuf, unsigned long *flags) { - struct ion_buffer *buffer = dmabuf->priv; + struct ion_buffer *buffer = container_of(dmabuf->priv, typeof(*buffer), + iommu_data); *flags = buffer->flags; return 0; @@ -711,7 +725,7 @@ struct dma_buf *ion_alloc(size_t len, unsigned int heap_id_mask, .ops = &dma_buf_ops, .flags = O_RDWR, .size = buffer->size, - .priv = buffer + .priv = &buffer->iommu_data }; dmabuf = dma_buf_export(&exp_info); diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index cdd02b5a0f0d..a2cc1e548263 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -121,6 +122,7 @@ struct ion_buffer { struct sg_table *sg_table; struct list_head attachments; struct list_head vmas; + struct msm_iommu_data iommu_data; }; void ion_buffer_destroy(struct ion_buffer *buffer); diff --git a/include/linux/msm_dma_iommu_mapping.h b/include/linux/msm_dma_iommu_mapping.h index ae20f0990a98..32052cc8ed01 100644 --- a/include/linux/msm_dma_iommu_mapping.h +++ b/include/linux/msm_dma_iommu_mapping.h @@ -18,6 +18,12 @@ #include #include +struct msm_iommu_meta; +struct msm_iommu_data { + struct msm_iommu_meta *meta; + struct mutex lock; +}; + #ifdef CONFIG_QCOM_LAZY_MAPPING /* * This function is not taking a reference to the dma_buf here. It is expected @@ -71,7 +77,7 @@ int msm_dma_unmap_all_for_dev(struct device *dev); * Below is private function only to be called by framework (ION) and not by * clients. */ -void msm_dma_buf_freed(void *buffer); +void msm_dma_buf_freed(struct msm_iommu_data *data); #else /*CONFIG_QCOM_LAZY_MAPPING*/ @@ -117,7 +123,7 @@ static inline int msm_dma_unmap_all_for_dev(struct device *dev) return 0; } -static inline void msm_dma_buf_freed(void *buffer) {} +static inline void msm_dma_buf_freed(struct msm_iommu_data *data) {} #endif /*CONFIG_QCOM_LAZY_MAPPING*/ #endif From 9e7c6d88c87a66d32b716f79a05facde259cb5bd Mon Sep 17 00:00:00 2001 From: Sultan Alsawaf Date: Sun, 25 Aug 2019 22:20:24 -0700 Subject: [PATCH 542/592] iommu: msm: Fix issues in the 4.14 port Signed-off-by: Sultan Alsawaf Signed-off-by: Danny Lin Signed-off-by: UtsavBalar1231 --- drivers/iommu/msm_dma_iommu_mapping.c | 45 ++++++++++----------------- 1 file changed, 17 insertions(+), 28 deletions(-) diff --git a/drivers/iommu/msm_dma_iommu_mapping.c b/drivers/iommu/msm_dma_iommu_mapping.c index 8ff0b8955340..3ce62c6c905c 100644 --- a/drivers/iommu/msm_dma_iommu_mapping.c +++ b/drivers/iommu/msm_dma_iommu_mapping.c @@ -22,9 +22,9 @@ struct msm_iommu_map { struct list_head lnode; struct scatterlist *sgl; enum dma_data_direction dir; - unsigned int nents; - int refcount; unsigned long attrs; + int nents; + int refcount; }; static LIST_HEAD(meta_list); @@ -66,9 +66,7 @@ static void msm_iommu_map_free(struct msm_iommu_meta *meta, } /* Skip an additional cache maintenance on the dma unmap path */ - if (!(map->attrs & DMA_ATTR_SKIP_CPU_SYNC)) - map->attrs |= DMA_ATTR_SKIP_CPU_SYNC; - + map->attrs |= DMA_ATTR_SKIP_CPU_SYNC; dma_unmap_sg_attrs(map->dev, map->sgl, map->nents, map->dir, map->attrs); sg_free_table(&table); @@ -81,9 +79,7 @@ static struct scatterlist *clone_sgl(struct scatterlist *sg, int nents) struct sg_table table; int i; - if (sg_alloc_table(&table, nents, GFP_KERNEL)) - return NULL; - + sg_alloc_table(&table, nents, GFP_KERNEL | __GFP_NOFAIL); next = table.sgl; for_each_sg(sg, s, nents, i) { *next = *s; @@ -118,11 +114,11 @@ int msm_dma_map_sg_attrs(struct device *dev, struct scatterlist *sg, int nents, for_each_sg(map->sgl, map_sg, nents, i) { sg_dma_address(sg_tmp) = sg_dma_address(map_sg); sg_dma_len(sg_tmp) = sg_dma_len(map_sg); - if (sg_dma_len(map_sg) == 0) + if (!sg_dma_len(map_sg)) break; sg_tmp = sg_next(sg_tmp); - if (sg_tmp == NULL) + if (!sg_tmp) break; } @@ -142,11 +138,6 @@ int msm_dma_map_sg_attrs(struct device *dev, struct scatterlist *sg, int nents, map->attrs = attrs; map->refcount = 2 - not_lazy; map->sgl = clone_sgl(sg, nents); - if (!map->sgl) { - kfree(map); - ret = -ENOMEM; - goto out_unlock; - } if (meta) { meta->refcount++; @@ -164,15 +155,13 @@ int msm_dma_map_sg_attrs(struct device *dev, struct scatterlist *sg, int nents, list_add(&map->lnode, &meta->map_list); } } - ret = nents; - -out_unlock: up_read(&unmap_all_rwsem); mutex_unlock(&data->lock); - return ret; + + return nents; } -void msm_dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sgl, +void msm_dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sg, int nents, enum dma_data_direction dir, struct dma_buf *dma_buf, unsigned long attrs) { @@ -180,16 +169,19 @@ void msm_dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sgl, struct msm_iommu_meta *meta; struct msm_iommu_map *map; - if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC)) - dma_sync_sg_for_cpu(dev, map->sgl, map->nents, dir); - mutex_lock(&data->lock); down_read(&unmap_all_rwsem); meta = data->meta; if (meta) { map = msm_iommu_map_lookup(meta, dev); - if (map && !--map->refcount) - msm_iommu_map_free(meta, map); + if (map) { + if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC)) + dma_sync_sg_for_cpu(dev, map->sgl, map->nents, + dir); + + if (!--map->refcount) + msm_iommu_map_free(meta, map); + } } up_read(&unmap_all_rwsem); mutex_unlock(&data->lock); @@ -211,9 +203,6 @@ int msm_dma_unmap_all_for_dev(struct device *dev) return 0; } -/* - * Only to be called by ION code when a buffer is freed - */ void msm_dma_buf_freed(struct msm_iommu_data *data) { struct msm_iommu_map *map, *tmp_map; From 39a5cfc32afb564de6eb258fe33c53feb4edf626 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Fri, 14 Aug 2020 17:30:10 -0700 Subject: [PATCH 543/592] BACKPORT: lz4: fix kernel decompression speed This patch replaces all memcpy() calls with LZ4_memcpy() which calls __builtin_memcpy() so the compiler can inline it. LZ4 relies heavily on memcpy() with a constant size being inlined. In x86 and i386 pre-boot environments memcpy() cannot be inlined because memcpy() doesn't get defined as __builtin_memcpy(). An equivalent patch has been applied upstream so that the next import won't lose this change [1]. I've measured the kernel decompression speed using QEMU before and after this patch for the x86_64 and i386 architectures. The speed-up is about 10x as shown below. Code Arch Kernel Size Time Speed v5.8 x86_64 11504832 B 148 ms 79 MB/s patch x86_64 11503872 B 13 ms 885 MB/s v5.8 i386 9621216 B 91 ms 106 MB/s patch i386 9620224 B 10 ms 962 MB/s I also measured the time to decompress the initramfs on x86_64, i386, and arm. All three show the same decompression speed before and after, as expected. [1] https://github.com/lz4/lz4/pull/890 Signed-off-by: Nick Terrell Signed-off-by: Andrew Morton Cc: Yann Collet Cc: Gao Xiang Cc: Sven Schmidt <4sschmid@informatik.uni-hamburg.de> Cc: Greg Kroah-Hartman Cc: Ingo Molnar Cc: Arvind Sankar Link: http://lkml.kernel.org/r/20200803194022.2966806-1-nickrterrell@gmail.com Signed-off-by: Linus Torvalds Signed-off-by: UtsavBalar1231 --- lib/lz4/lz4_compress.c | 2 +- lib/lz4/lz4_decompress.c | 14 +++++++------- lib/lz4/lz4defs.h | 10 ++++++++++ lib/lz4/lz4hc_compress.c | 2 +- 4 files changed, 19 insertions(+), 9 deletions(-) diff --git a/lib/lz4/lz4_compress.c b/lib/lz4/lz4_compress.c index 187ecdfae375..aa09d3cae270 100644 --- a/lib/lz4/lz4_compress.c +++ b/lib/lz4/lz4_compress.c @@ -395,7 +395,7 @@ _last_literals: *op++ = (BYTE)(lastRun << ML_BITS); } - memcpy(op, anchor, lastRun); + LZ4_memcpy(op, anchor, lastRun); op += lastRun; } diff --git a/lib/lz4/lz4_decompress.c b/lib/lz4/lz4_decompress.c index 0aa27c80a9f2..72869743fca4 100644 --- a/lib/lz4/lz4_decompress.c +++ b/lib/lz4/lz4_decompress.c @@ -149,7 +149,7 @@ static FORCE_INLINE int LZ4_decompress_generic( && likely((endOnInput ? ip < shortiend : 1) & (op <= shortoend))) { /* Copy the literals */ - memcpy(op, ip, endOnInput ? 16 : 8); + LZ4_memcpy(op, ip, endOnInput ? 16 : 8); op += length; ip += length; /* @@ -168,9 +168,9 @@ static FORCE_INLINE int LZ4_decompress_generic( (offset >= 8) && (dict == withPrefix64k || match >= lowPrefix)) { /* Copy the match. */ - memcpy(op + 0, match + 0, 8); - memcpy(op + 8, match + 8, 8); - memcpy(op + 16, match + 16, 2); + LZ4_memcpy(op + 0, match + 0, 8); + LZ4_memcpy(op + 8, match + 8, 8); + LZ4_memcpy(op + 16, match + 16, 2); op += length + MINMATCH; /* Both stages worked, load the next token. */ continue; @@ -259,7 +259,7 @@ static FORCE_INLINE int LZ4_decompress_generic( } } - memcpy(op, ip, length); + LZ4_memcpy(op, ip, length); ip += length; op += length; @@ -340,7 +340,7 @@ _copy_match: while (op < copyEnd) *op++ = *match++; } else { - memcpy(op, match, mlen); + LZ4_memcpy(op, match, mlen); } op = copyEnd; if (op == oend) @@ -354,7 +354,7 @@ _copy_match: op[2] = match[2]; op[3] = match[3]; match += inc32table[offset]; - memcpy(op + 4, match, 4); + LZ4_memcpy(op + 4, match, 4); match -= dec64table[offset]; } else { LZ4_copy8(op, match); diff --git a/lib/lz4/lz4defs.h b/lib/lz4/lz4defs.h index bfb9ba5181a8..49e637d7bdbe 100644 --- a/lib/lz4/lz4defs.h +++ b/lib/lz4/lz4defs.h @@ -137,6 +137,16 @@ static FORCE_INLINE void LZ4_writeLE16(void *memPtr, U16 value) return put_unaligned_le16(value, memPtr); } +/* + * LZ4 relies on memcpy with a constant size being inlined. In freestanding + * environments, the compiler can't assume the implementation of memcpy() is + * standard compliant, so apply its specialized memcpy() inlining logic. When + * possible, use __builtin_memcpy() to tell the compiler to analyze memcpy() + * as-if it were standard compliant, so it can inline it in freestanding + * environments. This is needed when decompressing the Linux Kernel, for example. + */ +#define LZ4_memcpy(dst, src, size) __builtin_memcpy(dst, src, size) + static FORCE_INLINE void LZ4_copy8(void *dst, const void *src) { #if LZ4_ARCH64 diff --git a/lib/lz4/lz4hc_compress.c b/lib/lz4/lz4hc_compress.c index a67c8e5f765f..be8bfa09a74a 100644 --- a/lib/lz4/lz4hc_compress.c +++ b/lib/lz4/lz4hc_compress.c @@ -570,7 +570,7 @@ _Search3: *op++ = (BYTE) lastRun; } else *op++ = (BYTE)(lastRun< Date: Thu, 4 Jun 2020 16:50:11 -0700 Subject: [PATCH 544/592] lib: Add might_fault() to strncpy_from_user. When updating a piece of broken logic from using get_user to strncpy_from_user, we noticed that a warning which is expected when calling a function that might fault from an atomic context with pagefaults enabled disappeared. Not having this warning in place can lead to calling strncpy_from_user from an atomic context and eventually kernel crashes/stack corruption. Signed-off-by: KP Singh Signed-off-by: Andrew Morton Reviewed-by: Andrew Morton Cc: Jann Horn Cc: Christophe Leroy Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20200414225705.255711-1-kpsingh@chromium.org Signed-off-by: Linus Torvalds Signed-off-by: UtsavBalar1231 --- lib/strncpy_from_user.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/strncpy_from_user.c b/lib/strncpy_from_user.c index 56a5981ba968..0dae80047372 100644 --- a/lib/strncpy_from_user.c +++ b/lib/strncpy_from_user.c @@ -98,6 +98,7 @@ long strncpy_from_user(char *dst, const char __user *src, long count) { unsigned long max_addr, src_addr; + might_fault(); if (unlikely(count <= 0)) return 0; From 9a594f80deeabb25c96cd620b461d18cac8dbb88 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Thu, 30 Jul 2020 12:08:34 -0700 Subject: [PATCH 545/592] lib: Prepare zstd for preboot environment, improve performance These changes are necessary to get the build to work in the preboot environment, and to get reasonable performance: - Remove a double definition of the CHECK_F macro when the zstd library is amalgamated. - Switch ZSTD_copy8() to __builtin_memcpy(), because in the preboot environment on x86 gcc can't inline `memcpy()` otherwise. - Limit the gcc hack in ZSTD_wildcopy() to the broken gcc version. See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81388. ZSTD_copy8() and ZSTD_wildcopy() are in the core of the zstd hot loop. So outlining these calls to memcpy(), and having an extra branch are very detrimental to performance. Signed-off-by: Nick Terrell Signed-off-by: Ingo Molnar Tested-by: Sedat Dilek Reviewed-by: Kees Cook Link: https://lore.kernel.org/r/20200730190841.2071656-2-nickrterrell@gmail.com Signed-off-by: UtsavBalar1231 --- lib/zstd/fse_decompress.c | 9 +-------- lib/zstd/zstd_internal.h | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/lib/zstd/fse_decompress.c b/lib/zstd/fse_decompress.c index a84300e5a013..0b353530fb3f 100644 --- a/lib/zstd/fse_decompress.c +++ b/lib/zstd/fse_decompress.c @@ -47,6 +47,7 @@ ****************************************************************/ #include "bitstream.h" #include "fse.h" +#include "zstd_internal.h" #include #include #include /* memcpy, memset */ @@ -60,14 +61,6 @@ enum { FSE_static_assert = 1 / (int)(!!(c)) }; \ } /* use only *after* variable declarations */ -/* check and forward error code */ -#define CHECK_F(f) \ - { \ - size_t const e = f; \ - if (FSE_isError(e)) \ - return e; \ - } - /* ************************************************************** * Templates ****************************************************************/ diff --git a/lib/zstd/zstd_internal.h b/lib/zstd/zstd_internal.h index 1a79fab9e13a..dac753397f86 100644 --- a/lib/zstd/zstd_internal.h +++ b/lib/zstd/zstd_internal.h @@ -127,7 +127,14 @@ static const U32 OF_defaultNormLog = OF_DEFAULTNORMLOG; * Shared functions to include for inlining *********************************************/ ZSTD_STATIC void ZSTD_copy8(void *dst, const void *src) { - memcpy(dst, src, 8); + /* + * zstd relies heavily on gcc being able to analyze and inline this + * memcpy() call, since it is called in a tight loop. Preboot mode + * is compiled in freestanding mode, which stops gcc from analyzing + * memcpy(). Use __builtin_memcpy() to tell gcc to analyze this as a + * regular memcpy(). + */ + __builtin_memcpy(dst, src, 8); } /*! ZSTD_wildcopy() : * custom version of memcpy(), can copy up to 7 bytes too many (8 bytes if length==0) */ @@ -137,13 +144,16 @@ ZSTD_STATIC void ZSTD_wildcopy(void *dst, const void *src, ptrdiff_t length) const BYTE* ip = (const BYTE*)src; BYTE* op = (BYTE*)dst; BYTE* const oend = op + length; - /* Work around https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81388. +#if defined(GCC_VERSION) && GCC_VERSION >= 70000 && GCC_VERSION < 70200 + /* + * Work around https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81388. * Avoid the bad case where the loop only runs once by handling the * special case separately. This doesn't trigger the bug because it * doesn't involve pointer/integer overflow. */ if (length <= 8) return ZSTD_copy8(dst, src); +#endif do { ZSTD_copy8(op, ip); op += 8; From b8a3b8a477ec162bcce8489fe9d7e5fd5d051ddb Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Thu, 30 Jul 2020 12:08:35 -0700 Subject: [PATCH 546/592] lib: Add zstd support to decompress - Add unzstd() and the zstd decompress interface. - Add zstd support to decompress_method(). The decompress_method() and unzstd() functions are used to decompress the initramfs and the initrd. The __decompress() function is used in the preboot environment to decompress a zstd compressed kernel. The zstd decompression function allows the input and output buffers to overlap because that is used by x86 kernel decompression. Signed-off-by: Nick Terrell Signed-off-by: Ingo Molnar Tested-by: Sedat Dilek Reviewed-by: Kees Cook Link: https://lore.kernel.org/r/20200730190841.2071656-3-nickrterrell@gmail.com Signed-off-by: UtsavBalar1231 --- include/linux/decompress/unzstd.h | 11 + lib/Kconfig | 4 + lib/Makefile | 1 + lib/decompress.c | 5 + lib/decompress_unzstd.c | 345 ++++++++++++++++++++++++++++++ 5 files changed, 366 insertions(+) create mode 100644 include/linux/decompress/unzstd.h create mode 100644 lib/decompress_unzstd.c diff --git a/include/linux/decompress/unzstd.h b/include/linux/decompress/unzstd.h new file mode 100644 index 000000000000..56d539ae880f --- /dev/null +++ b/include/linux/decompress/unzstd.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef LINUX_DECOMPRESS_UNZSTD_H +#define LINUX_DECOMPRESS_UNZSTD_H + +int unzstd(unsigned char *inbuf, long len, + long (*fill)(void*, unsigned long), + long (*flush)(void*, unsigned long), + unsigned char *output, + long *pos, + void (*error_fn)(char *x)); +#endif diff --git a/lib/Kconfig b/lib/Kconfig index eec1142136dc..4c3d414495ef 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -285,6 +285,10 @@ config DECOMPRESS_LZ4 select LZ4_DECOMPRESS tristate +config DECOMPRESS_ZSTD + select ZSTD_DECOMPRESS + tristate + # # Generic allocator support is selected if needed # diff --git a/lib/Makefile b/lib/Makefile index 4cfeba73334b..6ae07fbc71f6 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -148,6 +148,7 @@ lib-$(CONFIG_DECOMPRESS_LZMA) += decompress_unlzma.o lib-$(CONFIG_DECOMPRESS_XZ) += decompress_unxz.o lib-$(CONFIG_DECOMPRESS_LZO) += decompress_unlzo.o lib-$(CONFIG_DECOMPRESS_LZ4) += decompress_unlz4.o +lib-$(CONFIG_DECOMPRESS_ZSTD) += decompress_unzstd.o obj-$(CONFIG_TEXTSEARCH) += textsearch.o obj-$(CONFIG_TEXTSEARCH_KMP) += ts_kmp.o diff --git a/lib/decompress.c b/lib/decompress.c index 857ab1af1ef3..ab3fc90ffc64 100644 --- a/lib/decompress.c +++ b/lib/decompress.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -37,6 +38,9 @@ #ifndef CONFIG_DECOMPRESS_LZ4 # define unlz4 NULL #endif +#ifndef CONFIG_DECOMPRESS_ZSTD +# define unzstd NULL +#endif struct compress_format { unsigned char magic[2]; @@ -52,6 +56,7 @@ static const struct compress_format compressed_formats[] __initconst = { { {0xfd, 0x37}, "xz", unxz }, { {0x89, 0x4c}, "lzo", unlzo }, { {0x02, 0x21}, "lz4", unlz4 }, + { {0x28, 0xb5}, "zstd", unzstd }, { {0, 0}, NULL, NULL } }; diff --git a/lib/decompress_unzstd.c b/lib/decompress_unzstd.c new file mode 100644 index 000000000000..0ad2c15479ed --- /dev/null +++ b/lib/decompress_unzstd.c @@ -0,0 +1,345 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * Important notes about in-place decompression + * + * At least on x86, the kernel is decompressed in place: the compressed data + * is placed to the end of the output buffer, and the decompressor overwrites + * most of the compressed data. There must be enough safety margin to + * guarantee that the write position is always behind the read position. + * + * The safety margin for ZSTD with a 128 KB block size is calculated below. + * Note that the margin with ZSTD is bigger than with GZIP or XZ! + * + * The worst case for in-place decompression is that the beginning of + * the file is compressed extremely well, and the rest of the file is + * uncompressible. Thus, we must look for worst-case expansion when the + * compressor is encoding uncompressible data. + * + * The structure of the .zst file in case of a compresed kernel is as follows. + * Maximum sizes (as bytes) of the fields are in parenthesis. + * + * Frame Header: (18) + * Blocks: (N) + * Checksum: (4) + * + * The frame header and checksum overhead is at most 22 bytes. + * + * ZSTD stores the data in blocks. Each block has a header whose size is + * a 3 bytes. After the block header, there is up to 128 KB of payload. + * The maximum uncompressed size of the payload is 128 KB. The minimum + * uncompressed size of the payload is never less than the payload size + * (excluding the block header). + * + * The assumption, that the uncompressed size of the payload is never + * smaller than the payload itself, is valid only when talking about + * the payload as a whole. It is possible that the payload has parts where + * the decompressor consumes more input than it produces output. Calculating + * the worst case for this would be tricky. Instead of trying to do that, + * let's simply make sure that the decompressor never overwrites any bytes + * of the payload which it is currently reading. + * + * Now we have enough information to calculate the safety margin. We need + * - 22 bytes for the .zst file format headers; + * - 3 bytes per every 128 KiB of uncompressed size (one block header per + * block); and + * - 128 KiB (biggest possible zstd block size) to make sure that the + * decompressor never overwrites anything from the block it is currently + * reading. + * + * We get the following formula: + * + * safety_margin = 22 + uncompressed_size * 3 / 131072 + 131072 + * <= 22 + (uncompressed_size >> 15) + 131072 + */ + +/* + * Preboot environments #include "path/to/decompress_unzstd.c". + * All of the source files we depend on must be #included. + * zstd's only source dependeny is xxhash, which has no source + * dependencies. + * + * When UNZSTD_PREBOOT is defined we declare __decompress(), which is + * used for kernel decompression, instead of unzstd(). + * + * Define __DISABLE_EXPORTS in preboot environments to prevent symbols + * from xxhash and zstd from being exported by the EXPORT_SYMBOL macro. + */ +#ifdef STATIC +# define UNZSTD_PREBOOT +# include "xxhash.c" +# include "zstd/entropy_common.c" +# include "zstd/fse_decompress.c" +# include "zstd/huf_decompress.c" +# include "zstd/zstd_common.c" +# include "zstd/decompress.c" +#endif + +#include +#include +#include + +/* 128MB is the maximum window size supported by zstd. */ +#define ZSTD_WINDOWSIZE_MAX (1 << ZSTD_WINDOWLOG_MAX) +/* + * Size of the input and output buffers in multi-call mode. + * Pick a larger size because it isn't used during kernel decompression, + * since that is single pass, and we have to allocate a large buffer for + * zstd's window anyway. The larger size speeds up initramfs decompression. + */ +#define ZSTD_IOBUF_SIZE (1 << 17) + +static int INIT handle_zstd_error(size_t ret, void (*error)(char *x)) +{ + const int err = ZSTD_getErrorCode(ret); + + if (!ZSTD_isError(ret)) + return 0; + + switch (err) { + case ZSTD_error_memory_allocation: + error("ZSTD decompressor ran out of memory"); + break; + case ZSTD_error_prefix_unknown: + error("Input is not in the ZSTD format (wrong magic bytes)"); + break; + case ZSTD_error_dstSize_tooSmall: + case ZSTD_error_corruption_detected: + case ZSTD_error_checksum_wrong: + error("ZSTD-compressed data is corrupt"); + break; + default: + error("ZSTD-compressed data is probably corrupt"); + break; + } + return -1; +} + +/* + * Handle the case where we have the entire input and output in one segment. + * We can allocate less memory (no circular buffer for the sliding window), + * and avoid some memcpy() calls. + */ +static int INIT decompress_single(const u8 *in_buf, long in_len, u8 *out_buf, + long out_len, long *in_pos, + void (*error)(char *x)) +{ + const size_t wksp_size = ZSTD_DCtxWorkspaceBound(); + void *wksp = large_malloc(wksp_size); + ZSTD_DCtx *dctx = ZSTD_initDCtx(wksp, wksp_size); + int err; + size_t ret; + + if (dctx == NULL) { + error("Out of memory while allocating ZSTD_DCtx"); + err = -1; + goto out; + } + /* + * Find out how large the frame actually is, there may be junk at + * the end of the frame that ZSTD_decompressDCtx() can't handle. + */ + ret = ZSTD_findFrameCompressedSize(in_buf, in_len); + err = handle_zstd_error(ret, error); + if (err) + goto out; + in_len = (long)ret; + + ret = ZSTD_decompressDCtx(dctx, out_buf, out_len, in_buf, in_len); + err = handle_zstd_error(ret, error); + if (err) + goto out; + + if (in_pos != NULL) + *in_pos = in_len; + + err = 0; +out: + if (wksp != NULL) + large_free(wksp); + return err; +} + +static int INIT __unzstd(unsigned char *in_buf, long in_len, + long (*fill)(void*, unsigned long), + long (*flush)(void*, unsigned long), + unsigned char *out_buf, long out_len, + long *in_pos, + void (*error)(char *x)) +{ + ZSTD_inBuffer in; + ZSTD_outBuffer out; + ZSTD_frameParams params; + void *in_allocated = NULL; + void *out_allocated = NULL; + void *wksp = NULL; + size_t wksp_size; + ZSTD_DStream *dstream; + int err; + size_t ret; + + if (out_len == 0) + out_len = LONG_MAX; /* no limit */ + + if (fill == NULL && flush == NULL) + /* + * We can decompress faster and with less memory when we have a + * single chunk. + */ + return decompress_single(in_buf, in_len, out_buf, out_len, + in_pos, error); + + /* + * If in_buf is not provided, we must be using fill(), so allocate + * a large enough buffer. If it is provided, it must be at least + * ZSTD_IOBUF_SIZE large. + */ + if (in_buf == NULL) { + in_allocated = large_malloc(ZSTD_IOBUF_SIZE); + if (in_allocated == NULL) { + error("Out of memory while allocating input buffer"); + err = -1; + goto out; + } + in_buf = in_allocated; + in_len = 0; + } + /* Read the first chunk, since we need to decode the frame header. */ + if (fill != NULL) + in_len = fill(in_buf, ZSTD_IOBUF_SIZE); + if (in_len < 0) { + error("ZSTD-compressed data is truncated"); + err = -1; + goto out; + } + /* Set the first non-empty input buffer. */ + in.src = in_buf; + in.pos = 0; + in.size = in_len; + /* Allocate the output buffer if we are using flush(). */ + if (flush != NULL) { + out_allocated = large_malloc(ZSTD_IOBUF_SIZE); + if (out_allocated == NULL) { + error("Out of memory while allocating output buffer"); + err = -1; + goto out; + } + out_buf = out_allocated; + out_len = ZSTD_IOBUF_SIZE; + } + /* Set the output buffer. */ + out.dst = out_buf; + out.pos = 0; + out.size = out_len; + + /* + * We need to know the window size to allocate the ZSTD_DStream. + * Since we are streaming, we need to allocate a buffer for the sliding + * window. The window size varies from 1 KB to ZSTD_WINDOWSIZE_MAX + * (8 MB), so it is important to use the actual value so as not to + * waste memory when it is smaller. + */ + ret = ZSTD_getFrameParams(¶ms, in.src, in.size); + err = handle_zstd_error(ret, error); + if (err) + goto out; + if (ret != 0) { + error("ZSTD-compressed data has an incomplete frame header"); + err = -1; + goto out; + } + if (params.windowSize > ZSTD_WINDOWSIZE_MAX) { + error("ZSTD-compressed data has too large a window size"); + err = -1; + goto out; + } + + /* + * Allocate the ZSTD_DStream now that we know how much memory is + * required. + */ + wksp_size = ZSTD_DStreamWorkspaceBound(params.windowSize); + wksp = large_malloc(wksp_size); + dstream = ZSTD_initDStream(params.windowSize, wksp, wksp_size); + if (dstream == NULL) { + error("Out of memory while allocating ZSTD_DStream"); + err = -1; + goto out; + } + + /* + * Decompression loop: + * Read more data if necessary (error if no more data can be read). + * Call the decompression function, which returns 0 when finished. + * Flush any data produced if using flush(). + */ + if (in_pos != NULL) + *in_pos = 0; + do { + /* + * If we need to reload data, either we have fill() and can + * try to get more data, or we don't and the input is truncated. + */ + if (in.pos == in.size) { + if (in_pos != NULL) + *in_pos += in.pos; + in_len = fill ? fill(in_buf, ZSTD_IOBUF_SIZE) : -1; + if (in_len < 0) { + error("ZSTD-compressed data is truncated"); + err = -1; + goto out; + } + in.pos = 0; + in.size = in_len; + } + /* Returns zero when the frame is complete. */ + ret = ZSTD_decompressStream(dstream, &out, &in); + err = handle_zstd_error(ret, error); + if (err) + goto out; + /* Flush all of the data produced if using flush(). */ + if (flush != NULL && out.pos > 0) { + if (out.pos != flush(out.dst, out.pos)) { + error("Failed to flush()"); + err = -1; + goto out; + } + out.pos = 0; + } + } while (ret != 0); + + if (in_pos != NULL) + *in_pos += in.pos; + + err = 0; +out: + if (in_allocated != NULL) + large_free(in_allocated); + if (out_allocated != NULL) + large_free(out_allocated); + if (wksp != NULL) + large_free(wksp); + return err; +} + +#ifndef UNZSTD_PREBOOT +STATIC int INIT unzstd(unsigned char *buf, long len, + long (*fill)(void*, unsigned long), + long (*flush)(void*, unsigned long), + unsigned char *out_buf, + long *pos, + void (*error)(char *x)) +{ + return __unzstd(buf, len, fill, flush, out_buf, 0, pos, error); +} +#else +STATIC int INIT __decompress(unsigned char *buf, long len, + long (*fill)(void*, unsigned long), + long (*flush)(void*, unsigned long), + unsigned char *out_buf, long out_len, + long *pos, + void (*error)(char *x)) +{ + return __unzstd(buf, len, fill, flush, out_buf, out_len, pos, error); +} +#endif From 512a88f5068718df4858b5a29af8e09a7e270ef6 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Thu, 30 Jul 2020 12:08:38 -0700 Subject: [PATCH 547/592] x86: Bump ZO_z_extra_bytes margin for zstd Bump the ZO_z_extra_bytes margin for zstd. Zstd needs 3 bytes per 128 KB, and has a 22 byte fixed overhead. Zstd needs to maintain 128 KB of space at all times, since that is the maximum block size. See the comments regarding in-place decompression added in lib/decompress_unzstd.c for details. The existing code is written so that all the compression algorithms use the same ZO_z_extra_bytes. It is taken to be the maximum of the growth rate plus the maximum fixed overhead. The comments just above this diff state that: Signed-off-by: Nick Terrell Signed-off-by: Ingo Molnar Tested-by: Sedat Dilek Reviewed-by: Kees Cook Link: https://lore.kernel.org/r/20200730190841.2071656-6-nickrterrell@gmail.com Signed-off-by: UtsavBalar1231 --- arch/x86/boot/header.S | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S index 9c7ea597eee6..bc2ed038988a 100644 --- a/arch/x86/boot/header.S +++ b/arch/x86/boot/header.S @@ -527,8 +527,14 @@ pref_address: .quad LOAD_PHYSICAL_ADDR # preferred load addr # the size-dependent part now grows so fast. # # extra_bytes = (uncompressed_size >> 8) + 65536 +# +# ZSTD compressed data grows by at most 3 bytes per 128K, and only has a 22 +# byte fixed overhead but has a maximum block size of 128K, so it needs a +# larger margin. +# +# extra_bytes = (uncompressed_size >> 8) + 131072 -#define ZO_z_extra_bytes ((ZO_z_output_len >> 8) + 65536) +#define ZO_z_extra_bytes ((ZO_z_output_len >> 8) + 131072) #if ZO_z_output_len > ZO_z_input_len # define ZO_z_extract_offset (ZO_z_output_len + ZO_z_extra_bytes - \ ZO_z_input_len) From 2b1b22eeb73a8f4140087bfd97c6d22e57aa5faf Mon Sep 17 00:00:00 2001 From: Adam Borowski Date: Thu, 30 Jul 2020 12:08:40 -0700 Subject: [PATCH 548/592] .gitignore: Add ZSTD-compressed files For now, that's arch/x86/boot/compressed/vmlinux.bin.zst but probably more will come, thus let's be consistent with all other compressors. Signed-off-by: Adam Borowski Signed-off-by: Nick Terrell Signed-off-by: Ingo Molnar Tested-by: Sedat Dilek Reviewed-by: Kees Cook Link: https://lore.kernel.org/r/20200730190841.2071656-8-nickrterrell@gmail.com Signed-off-by: UtsavBalar1231 --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 26813d864c87..70bc59603718 100644 --- a/.gitignore +++ b/.gitignore @@ -39,6 +39,7 @@ *.symtypes *.tar *.xz +*.zst Module.symvers modules.builtin From 2025250090b38d73e1cfdda30bd53bcc3f5d2b3f Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Thu, 30 Jul 2020 12:08:41 -0700 Subject: [PATCH 549/592] Documentation: dontdiff: Add zstd compressed files For now, that's arch/x86/boot/compressed/vmlinux.bin.zst but probably more will come, thus let's be consistent with all other compressors. Signed-off-by: Nick Terrell Signed-off-by: Ingo Molnar Link: https://lore.kernel.org/r/20200730190841.2071656-9-nickrterrell@gmail.com Signed-off-by: UtsavBalar1231 --- Documentation/dontdiff | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/dontdiff b/Documentation/dontdiff index 2e2e52c267d5..844284713420 100644 --- a/Documentation/dontdiff +++ b/Documentation/dontdiff @@ -54,6 +54,7 @@ *.ver *.xml *.xz +*.zst *_MODULES *_vga16.c *~ From 75e6424444bee9c1409bebc597310e87ffaeee1c Mon Sep 17 00:00:00 2001 From: Taejoon Song Date: Thu, 30 Jan 2020 22:15:22 -0800 Subject: [PATCH 550/592] zram: try to avoid worst-case scenario on same element pages The worst-case scenario on finding same element pages is that almost all elements are same at the first glance but only last few elements are different. Since the same element tends to be grouped from the beginning of the pages, if we check the first element with the last element before looping through all elements, we might have some chances to quickly detect non-same element pages. 1. Test is done under LG webOS TV (64-bit arch) 2. Dump the swap-out pages (~819200 pages) 3. Analyze the pages with simple test script which counts the iteration number and measures the speed at off-line Under 64-bit arch, the worst iteration count is PAGE_SIZE / 8 bytes = 512. The speed is based on the time to consume page_same_filled() function only. The result, on average, is listed as below: Num of Iter Speed(MB/s) Looping-Forward (Orig) 38 99265 Looping-Backward 36 102725 Last-element-check (This Patch) 33 125072 The result shows that the average iteration count decreases by 13% and the speed increases by 25% with this patch. This patch does not increase the overall time complexity, though. I also ran simpler version which uses backward loop. Just looping backward also makes some improvement, but less than this patch. [taejoon.song@lge.com: fix off-by-one] Link: http://lkml.kernel.org/r/1578642001-11765-1-git-send-email-taejoon.song@lge.com Link: http://lkml.kernel.org/r/1575424418-16119-1-git-send-email-taejoon.song@lge.com Signed-off-by: Taejoon Song Acked-by: Minchan Kim Cc: Sergey Senozhatsky Cc: Jens Axboe Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: UtsavBalar1231 --- drivers/block/zram/zram_drv.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c index 9d7866ac40b8..49a7b784f729 100644 --- a/drivers/block/zram/zram_drv.c +++ b/drivers/block/zram/zram_drv.c @@ -208,14 +208,17 @@ static inline void zram_fill_page(void *ptr, unsigned long len, static bool page_same_filled(void *ptr, unsigned long *element) { - unsigned int pos; unsigned long *page; unsigned long val; + unsigned int pos, last_pos = PAGE_SIZE / sizeof(*page) - 1; page = (unsigned long *)ptr; val = page[0]; - for (pos = 1; pos < PAGE_SIZE / sizeof(*page); pos++) { + if (val != page[last_pos]) + return false; + + for (pos = 1; pos < last_pos; pos++) { if (val != page[pos]) return false; } From f2c97e34fd8efebb5f96f68d2aeb8af52476e5fa Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 30 Jan 2020 22:15:25 -0800 Subject: [PATCH 551/592] drivers/block/zram/zram_drv.c: fix error return codes not being returned in writeback_store Currently when an error code -EIO or -ENOSPC in the for-loop of writeback_store the error code is being overwritten by a ret = len assignment at the end of the function and the error codes are being lost. Fix this by assigning ret = len at the start of the function and remove the assignment from the end, hence allowing ret to be preserved when error codes are assigned to it. Addresses Coverity ("Unused value") Link: http://lkml.kernel.org/r/20191128122958.178290-1-colin.king@canonical.com Fixes: a939888ec38b ("zram: support idle/huge page writeback") Signed-off-by: Colin Ian King Acked-by: Minchan Kim Cc: Sergey Senozhatsky Cc: Jens Axboe Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: UtsavBalar1231 --- drivers/block/zram/zram_drv.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c index 49a7b784f729..19247ee48cbd 100644 --- a/drivers/block/zram/zram_drv.c +++ b/drivers/block/zram/zram_drv.c @@ -617,7 +617,7 @@ static ssize_t writeback_store(struct device *dev, struct bio bio; struct bio_vec bio_vec; struct page *page; - ssize_t ret; + ssize_t ret = len; int mode; unsigned long blk_idx = 0; @@ -753,7 +753,6 @@ next: if (blk_idx) free_block_bdev(zram, blk_idx); - ret = len; __free_page(page); release_init_lock: up_read(&zram->init_lock); From 5a89b931896782d00c5caa8fa05f96b7489770ee Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 27 May 2020 22:11:18 +0200 Subject: [PATCH 552/592] zram: Allocate struct zcomp_strm as per-CPU memory zcomp::stream is a per-CPU pointer, pointing to struct zcomp_strm which contains two pointers. Having struct zcomp_strm allocated directly as per-CPU memory would avoid one additional memory allocation and a pointer dereference. This also simplifies the addition of a local_lock to struct zcomp_strm. Allocate zcomp::stream directly as per-CPU memory. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Ingo Molnar Acked-by: Peter Zijlstra Link: https://lore.kernel.org/r/20200527201119.1692513-7-bigeasy@linutronix.de Signed-off-by: UtsavBalar1231 --- drivers/block/zram/zcomp.c | 41 +++++++++++++++----------------------- drivers/block/zram/zcomp.h | 2 +- 2 files changed, 17 insertions(+), 26 deletions(-) diff --git a/drivers/block/zram/zcomp.c b/drivers/block/zram/zcomp.c index e9b08f356b5b..7141b0fc0ae9 100644 --- a/drivers/block/zram/zcomp.c +++ b/drivers/block/zram/zcomp.c @@ -44,19 +44,16 @@ static void zcomp_strm_free(struct zcomp_strm *zstrm) if (!IS_ERR_OR_NULL(zstrm->tfm)) crypto_free_comp(zstrm->tfm); free_pages((unsigned long)zstrm->buffer, 1); - kfree(zstrm); + zstrm->tfm = NULL; + zstrm->buffer = NULL; } /* - * allocate new zcomp_strm structure with ->tfm initialized by - * backend, return NULL on error + * Initialize zcomp_strm structure with ->tfm initialized by backend, and + * ->buffer. Return a negative value on error. */ -static struct zcomp_strm *zcomp_strm_alloc(struct zcomp *comp) +static int zcomp_strm_init(struct zcomp_strm *zstrm, struct zcomp *comp) { - struct zcomp_strm *zstrm = kmalloc(sizeof(*zstrm), GFP_KERNEL); - if (!zstrm) - return NULL; - zstrm->tfm = crypto_alloc_comp(comp->name, 0, 0); /* * allocate 2 pages. 1 for compressed data, plus 1 extra for the @@ -65,9 +62,9 @@ static struct zcomp_strm *zcomp_strm_alloc(struct zcomp *comp) zstrm->buffer = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 1); if (IS_ERR_OR_NULL(zstrm->tfm) || !zstrm->buffer) { zcomp_strm_free(zstrm); - zstrm = NULL; + return -ENOMEM; } - return zstrm; + return 0; } bool zcomp_available_algorithm(const char *comp) @@ -120,7 +117,7 @@ ssize_t zcomp_available_show(const char *comp, char *buf) struct zcomp_strm *zcomp_stream_get(struct zcomp *comp) { - return *get_cpu_ptr(comp->stream); + return get_cpu_ptr(comp->stream); } void zcomp_stream_put(struct zcomp *comp) @@ -166,17 +163,13 @@ int zcomp_cpu_up_prepare(unsigned int cpu, struct hlist_node *node) { struct zcomp *comp = hlist_entry(node, struct zcomp, node); struct zcomp_strm *zstrm; + int ret; - if (WARN_ON(*per_cpu_ptr(comp->stream, cpu))) - return 0; - - zstrm = zcomp_strm_alloc(comp); - if (IS_ERR_OR_NULL(zstrm)) { + zstrm = per_cpu_ptr(comp->stream, cpu); + ret = zcomp_strm_init(zstrm, comp); + if (ret) pr_err("Can't allocate a compression stream\n"); - return -ENOMEM; - } - *per_cpu_ptr(comp->stream, cpu) = zstrm; - return 0; + return ret; } int zcomp_cpu_dead(unsigned int cpu, struct hlist_node *node) @@ -184,10 +177,8 @@ int zcomp_cpu_dead(unsigned int cpu, struct hlist_node *node) struct zcomp *comp = hlist_entry(node, struct zcomp, node); struct zcomp_strm *zstrm; - zstrm = *per_cpu_ptr(comp->stream, cpu); - if (!IS_ERR_OR_NULL(zstrm)) - zcomp_strm_free(zstrm); - *per_cpu_ptr(comp->stream, cpu) = NULL; + zstrm = per_cpu_ptr(comp->stream, cpu); + zcomp_strm_free(zstrm); return 0; } @@ -195,7 +186,7 @@ static int zcomp_init(struct zcomp *comp) { int ret; - comp->stream = alloc_percpu(struct zcomp_strm *); + comp->stream = alloc_percpu(struct zcomp_strm); if (!comp->stream) return -ENOMEM; diff --git a/drivers/block/zram/zcomp.h b/drivers/block/zram/zcomp.h index 41c1002a7d7d..9e94095ce000 100644 --- a/drivers/block/zram/zcomp.h +++ b/drivers/block/zram/zcomp.h @@ -18,7 +18,7 @@ struct zcomp_strm { /* dynamic per-device compression frontend */ struct zcomp { - struct zcomp_strm * __percpu *stream; + struct zcomp_strm __percpu *stream; const char *name; struct hlist_node node; }; From e1a0217e5b43cb55fdc75d4d4cf1bef5e443d36b Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 4 Jun 2020 16:49:52 -0700 Subject: [PATCH 553/592] zcomp: Use ARRAY_SIZE() for backends list Instead of keeping NULL terminated array switch to use ARRAY_SIZE() which helps to further clean up. Signed-off-by: Andy Shevchenko Signed-off-by: Andrew Morton Reviewed-by: Andrew Morton Acked-by: Minchan Kim Cc: Sergey Senozhatsky Cc: Jens Axboe Cc: Andy Shevchenko Link: http://lkml.kernel.org/r/20200508100758.51644-1-andriy.shevchenko@linux.intel.com Signed-off-by: Linus Torvalds Signed-off-by: UtsavBalar1231 --- drivers/block/zram/zcomp.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/block/zram/zcomp.c b/drivers/block/zram/zcomp.c index 7141b0fc0ae9..91adb747d585 100644 --- a/drivers/block/zram/zcomp.c +++ b/drivers/block/zram/zcomp.c @@ -36,7 +36,6 @@ static const char * const backends[] = { #if IS_ENABLED(CONFIG_CRYPTO_ZSTD) "zstd", #endif - NULL }; static void zcomp_strm_free(struct zcomp_strm *zstrm) @@ -71,7 +70,7 @@ bool zcomp_available_algorithm(const char *comp) { int i; - i = __sysfs_match_string(backends, -1, comp); + i = sysfs_match_string(backends, comp); if (i >= 0) return true; @@ -90,9 +89,9 @@ ssize_t zcomp_available_show(const char *comp, char *buf) { bool known_algorithm = false; ssize_t sz = 0; - int i = 0; + int i; - for (; backends[i]; i++) { + for (i = 0; i < ARRAY_SIZE(backends); i++) { if (!strcmp(comp, backends[i])) { known_algorithm = true; sz += scnprintf(buf + sz, PAGE_SIZE - sz - 2, From 11d0ac25dda1d0c37a6660867a421b8c77b939ec Mon Sep 17 00:00:00 2001 From: UtsavBalar1231 Date: Mon, 17 Aug 2020 18:53:14 +0530 Subject: [PATCH 554/592] ARM64: configs: raphael: use zstd from zRAM compression Signed-off-by: UtsavBalar1231 --- arch/arm64/configs/raphael_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/configs/raphael_defconfig b/arch/arm64/configs/raphael_defconfig index f15437ed2f05..26a65ea2193d 100644 --- a/arch/arm64/configs/raphael_defconfig +++ b/arch/arm64/configs/raphael_defconfig @@ -1408,7 +1408,7 @@ CONFIG_BLK_DEV=y # CONFIG_BLK_DEV_NULL_BLK is not set CONFIG_ZRAM=y CONFIG_ZRAM_WRITEBACK=y -CONFIG_ZRAM_DEFAULT_COMP_ALGORITHM="lz4" +CONFIG_ZRAM_DEFAULT_COMP_ALGORITHM="zstd" CONFIG_ZRAM_SIZE_OVERRIDE=2 # CONFIG_BLK_DEV_COW_COMMON is not set CONFIG_BLK_DEV_LOOP=y From 5cd56b558f8806eac0bf126862c087f19fe8882d Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Wed, 15 Nov 2017 17:32:18 -0800 Subject: [PATCH 555/592] slab, slub, slob: add slab_flags_t Add sparse-checked slab_flags_t for struct kmem_cache::flags (SLAB_POISON, etc). SLAB is bloated temporarily by switching to "unsigned long", but only temporarily. Link: http://lkml.kernel.org/r/20171021100225.GA22428@avx2 Signed-off-by: Alexey Dobriyan Acked-by: Pekka Enberg Cc: Christoph Lameter Cc: David Rientjes Cc: Joonsoo Kim Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: UtsavBalar1231 --- fs/ecryptfs/main.c | 2 +- fs/xfs/kmem.h | 2 +- include/linux/kasan.h | 4 +-- include/linux/kmemleak.h | 8 +++--- include/linux/slab.h | 55 +++++++++++++++++++++++++--------------- include/linux/slab_def.h | 2 +- include/linux/slub_def.h | 2 +- include/linux/types.h | 1 + include/net/sock.h | 2 +- mm/kasan/common.c | 2 +- mm/slab.c | 23 ++++++++--------- mm/slab.h | 26 +++++++++---------- mm/slab_common.c | 16 ++++++------ mm/slob.c | 2 +- mm/slub.c | 26 ++++++++++--------- 15 files changed, 94 insertions(+), 79 deletions(-) diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index 6b801186baa5..25aeaa7328ba 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c @@ -660,7 +660,7 @@ static struct ecryptfs_cache_info { struct kmem_cache **cache; const char *name; size_t size; - unsigned long flags; + slab_flags_t flags; void (*ctor)(void *obj); } ecryptfs_cache_infos[] = { { diff --git a/fs/xfs/kmem.h b/fs/xfs/kmem.h index 4d85992d75b2..7509019ae922 100644 --- a/fs/xfs/kmem.h +++ b/fs/xfs/kmem.h @@ -104,7 +104,7 @@ kmem_zone_init(int size, char *zone_name) } static inline kmem_zone_t * -kmem_zone_init_flags(int size, char *zone_name, unsigned long flags, +kmem_zone_init_flags(int size, char *zone_name, slab_flags_t flags, void (*construct)(void *)) { return kmem_cache_create(zone_name, size, 0, flags, construct); diff --git a/include/linux/kasan.h b/include/linux/kasan.h index 6c5bf7e3cf44..fb01155e1adb 100644 --- a/include/linux/kasan.h +++ b/include/linux/kasan.h @@ -44,7 +44,7 @@ void kasan_alloc_pages(struct page *page, unsigned int order); void kasan_free_pages(struct page *page, unsigned int order); void kasan_cache_create(struct kmem_cache *cache, unsigned int *size, - unsigned long *flags); + slab_flags_t *flags); void kasan_poison_slab(struct page *page); void kasan_unpoison_object_data(struct kmem_cache *cache, void *object); @@ -98,7 +98,7 @@ static inline void kasan_free_pages(struct page *page, unsigned int order) {} static inline void kasan_cache_create(struct kmem_cache *cache, unsigned int *size, - unsigned long *flags) {} + slab_flags_t *flags) {} static inline void kasan_poison_slab(struct page *page) {} static inline void kasan_unpoison_object_data(struct kmem_cache *cache, diff --git a/include/linux/kmemleak.h b/include/linux/kmemleak.h index 590343f6c1b1..5ac416e2d339 100644 --- a/include/linux/kmemleak.h +++ b/include/linux/kmemleak.h @@ -48,14 +48,14 @@ extern void kmemleak_not_leak_phys(phys_addr_t phys) __ref; extern void kmemleak_ignore_phys(phys_addr_t phys) __ref; static inline void kmemleak_alloc_recursive(const void *ptr, size_t size, - int min_count, unsigned long flags, + int min_count, slab_flags_t flags, gfp_t gfp) { if (!(flags & SLAB_NOLEAKTRACE)) kmemleak_alloc(ptr, size, min_count, gfp); } -static inline void kmemleak_free_recursive(const void *ptr, unsigned long flags) +static inline void kmemleak_free_recursive(const void *ptr, slab_flags_t flags) { if (!(flags & SLAB_NOLEAKTRACE)) kmemleak_free(ptr); @@ -76,7 +76,7 @@ static inline void kmemleak_alloc(const void *ptr, size_t size, int min_count, { } static inline void kmemleak_alloc_recursive(const void *ptr, size_t size, - int min_count, unsigned long flags, + int min_count, slab_flags_t flags, gfp_t gfp) { } @@ -94,7 +94,7 @@ static inline void kmemleak_free(const void *ptr) static inline void kmemleak_free_part(const void *ptr, size_t size) { } -static inline void kmemleak_free_recursive(const void *ptr, unsigned long flags) +static inline void kmemleak_free_recursive(const void *ptr, slab_flags_t flags) { } static inline void kmemleak_free_percpu(const void __percpu *ptr) diff --git a/include/linux/slab.h b/include/linux/slab.h index 5921f381f5bc..6ebed7ac533f 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -21,13 +21,20 @@ * Flags to pass to kmem_cache_create(). * The ones marked DEBUG are only valid if CONFIG_DEBUG_SLAB is set. */ -#define SLAB_CONSISTENCY_CHECKS 0x00000100UL /* DEBUG: Perform (expensive) checks on alloc/free */ -#define SLAB_RED_ZONE 0x00000400UL /* DEBUG: Red zone objs in a cache */ -#define SLAB_POISON 0x00000800UL /* DEBUG: Poison objects */ -#define SLAB_HWCACHE_ALIGN 0x00002000UL /* Align objs on cache lines */ -#define SLAB_CACHE_DMA 0x00004000UL /* Use GFP_DMA memory */ -#define SLAB_STORE_USER 0x00010000UL /* DEBUG: Store the last owner for bug hunting */ -#define SLAB_PANIC 0x00040000UL /* Panic if kmem_cache_create() fails */ +/* DEBUG: Perform (expensive) checks on alloc/free */ +#define SLAB_CONSISTENCY_CHECKS ((slab_flags_t __force)0x00000100UL) +/* DEBUG: Red zone objs in a cache */ +#define SLAB_RED_ZONE ((slab_flags_t __force)0x00000400UL) +/* DEBUG: Poison objects */ +#define SLAB_POISON ((slab_flags_t __force)0x00000800UL) +/* Align objs on cache lines */ +#define SLAB_HWCACHE_ALIGN ((slab_flags_t __force)0x00002000UL) +/* Use GFP_DMA memory */ +#define SLAB_CACHE_DMA ((slab_flags_t __force)0x00004000UL) +/* DEBUG: Store the last owner for bug hunting */ +#define SLAB_STORE_USER ((slab_flags_t __force)0x00010000UL) +/* Panic if kmem_cache_create() fails */ +#define SLAB_PANIC ((slab_flags_t __force)0x00040000UL) /* * SLAB_TYPESAFE_BY_RCU - **WARNING** READ THIS! * @@ -65,38 +72,44 @@ * * Note that SLAB_TYPESAFE_BY_RCU was originally named SLAB_DESTROY_BY_RCU. */ -#define SLAB_TYPESAFE_BY_RCU 0x00080000UL /* Defer freeing slabs to RCU */ -#define SLAB_MEM_SPREAD 0x00100000UL /* Spread some memory over cpuset */ -#define SLAB_TRACE 0x00200000UL /* Trace allocations and frees */ +/* Defer freeing slabs to RCU */ +#define SLAB_TYPESAFE_BY_RCU ((slab_flags_t __force)0x00080000UL) +/* Spread some memory over cpuset */ +#define SLAB_MEM_SPREAD ((slab_flags_t __force)0x00100000UL) +/* Trace allocations and frees */ +#define SLAB_TRACE ((slab_flags_t __force)0x00200000UL) /* Flag to prevent checks on free */ #ifdef CONFIG_DEBUG_OBJECTS -# define SLAB_DEBUG_OBJECTS 0x00400000UL +# define SLAB_DEBUG_OBJECTS ((slab_flags_t __force)0x00400000UL) #else -# define SLAB_DEBUG_OBJECTS 0x00000000UL +# define SLAB_DEBUG_OBJECTS ((slab_flags_t __force)0x00000000UL) #endif -#define SLAB_NOLEAKTRACE 0x00800000UL /* Avoid kmemleak tracing */ +/* Avoid kmemleak tracing */ +#define SLAB_NOLEAKTRACE ((slab_flags_t __force)0x00800000UL) #ifdef CONFIG_FAILSLAB -# define SLAB_FAILSLAB 0x02000000UL /* Fault injection mark */ +# define SLAB_FAILSLAB ((slab_flags_t __force)0x02000000UL) #else -# define SLAB_FAILSLAB 0x00000000UL +# define SLAB_FAILSLAB ((slab_flags_t __force)0x00000000UL) #endif +/* Account to memcg */ #if defined(CONFIG_MEMCG) && !defined(CONFIG_SLOB) -# define SLAB_ACCOUNT 0x04000000UL /* Account to memcg */ +# define SLAB_ACCOUNT ((slab_flags_t __force)0x04000000UL) #else -# define SLAB_ACCOUNT 0x00000000UL +# define SLAB_ACCOUNT ((slab_flags_t __force)0x00000000UL) #endif #ifdef CONFIG_KASAN -#define SLAB_KASAN 0x08000000UL +#define SLAB_KASAN ((slab_flags_t __force)0x08000000UL) #else -#define SLAB_KASAN 0x00000000UL +#define SLAB_KASAN ((slab_flags_t __force)0x00000000UL) #endif /* The following flags affect the page allocator grouping pages by mobility */ -#define SLAB_RECLAIM_ACCOUNT 0x00020000UL /* Objects are reclaimable */ +/* Objects are reclaimable */ +#define SLAB_RECLAIM_ACCOUNT ((slab_flags_t __force)0x00020000UL) #define SLAB_TEMPORARY SLAB_RECLAIM_ACCOUNT /* Objects are short-lived */ /* * ZERO_SIZE_PTR will be returned for zero sized kmalloc requests. @@ -122,7 +135,7 @@ void __init kmem_cache_init(void); bool slab_is_available(void); struct kmem_cache *kmem_cache_create(const char *, size_t, size_t, - unsigned long, + slab_flags_t, void (*)(void *)); void kmem_cache_destroy(struct kmem_cache *); int kmem_cache_shrink(struct kmem_cache *); diff --git a/include/linux/slab_def.h b/include/linux/slab_def.h index b2932047163d..94217ef9baf3 100644 --- a/include/linux/slab_def.h +++ b/include/linux/slab_def.h @@ -20,7 +20,7 @@ struct kmem_cache { struct reciprocal_value reciprocal_buffer_size; /* 2) touched by every alloc & free from the backend */ - unsigned int flags; /* constant flags */ + slab_flags_t flags; /* constant flags */ unsigned int num; /* # of objs per slab */ /* 3) cache_grow/shrink */ diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h index f8ced87a2efe..96895128c1b3 100644 --- a/include/linux/slub_def.h +++ b/include/linux/slub_def.h @@ -82,7 +82,7 @@ struct kmem_cache_order_objects { struct kmem_cache { struct kmem_cache_cpu __percpu *cpu_slab; /* Used for retriving partial slabs etc */ - unsigned long flags; + slab_flags_t flags; unsigned long min_partial; int size; /* The size of an object including meta data */ int object_size; /* The size of an object without meta data */ diff --git a/include/linux/types.h b/include/linux/types.h index 3ce3d5a70e76..7fe2d9d600fe 100644 --- a/include/linux/types.h +++ b/include/linux/types.h @@ -160,6 +160,7 @@ typedef u32 dma_addr_t; #endif typedef unsigned __bitwise gfp_t; +typedef unsigned long __bitwise slab_flags_t; typedef unsigned __bitwise fmode_t; #ifdef CONFIG_PHYS_ADDR_T_64BIT diff --git a/include/net/sock.h b/include/net/sock.h index 366fe76a1a30..a460e3ec35c8 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1131,7 +1131,7 @@ struct proto { struct kmem_cache *slab; unsigned int obj_size; - int slab_flags; + slab_flags_t slab_flags; struct percpu_counter *orphan_count; diff --git a/mm/kasan/common.c b/mm/kasan/common.c index 46ef2ea7293a..b1d791b36eca 100644 --- a/mm/kasan/common.c +++ b/mm/kasan/common.c @@ -261,7 +261,7 @@ static inline unsigned int optimal_redzone(unsigned int object_size) } void kasan_cache_create(struct kmem_cache *cache, unsigned int *size, - unsigned long *flags) + slab_flags_t *flags) { unsigned int orig_size = *size; unsigned int redzone_size; diff --git a/mm/slab.c b/mm/slab.c index 5dd23f6fd451..417f20f09e1c 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -251,8 +251,8 @@ static void kmem_cache_node_init(struct kmem_cache_node *parent) MAKE_LIST((cachep), (&(ptr)->slabs_free), slabs_free, nodeid); \ } while (0) -#define CFLGS_OBJFREELIST_SLAB (0x40000000UL) -#define CFLGS_OFF_SLAB (0x80000000UL) +#define CFLGS_OBJFREELIST_SLAB ((slab_flags_t __force)0x40000000UL) +#define CFLGS_OFF_SLAB ((slab_flags_t __force)0x80000000UL) #define OBJFREELIST_SLAB(x) ((x)->flags & CFLGS_OBJFREELIST_SLAB) #define OFF_SLAB(x) ((x)->flags & CFLGS_OFF_SLAB) @@ -427,7 +427,7 @@ static inline struct array_cache *cpu_cache_get(struct kmem_cache *cachep) * Calculate the number of objects and left-over bytes for a given buffer size. */ static unsigned int cache_estimate(unsigned long gfporder, size_t buffer_size, - unsigned long flags, size_t *left_over) + slab_flags_t flags, size_t *left_over) { unsigned int num; size_t slab_size = PAGE_SIZE << gfporder; @@ -1737,7 +1737,7 @@ static void slabs_destroy(struct kmem_cache *cachep, struct list_head *list) * towards high-order requests, this should be changed. */ static size_t calculate_slab_order(struct kmem_cache *cachep, - size_t size, unsigned long flags) + size_t size, slab_flags_t flags) { size_t left_over = 0; int gfporder; @@ -1864,8 +1864,8 @@ static int __ref setup_cpu_cache(struct kmem_cache *cachep, gfp_t gfp) return 0; } -unsigned long kmem_cache_flags(unsigned long object_size, - unsigned long flags, const char *name, +slab_flags_t kmem_cache_flags(unsigned long object_size, + slab_flags_t flags, const char *name, void (*ctor)(void *)) { return flags; @@ -1873,7 +1873,7 @@ unsigned long kmem_cache_flags(unsigned long object_size, struct kmem_cache * __kmem_cache_alias(const char *name, size_t size, size_t align, - unsigned long flags, void (*ctor)(void *)) + slab_flags_t flags, void (*ctor)(void *)) { struct kmem_cache *cachep; @@ -1891,7 +1891,7 @@ __kmem_cache_alias(const char *name, size_t size, size_t align, } static bool set_objfreelist_slab_cache(struct kmem_cache *cachep, - size_t size, unsigned long flags) + size_t size, slab_flags_t flags) { size_t left; @@ -1922,7 +1922,7 @@ static bool set_objfreelist_slab_cache(struct kmem_cache *cachep, } static bool set_off_slab_cache(struct kmem_cache *cachep, - size_t size, unsigned long flags) + size_t size, slab_flags_t flags) { size_t left; @@ -1956,7 +1956,7 @@ static bool set_off_slab_cache(struct kmem_cache *cachep, } static bool set_on_slab_cache(struct kmem_cache *cachep, - size_t size, unsigned long flags) + size_t size, slab_flags_t flags) { size_t left; @@ -1992,8 +1992,7 @@ static bool set_on_slab_cache(struct kmem_cache *cachep, * cacheline. This can be beneficial if you're counting cycles as closely * as davem. */ -int -__kmem_cache_create (struct kmem_cache *cachep, unsigned long flags) +int __kmem_cache_create(struct kmem_cache *cachep, slab_flags_t flags) { size_t ralign = BYTES_PER_WORD; gfp_t gfp; diff --git a/mm/slab.h b/mm/slab.h index 20ee67d11bb4..ecb84c5568db 100644 --- a/mm/slab.h +++ b/mm/slab.h @@ -21,7 +21,7 @@ struct kmem_cache { unsigned int object_size;/* The original size of the object */ unsigned int size; /* The aligned/padded/added on size */ unsigned int align; /* Alignment as calculated */ - unsigned long flags; /* Active flags on the slab */ + slab_flags_t flags; /* Active flags on the slab */ const char *name; /* Slab name for sysfs */ int refcount; /* Use counter */ void (*ctor)(void *); /* Called on object slot creation */ @@ -78,13 +78,13 @@ extern const struct kmalloc_info_struct { unsigned long size; } kmalloc_info[]; -unsigned long calculate_alignment(unsigned long flags, +unsigned long calculate_alignment(slab_flags_t flags, unsigned long align, unsigned long size); #ifndef CONFIG_SLOB /* Kmalloc array related functions */ void setup_kmalloc_cache_index_table(void); -void create_kmalloc_caches(unsigned long); +void create_kmalloc_caches(slab_flags_t); /* Find the kmalloc slab corresponding for a certain size */ struct kmem_cache *kmalloc_slab(size_t, gfp_t); @@ -92,32 +92,32 @@ struct kmem_cache *kmalloc_slab(size_t, gfp_t); /* Functions provided by the slab allocators */ -extern int __kmem_cache_create(struct kmem_cache *, unsigned long flags); +int __kmem_cache_create(struct kmem_cache *, slab_flags_t flags); extern struct kmem_cache *create_kmalloc_cache(const char *name, size_t size, - unsigned long flags); + slab_flags_t flags); extern void create_boot_cache(struct kmem_cache *, const char *name, - size_t size, unsigned long flags); + size_t size, slab_flags_t flags); int slab_unmergeable(struct kmem_cache *s); struct kmem_cache *find_mergeable(size_t size, size_t align, - unsigned long flags, const char *name, void (*ctor)(void *)); + slab_flags_t flags, const char *name, void (*ctor)(void *)); #ifndef CONFIG_SLOB struct kmem_cache * __kmem_cache_alias(const char *name, size_t size, size_t align, - unsigned long flags, void (*ctor)(void *)); + slab_flags_t flags, void (*ctor)(void *)); -unsigned long kmem_cache_flags(unsigned long object_size, - unsigned long flags, const char *name, +slab_flags_t kmem_cache_flags(unsigned long object_size, + slab_flags_t flags, const char *name, void (*ctor)(void *)); #else static inline struct kmem_cache * __kmem_cache_alias(const char *name, size_t size, size_t align, - unsigned long flags, void (*ctor)(void *)) + slab_flags_t flags, void (*ctor)(void *)) { return NULL; } -static inline unsigned long kmem_cache_flags(unsigned long object_size, - unsigned long flags, const char *name, +static inline slab_flags_t kmem_cache_flags(unsigned long object_size, + slab_flags_t flags, const char *name, void (*ctor)(void *)) { return flags; diff --git a/mm/slab_common.c b/mm/slab_common.c index 7fe72acfa501..cdcbcd6238ab 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c @@ -291,7 +291,7 @@ int slab_unmergeable(struct kmem_cache *s) } struct kmem_cache *find_mergeable(size_t size, size_t align, - unsigned long flags, const char *name, void (*ctor)(void *)) + slab_flags_t flags, const char *name, void (*ctor)(void *)) { struct kmem_cache *s; @@ -341,7 +341,7 @@ struct kmem_cache *find_mergeable(size_t size, size_t align, * Figure out what the alignment of the objects will be given a set of * flags, a user specified alignment and the size of the objects. */ -unsigned long calculate_alignment(unsigned long flags, +unsigned long calculate_alignment(slab_flags_t flags, unsigned long align, unsigned long size) { /* @@ -366,7 +366,7 @@ unsigned long calculate_alignment(unsigned long flags, static struct kmem_cache *create_cache(const char *name, size_t object_size, size_t size, size_t align, - unsigned long flags, void (*ctor)(void *), + slab_flags_t flags, void (*ctor)(void *), struct mem_cgroup *memcg, struct kmem_cache *root_cache) { struct kmem_cache *s; @@ -431,7 +431,7 @@ out_free_cache: */ struct kmem_cache * kmem_cache_create(const char *name, size_t size, size_t align, - unsigned long flags, void (*ctor)(void *)) + slab_flags_t flags, void (*ctor)(void *)) { struct kmem_cache *s = NULL; const char *cache_name; @@ -883,7 +883,7 @@ bool slab_is_available(void) #ifndef CONFIG_SLOB /* Create a cache during boot when no slab services are available yet */ void __init create_boot_cache(struct kmem_cache *s, const char *name, size_t size, - unsigned long flags) + slab_flags_t flags) { int err; @@ -903,7 +903,7 @@ void __init create_boot_cache(struct kmem_cache *s, const char *name, size_t siz } struct kmem_cache *__init create_kmalloc_cache(const char *name, size_t size, - unsigned long flags) + slab_flags_t flags) { struct kmem_cache *s = kmem_cache_zalloc(kmem_cache, GFP_NOWAIT); @@ -1068,7 +1068,7 @@ kmalloc_cache_name(const char *prefix, unsigned int size) } static void __init -new_kmalloc_cache(int idx, int type, unsigned long flags) +new_kmalloc_cache(int idx, int type, slab_flags_t flags) { const char *name; @@ -1090,7 +1090,7 @@ new_kmalloc_cache(int idx, int type, unsigned long flags) * may already have been created because they were needed to * enable allocations for slab creation. */ -void __init create_kmalloc_caches(unsigned long flags) +void __init create_kmalloc_caches(slab_flags_t flags) { int i, type; diff --git a/mm/slob.c b/mm/slob.c index 10249160b693..839a52bc3fd5 100644 --- a/mm/slob.c +++ b/mm/slob.c @@ -524,7 +524,7 @@ size_t ksize(const void *block) } EXPORT_SYMBOL(ksize); -int __kmem_cache_create(struct kmem_cache *c, unsigned long flags) +int __kmem_cache_create(struct kmem_cache *c, slab_flags_t flags) { if (flags & SLAB_TYPESAFE_BY_RCU) { /* leave room for rcu footer at the end of object */ diff --git a/mm/slub.c b/mm/slub.c index f950312acfde..04dbe8139650 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -192,8 +192,10 @@ static inline bool kmem_cache_has_cpu_partial(struct kmem_cache *s) #define MAX_OBJS_PER_PAGE 32767 /* since page.objects is u15 */ /* Internal SLUB flags */ -#define __OBJECT_POISON 0x80000000UL /* Poison object */ -#define __CMPXCHG_DOUBLE 0x40000000UL /* Use cmpxchg_double */ +/* Poison object */ +#define __OBJECT_POISON ((slab_flags_t __force)0x80000000UL) +/* Use cmpxchg_double */ +#define __CMPXCHG_DOUBLE ((slab_flags_t __force)0x40000000UL) /* * Tracking user of a slab. @@ -489,9 +491,9 @@ static inline void *restore_red_left(struct kmem_cache *s, void *p) * Debug settings: */ #if defined(CONFIG_SLUB_DEBUG_ON) -static int slub_debug = DEBUG_DEFAULT_FLAGS; +static slab_flags_t slub_debug = DEBUG_DEFAULT_FLAGS; #else -static int slub_debug; +static slab_flags_t slub_debug; #endif static char *slub_debug_slabs; @@ -1334,8 +1336,8 @@ out: __setup("slub_debug", setup_slub_debug); -unsigned long kmem_cache_flags(unsigned long object_size, - unsigned long flags, const char *name, +slab_flags_t kmem_cache_flags(unsigned long object_size, + slab_flags_t flags, const char *name, void (*ctor)(void *)) { /* @@ -1369,8 +1371,8 @@ static inline void add_full(struct kmem_cache *s, struct kmem_cache_node *n, struct page *page) {} static inline void remove_full(struct kmem_cache *s, struct kmem_cache_node *n, struct page *page) {} -unsigned long kmem_cache_flags(unsigned long object_size, - unsigned long flags, const char *name, +slab_flags_t kmem_cache_flags(unsigned long object_size, + slab_flags_t flags, const char *name, void (*ctor)(void *)) { return flags; @@ -3591,7 +3593,7 @@ static void set_cpu_partial(struct kmem_cache *s) */ static int calculate_sizes(struct kmem_cache *s, int forced_order) { - unsigned long flags = s->flags; + slab_flags_t flags = s->flags; unsigned int size = s->object_size; int order; @@ -3707,7 +3709,7 @@ static int calculate_sizes(struct kmem_cache *s, int forced_order) return !!oo_objects(s->oo); } -static int kmem_cache_open(struct kmem_cache *s, unsigned long flags) +static int kmem_cache_open(struct kmem_cache *s, slab_flags_t flags) { s->flags = kmem_cache_flags(s->size, flags, s->name, s->ctor); s->reserved = 0; @@ -4372,7 +4374,7 @@ void __init kmem_cache_init_late(void) struct kmem_cache * __kmem_cache_alias(const char *name, size_t size, size_t align, - unsigned long flags, void (*ctor)(void *)) + slab_flags_t flags, void (*ctor)(void *)) { struct kmem_cache *s, *c; @@ -4402,7 +4404,7 @@ __kmem_cache_alias(const char *name, size_t size, size_t align, return s; } -int __kmem_cache_create(struct kmem_cache *s, unsigned long flags) +int __kmem_cache_create(struct kmem_cache *s, slab_flags_t flags) { int err; From 462ab7f5708f9bb2e6650abd0c9ba03357f86ad8 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Wed, 15 Nov 2017 17:32:21 -0800 Subject: [PATCH 556/592] slab, slub, slob: convert slab_flags_t to 32-bit struct kmem_cache::flags is "unsigned long" which is unnecessary on 64-bit as no flags are defined in the higher bits. Switch the field to 32-bit and save some space on x86_64 until such flags appear: add/remove: 0/0 grow/shrink: 0/107 up/down: 0/-657 (-657) function old new delta sysfs_slab_add 720 719 -1 ... check_object 699 676 -23 [akpm@linux-foundation.org: fix printk warning] Link: http://lkml.kernel.org/r/20171021100635.GA8287@avx2 Signed-off-by: Alexey Dobriyan Acked-by: Pekka Enberg Cc: Christoph Lameter Cc: David Rientjes Cc: Joonsoo Kim Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: UtsavBalar1231 --- include/linux/slab.h | 40 ++++++++++++++++++++-------------------- include/linux/types.h | 2 +- mm/slab.c | 4 ++-- mm/slub.c | 6 +++--- 4 files changed, 26 insertions(+), 26 deletions(-) diff --git a/include/linux/slab.h b/include/linux/slab.h index 6ebed7ac533f..1a211cbbf6b3 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -22,19 +22,19 @@ * The ones marked DEBUG are only valid if CONFIG_DEBUG_SLAB is set. */ /* DEBUG: Perform (expensive) checks on alloc/free */ -#define SLAB_CONSISTENCY_CHECKS ((slab_flags_t __force)0x00000100UL) +#define SLAB_CONSISTENCY_CHECKS ((slab_flags_t __force)0x00000100U) /* DEBUG: Red zone objs in a cache */ -#define SLAB_RED_ZONE ((slab_flags_t __force)0x00000400UL) +#define SLAB_RED_ZONE ((slab_flags_t __force)0x00000400U) /* DEBUG: Poison objects */ -#define SLAB_POISON ((slab_flags_t __force)0x00000800UL) +#define SLAB_POISON ((slab_flags_t __force)0x00000800U) /* Align objs on cache lines */ -#define SLAB_HWCACHE_ALIGN ((slab_flags_t __force)0x00002000UL) +#define SLAB_HWCACHE_ALIGN ((slab_flags_t __force)0x00002000U) /* Use GFP_DMA memory */ -#define SLAB_CACHE_DMA ((slab_flags_t __force)0x00004000UL) +#define SLAB_CACHE_DMA ((slab_flags_t __force)0x00004000U) /* DEBUG: Store the last owner for bug hunting */ -#define SLAB_STORE_USER ((slab_flags_t __force)0x00010000UL) +#define SLAB_STORE_USER ((slab_flags_t __force)0x00010000U) /* Panic if kmem_cache_create() fails */ -#define SLAB_PANIC ((slab_flags_t __force)0x00040000UL) +#define SLAB_PANIC ((slab_flags_t __force)0x00040000U) /* * SLAB_TYPESAFE_BY_RCU - **WARNING** READ THIS! * @@ -73,43 +73,43 @@ * Note that SLAB_TYPESAFE_BY_RCU was originally named SLAB_DESTROY_BY_RCU. */ /* Defer freeing slabs to RCU */ -#define SLAB_TYPESAFE_BY_RCU ((slab_flags_t __force)0x00080000UL) +#define SLAB_TYPESAFE_BY_RCU ((slab_flags_t __force)0x00080000U) /* Spread some memory over cpuset */ -#define SLAB_MEM_SPREAD ((slab_flags_t __force)0x00100000UL) +#define SLAB_MEM_SPREAD ((slab_flags_t __force)0x00100000U) /* Trace allocations and frees */ -#define SLAB_TRACE ((slab_flags_t __force)0x00200000UL) +#define SLAB_TRACE ((slab_flags_t __force)0x00200000U) /* Flag to prevent checks on free */ #ifdef CONFIG_DEBUG_OBJECTS -# define SLAB_DEBUG_OBJECTS ((slab_flags_t __force)0x00400000UL) +# define SLAB_DEBUG_OBJECTS ((slab_flags_t __force)0x00400000U) #else -# define SLAB_DEBUG_OBJECTS ((slab_flags_t __force)0x00000000UL) +# define SLAB_DEBUG_OBJECTS 0 #endif /* Avoid kmemleak tracing */ -#define SLAB_NOLEAKTRACE ((slab_flags_t __force)0x00800000UL) +#define SLAB_NOLEAKTRACE ((slab_flags_t __force)0x00800000U) #ifdef CONFIG_FAILSLAB -# define SLAB_FAILSLAB ((slab_flags_t __force)0x02000000UL) +# define SLAB_FAILSLAB ((slab_flags_t __force)0x02000000U) #else -# define SLAB_FAILSLAB ((slab_flags_t __force)0x00000000UL) +# define SLAB_FAILSLAB 0 #endif /* Account to memcg */ #if defined(CONFIG_MEMCG) && !defined(CONFIG_SLOB) -# define SLAB_ACCOUNT ((slab_flags_t __force)0x04000000UL) +# define SLAB_ACCOUNT ((slab_flags_t __force)0x04000000U) #else -# define SLAB_ACCOUNT ((slab_flags_t __force)0x00000000UL) +# define SLAB_ACCOUNT 0 #endif #ifdef CONFIG_KASAN -#define SLAB_KASAN ((slab_flags_t __force)0x08000000UL) +#define SLAB_KASAN ((slab_flags_t __force)0x08000000U) #else -#define SLAB_KASAN ((slab_flags_t __force)0x00000000UL) +#define SLAB_KASAN 0 #endif /* The following flags affect the page allocator grouping pages by mobility */ /* Objects are reclaimable */ -#define SLAB_RECLAIM_ACCOUNT ((slab_flags_t __force)0x00020000UL) +#define SLAB_RECLAIM_ACCOUNT ((slab_flags_t __force)0x00020000U) #define SLAB_TEMPORARY SLAB_RECLAIM_ACCOUNT /* Objects are short-lived */ /* * ZERO_SIZE_PTR will be returned for zero sized kmalloc requests. diff --git a/include/linux/types.h b/include/linux/types.h index 7fe2d9d600fe..76d929bba9f9 100644 --- a/include/linux/types.h +++ b/include/linux/types.h @@ -160,7 +160,7 @@ typedef u32 dma_addr_t; #endif typedef unsigned __bitwise gfp_t; -typedef unsigned long __bitwise slab_flags_t; +typedef unsigned __bitwise slab_flags_t; typedef unsigned __bitwise fmode_t; #ifdef CONFIG_PHYS_ADDR_T_64BIT diff --git a/mm/slab.c b/mm/slab.c index 417f20f09e1c..678fe5034bbc 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -251,8 +251,8 @@ static void kmem_cache_node_init(struct kmem_cache_node *parent) MAKE_LIST((cachep), (&(ptr)->slabs_free), slabs_free, nodeid); \ } while (0) -#define CFLGS_OBJFREELIST_SLAB ((slab_flags_t __force)0x40000000UL) -#define CFLGS_OFF_SLAB ((slab_flags_t __force)0x80000000UL) +#define CFLGS_OBJFREELIST_SLAB ((slab_flags_t __force)0x40000000U) +#define CFLGS_OFF_SLAB ((slab_flags_t __force)0x80000000U) #define OBJFREELIST_SLAB(x) ((x)->flags & CFLGS_OBJFREELIST_SLAB) #define OFF_SLAB(x) ((x)->flags & CFLGS_OFF_SLAB) diff --git a/mm/slub.c b/mm/slub.c index 04dbe8139650..8ee2e6be7778 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -193,9 +193,9 @@ static inline bool kmem_cache_has_cpu_partial(struct kmem_cache *s) /* Internal SLUB flags */ /* Poison object */ -#define __OBJECT_POISON ((slab_flags_t __force)0x80000000UL) +#define __OBJECT_POISON ((slab_flags_t __force)0x80000000U) /* Use cmpxchg_double */ -#define __CMPXCHG_DOUBLE ((slab_flags_t __force)0x40000000UL) +#define __CMPXCHG_DOUBLE ((slab_flags_t __force)0x40000000U) /* * Tracking user of a slab. @@ -3771,7 +3771,7 @@ error: if (flags & SLAB_PANIC) panic("Cannot create slab %s size=%lu realsize=%u order=%u offset=%u flags=%lx\n", s->name, (unsigned long)s->size, s->size, - oo_order(s->oo), s->offset, flags); + oo_order(s->oo), s->offset, (unsigned long)flags); return -EINVAL; } From d580843e215546497fe90a09da01dbeddb96c9cc Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Wed, 15 Nov 2017 17:32:29 -0800 Subject: [PATCH 557/592] include/linux/slab.h: add kmalloc_array_node() and kcalloc_node() Patch series "Add kmalloc_array_node() and kcalloc_node()". Our current memeory allocation routines suffer form an API imbalance, for one we have kmalloc_array() and kcalloc() which check for overflows in size multiplication and we have kmalloc_node() and kzalloc_node() which allow for memory allocation on a certain NUMA node but don't check for eventual overflows. This patch (of 6): We have kmalloc_array() and kcalloc() wrappers on top of kmalloc() which ensure us overflow free multiplication for the size of a memory allocation but these implementations are not NUMA-aware. Likewise we have kmalloc_node() which is a NUMA-aware version of kmalloc() but the implementation is not aware of any possible overflows in eventual size calculations. Introduce a combination of the two above cases to have a NUMA-node aware version of kmalloc_array() and kcalloc(). Link: http://lkml.kernel.org/r/20170927082038.3782-2-jthumshirn@suse.de Signed-off-by: Johannes Thumshirn Acked-by: Vlastimil Babka Cc: Christoph Hellwig Cc: Christoph Lameter Cc: Damien Le Moal Cc: David Rientjes Cc: "David S. Miller" Cc: Doug Ledford Cc: Hal Rosenstock Cc: Jens Axboe Cc: Joonsoo Kim Cc: Mike Marciniszyn Cc: Pekka Enberg Cc: Santosh Shilimkar Cc: Sean Hefty Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: UtsavBalar1231 --- include/linux/slab.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/include/linux/slab.h b/include/linux/slab.h index 1a211cbbf6b3..87447c74e7b8 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -677,6 +677,22 @@ extern void *__kmalloc_track_caller(size_t, gfp_t, unsigned long); #define kmalloc_track_caller(size, flags) \ __kmalloc_track_caller(size, flags, _RET_IP_) +static inline void *kmalloc_array_node(size_t n, size_t size, gfp_t flags, + int node) +{ + if (size != 0 && n > SIZE_MAX / size) + return NULL; + if (__builtin_constant_p(n) && __builtin_constant_p(size)) + return kmalloc_node(n * size, flags, node); + return __kmalloc_node(n * size, flags, node); +} + +static inline void *kcalloc_node(size_t n, size_t size, gfp_t flags, int node) +{ + return kmalloc_array_node(n, size, flags | __GFP_ZERO, node); +} + + #ifdef CONFIG_NUMA extern void *__kmalloc_node_track_caller(size_t, gfp_t, int, unsigned long); #define kmalloc_node_track_caller(size, flags, node) \ From e53548d5873cb8bf54bea6186959518775bf5dba Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Wed, 15 Nov 2017 17:32:33 -0800 Subject: [PATCH 558/592] block/blk-mq.c: use kmalloc_array_node() Now that we have a NUMA-aware version of kmalloc_array() we can use it instead of kmalloc_node() without an overflow check in the size calculation. Link: http://lkml.kernel.org/r/20170927082038.3782-3-jthumshirn@suse.de Signed-off-by: Johannes Thumshirn Reviewed-by: Christoph Lameter Cc: Pekka Enberg Cc: David Rientjes Cc: Joonsoo Kim Cc: Damien Le Moal Cc: Christoph Hellwig Cc: Jens Axboe Cc: "David S. Miller" Cc: Doug Ledford Cc: Hal Rosenstock Cc: Mike Marciniszyn Cc: Santosh Shilimkar Cc: Sean Hefty Cc: Vlastimil Babka Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: UtsavBalar1231 --- block/blk-mq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block/blk-mq.c b/block/blk-mq.c index cf56bdad2e06..2992376e64c9 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -2021,7 +2021,7 @@ static int blk_mq_init_hctx(struct request_queue *q, * Allocate space for all possible cpus to avoid allocation at * runtime */ - hctx->ctxs = kmalloc_node(nr_cpu_ids * sizeof(void *), + hctx->ctxs = kmalloc_array_node(nr_cpu_ids, sizeof(void *), GFP_KERNEL, node); if (!hctx->ctxs) goto unregister_cpu_notifier; From ae7e37e7de5d5509ebd081bc8a5e0aabe08dd3db Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Wed, 15 Nov 2017 17:32:37 -0800 Subject: [PATCH 559/592] drivers/infiniband/hw/qib/qib_init.c: use kmalloc_array_node() Now that we have a NUMA-aware version of kmalloc_array() we can use it instead of kmalloc_node() without an overflow check in the size calculation. Link: http://lkml.kernel.org/r/20170927082038.3782-4-jthumshirn@suse.de Signed-off-by: Johannes Thumshirn Reviewed-by: Christoph Lameter Cc: Mike Marciniszyn Cc: Doug Ledford Cc: Sean Hefty Cc: Hal Rosenstock Cc: Christoph Hellwig Cc: Damien Le Moal Cc: David Rientjes Cc: "David S. Miller" Cc: Jens Axboe Cc: Joonsoo Kim Cc: Pekka Enberg Cc: Santosh Shilimkar Cc: Vlastimil Babka Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: UtsavBalar1231 --- drivers/infiniband/hw/qib/qib_init.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/hw/qib/qib_init.c b/drivers/infiniband/hw/qib/qib_init.c index 7ba7d2122f3b..3157408c6df2 100644 --- a/drivers/infiniband/hw/qib/qib_init.c +++ b/drivers/infiniband/hw/qib/qib_init.c @@ -1687,8 +1687,9 @@ int qib_setup_eagerbufs(struct qib_ctxtdata *rcd) } if (!rcd->rcvegrbuf_phys) { rcd->rcvegrbuf_phys = - kmalloc_node(chunk * sizeof(rcd->rcvegrbuf_phys[0]), - GFP_KERNEL, rcd->node_id); + kmalloc_array_node(chunk, + sizeof(rcd->rcvegrbuf_phys[0]), + GFP_KERNEL, rcd->node_id); if (!rcd->rcvegrbuf_phys) goto bail_rcvegrbuf; } From 1bcd0782d55a593caa24734267a304bd7b81c09e Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Wed, 15 Nov 2017 17:32:41 -0800 Subject: [PATCH 560/592] drivers/infiniband/sw/rdmavt/qp.c: use kmalloc_array_node() Now that we have a NUMA-aware version of kmalloc_array() we can use it instead of kmalloc_node() without an overflow check in the size calculation. Link: http://lkml.kernel.org/r/20170927082038.3782-5-jthumshirn@suse.de Signed-off-by: Johannes Thumshirn Reviewed-by: Christoph Lameter Cc: Christoph Hellwig Cc: Damien Le Moal Cc: David Rientjes Cc: "David S. Miller" Cc: Doug Ledford Cc: Hal Rosenstock Cc: Jens Axboe Cc: Joonsoo Kim Cc: Mike Marciniszyn Cc: Pekka Enberg Cc: Santosh Shilimkar Cc: Sean Hefty Cc: Vlastimil Babka Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: UtsavBalar1231 --- drivers/infiniband/sw/rdmavt/qp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/sw/rdmavt/qp.c b/drivers/infiniband/sw/rdmavt/qp.c index b0309876f4bb..b13cd11c39ca 100644 --- a/drivers/infiniband/sw/rdmavt/qp.c +++ b/drivers/infiniband/sw/rdmavt/qp.c @@ -238,7 +238,7 @@ int rvt_driver_qp_init(struct rvt_dev_info *rdi) rdi->qp_dev->qp_table_size = rdi->dparms.qp_table_size; rdi->qp_dev->qp_table_bits = ilog2(rdi->dparms.qp_table_size); rdi->qp_dev->qp_table = - kmalloc_node(rdi->qp_dev->qp_table_size * + kmalloc_array_node(rdi->qp_dev->qp_table_size, sizeof(*rdi->qp_dev->qp_table), GFP_KERNEL, rdi->dparms.node); if (!rdi->qp_dev->qp_table) From 8c7640a698b208514bd5fffecaf8d78e59104d52 Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Wed, 15 Nov 2017 17:32:45 -0800 Subject: [PATCH 561/592] mm/mempool.c: use kmalloc_array_node() Now that we have a NUMA-aware version of kmalloc_array() we can use it instead of kmalloc_node() without an overflow check in the size calculation. Link: http://lkml.kernel.org/r/20170927082038.3782-6-jthumshirn@suse.de Signed-off-by: Johannes Thumshirn Reviewed-by: Christoph Lameter Cc: Christoph Hellwig Cc: Damien Le Moal Cc: David Rientjes Cc: "David S. Miller" Cc: Doug Ledford Cc: Hal Rosenstock Cc: Jens Axboe Cc: Joonsoo Kim Cc: Mike Marciniszyn Cc: Pekka Enberg Cc: Santosh Shilimkar Cc: Sean Hefty Cc: Vlastimil Babka Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: UtsavBalar1231 --- mm/mempool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/mempool.c b/mm/mempool.c index 6fb1c0bd2870..3076ab3f7bc4 100644 --- a/mm/mempool.c +++ b/mm/mempool.c @@ -189,7 +189,7 @@ mempool_t *mempool_create_node(int min_nr, mempool_alloc_t *alloc_fn, pool = kzalloc_node(sizeof(*pool), gfp_mask, node_id); if (!pool) return NULL; - pool->elements = kmalloc_node(min_nr * sizeof(void *), + pool->elements = kmalloc_array_node(min_nr, sizeof(void *), gfp_mask, node_id); if (!pool->elements) { kfree(pool); From acabc96714797d7447b0621a32f173b5e76807dd Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Wed, 15 Nov 2017 17:32:49 -0800 Subject: [PATCH 562/592] net/rds/ib_fmr.c: use kmalloc_array_node() Now that we have a NUMA-aware version of kmalloc_array() we can use it instead of kmalloc_node() without an overflow check in the size calculation. Link: http://lkml.kernel.org/r/20170927082038.3782-7-jthumshirn@suse.de Signed-off-by: Johannes Thumshirn Reviewed-by: Christoph Lameter Cc: Santosh Shilimkar Cc: "David S. Miller" Cc: Christoph Hellwig Cc: Damien Le Moal Cc: David Rientjes Cc: Doug Ledford Cc: Hal Rosenstock Cc: Jens Axboe Cc: Joonsoo Kim Cc: Mike Marciniszyn Cc: Pekka Enberg Cc: Sean Hefty Cc: Vlastimil Babka Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: UtsavBalar1231 --- net/rds/ib_fmr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/rds/ib_fmr.c b/net/rds/ib_fmr.c index 353b59d3bd44..01e764f8f224 100644 --- a/net/rds/ib_fmr.c +++ b/net/rds/ib_fmr.c @@ -150,8 +150,8 @@ static int rds_ib_map_fmr(struct rds_ib_device *rds_ibdev, return -EINVAL; } - dma_pages = kmalloc_node(sizeof(u64) * page_cnt, GFP_ATOMIC, - rdsibdev_to_node(rds_ibdev)); + dma_pages = kmalloc_array_node(sizeof(u64), page_cnt, GFP_ATOMIC, + rdsibdev_to_node(rds_ibdev)); if (!dma_pages) { ib_dma_unmap_sg(dev, sg, nents, DMA_BIDIRECTIONAL); return -ENOMEM; From e5a2dbf9a11d8e2216b40db1f7ba1ca2f97e80cc Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Thu, 5 Apr 2018 16:20:22 -0700 Subject: [PATCH 563/592] slab: make kmalloc_index() return "unsigned int" kmalloc_index() return index into an array of kmalloc kmem caches, therefore should be unsigned. Space savings with SLUB on trimmed down .config: add/remove: 0/1 grow/shrink: 6/56 up/down: 85/-557 (-472) Function old new delta calculate_sizes 924 983 +59 on_freelist 589 604 +15 init_cache_random_seq 122 127 +5 ext4_mb_init 1206 1210 +4 slab_pad_check.part 270 271 +1 cpu_partial_store 112 113 +1 usersize_show 28 27 -1 ... new_slab 1871 1837 -34 slab_order 204 - -204 This patch start a series of converting SLUB (mostly) to "unsigned int". 1) Most integers in the code are in fact unsigned entities: array indexes, lengths, buffer sizes, allocation orders. It is therefore better to use unsigned variables 2) Some integers in the code are either "size_t" or "unsigned long" for no reason. size_t usually comes from people trying to maintain type correctness and figuring out that "sizeof" operator returns size_t or memset/memcpy takes size_t so should everything passed to it. However the number of 4GB+ objects in the kernel is very small. Most, if not all, dynamically allocated objects with kmalloc() or kmem_cache_create() aren't actually big. Maintaining wide types doesn't do anything. 64-bit ops are bigger than 32-bit on our beloved x86_64, so try to not use 64-bit where it isn't necessary (read: everywhere where integers are integers not pointers) 3) in case of SLAB allocators, there are additional limitations *) page->inuse, page->objects are only 16-/15-bit, *) cache size was always 32-bit *) slab orders are small, order 20 is needed to go 64-bit on x86_64 (PAGE_SIZE << order) Basically everything is 32-bit except kmalloc(1ULL<<32) which gets shortcut through page allocator. Christoph said: : : That changes with large base page size on power and ARM64 f.e. but then : we do not want to encourage larger allocations through slab anyways. Link: http://lkml.kernel.org/r/20180305200730.15812-2-adobriyan@gmail.com Signed-off-by: Alexey Dobriyan Acked-by: Christoph Lameter Cc: Pekka Enberg Cc: David Rientjes Cc: Joonsoo Kim Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds [UtsavBalar1231: port to 4.14] Signed-off-by: UtsavBalar1231 --- include/linux/slab.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/slab.h b/include/linux/slab.h index 87447c74e7b8..13b2a9bdf6a3 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -325,7 +325,7 @@ static __always_inline enum kmalloc_cache_type kmalloc_type(gfp_t flags) * 2 = 129 .. 192 bytes * n = 2^(n-1)+1 .. 2^n */ -static __always_inline int kmalloc_index(size_t size) +static __always_inline unsigned int kmalloc_index(size_t size) { if (!size) return 0; @@ -564,7 +564,7 @@ static __always_inline void *kmalloc_node(size_t size, gfp_t flags, int node) #ifndef CONFIG_SLOB if (__builtin_constant_p(size) && size <= KMALLOC_MAX_CACHE_SIZE) { - int i = kmalloc_index(size); + unsigned int i = kmalloc_index(size); if (!i) return ZERO_SIZE_PTR; From e455d264c9089b6f77f650b2a8be8ba48db53e7e Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Thu, 5 Apr 2018 16:20:26 -0700 Subject: [PATCH 564/592] slab: make kmalloc_size() return "unsigned int" kmalloc_size() derives size of kmalloc cache from internal index, which can't be negative. Propagate unsignedness a bit. Link: http://lkml.kernel.org/r/20180305200730.15812-3-adobriyan@gmail.com Signed-off-by: Alexey Dobriyan Acked-by: Christoph Lameter Cc: Pekka Enberg Cc: David Rientjes Cc: Joonsoo Kim Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: UtsavBalar1231 --- include/linux/slab.h | 4 ++-- mm/slab_common.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/linux/slab.h b/include/linux/slab.h index 13b2a9bdf6a3..aabc10b14e4c 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -544,11 +544,11 @@ static __always_inline void *kmalloc(size_t size, gfp_t flags) * return size or 0 if a kmalloc cache for that * size does not exist */ -static __always_inline int kmalloc_size(int n) +static __always_inline unsigned int kmalloc_size(unsigned int n) { #ifndef CONFIG_SLOB if (n > 2) - return 1 << n; + return 1U << n; if (n == 1 && KMALLOC_MIN_SIZE <= 32) return 96; diff --git a/mm/slab_common.c b/mm/slab_common.c index cdcbcd6238ab..8354bc72a669 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c @@ -1121,7 +1121,7 @@ void __init create_kmalloc_caches(slab_flags_t flags) struct kmem_cache *s = kmalloc_caches[KMALLOC_NORMAL][i]; if (s) { - int size = kmalloc_size(i); + unsigned int size = kmalloc_size(i); const char *n = kmalloc_cache_name("dma-kmalloc", size); BUG_ON(!n); From 338b074f139c74701a8c10a6ba213575ed20020b Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 8 May 2018 12:52:32 -0700 Subject: [PATCH 565/592] mm: Use overflow helpers in kmalloc_array*() Instead of open-coded multiplication and bounds checking, use the new overflow helper. Suggested-by: Rasmus Villemoes Signed-off-by: Kees Cook Signed-off-by: UtsavBalar1231 --- include/linux/slab.h | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/include/linux/slab.h b/include/linux/slab.h index aabc10b14e4c..a9376a897ae2 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -13,6 +13,7 @@ #define _LINUX_SLAB_H #include +#include #include #include @@ -647,11 +648,13 @@ int memcg_update_all_caches(int num_memcgs); */ static inline void *kmalloc_array(size_t n, size_t size, gfp_t flags) { - if (size != 0 && n > SIZE_MAX / size) + size_t bytes; + + if (unlikely(check_mul_overflow(n, size, &bytes))) return NULL; if (__builtin_constant_p(n) && __builtin_constant_p(size)) - return kmalloc(n * size, flags); - return __kmalloc(n * size, flags); + return kmalloc(bytes, flags); + return __kmalloc(bytes, flags); } /** @@ -680,11 +683,13 @@ extern void *__kmalloc_track_caller(size_t, gfp_t, unsigned long); static inline void *kmalloc_array_node(size_t n, size_t size, gfp_t flags, int node) { - if (size != 0 && n > SIZE_MAX / size) + size_t bytes; + + if (unlikely(check_mul_overflow(n, size, &bytes))) return NULL; if (__builtin_constant_p(n) && __builtin_constant_p(size)) - return kmalloc_node(n * size, flags, node); - return __kmalloc_node(n * size, flags, node); + return kmalloc_node(bytes, flags, node); + return __kmalloc_node(bytes, flags, node); } static inline void *kcalloc_node(size_t n, size_t size, gfp_t flags, int node) From 82820874db44ec028b8f02eef1ba533588052f25 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 8 May 2018 12:55:26 -0700 Subject: [PATCH 566/592] mm: Use overflow helpers in kvmalloc() Instead of open-coded multiplication and bounds checking, use the new overflow helper. Additionally prepare for vmalloc() users to add array_size()-family helpers in the future. Signed-off-by: Kees Cook Signed-off-by: UtsavBalar1231 --- include/linux/mm.h | 7 +++++-- include/linux/vmalloc.h | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index 1cb2dee564a5..1cea7a72f4cc 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -25,6 +25,7 @@ #include #include #include +#include struct mempolicy; struct anon_vma; @@ -565,10 +566,12 @@ static inline void *kvzalloc(size_t size, gfp_t flags) static inline void *kvmalloc_array(size_t n, size_t size, gfp_t flags) { - if (size != 0 && n > SIZE_MAX / size) + size_t bytes; + + if (unlikely(check_mul_overflow(n, size, &bytes))) return NULL; - return kvmalloc(n * size, flags); + return kvmalloc(bytes, flags); } static inline void *kvcalloc(size_t n, size_t size, gfp_t flags) diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h index 266b2f3e5ac4..861531cb0b19 100644 --- a/include/linux/vmalloc.h +++ b/include/linux/vmalloc.h @@ -8,6 +8,7 @@ #include #include /* pgprot_t */ #include +#include struct vm_area_struct; /* vma defining user mapping in mm_types.h */ struct notifier_block; /* in notifier.h */ From 39d90bf16b65c551bdb6a36fa9e5a781aaa6b1fe Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 8 May 2018 22:29:52 -0700 Subject: [PATCH 567/592] device: Use overflow helpers for devm_kmalloc() Use the overflow helpers both in existing multiplication-using inlines as well as the addition-overflow case in the core allocation routine. Signed-off-by: Kees Cook Signed-off-by: UtsavBalar1231 --- drivers/base/devres.c | 7 ++++++- include/linux/device.h | 8 ++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/base/devres.c b/drivers/base/devres.c index e43a04a495a3..9b495725da13 100644 --- a/drivers/base/devres.c +++ b/drivers/base/devres.c @@ -91,9 +91,14 @@ static struct devres_group * node_to_group(struct devres_node *node) static __always_inline struct devres * alloc_dr(dr_release_t release, size_t size, gfp_t gfp, int nid) { - size_t tot_size = sizeof(struct devres) + size; + size_t tot_size; struct devres *dr; + /* We must catch any near-SIZE_MAX cases that could overflow. */ + if (unlikely(check_add_overflow(sizeof(struct devres), size, + &tot_size))) + return NULL; + dr = kmalloc_node_track_caller(tot_size, gfp, nid); if (unlikely(!dr)) return NULL; diff --git a/include/linux/device.h b/include/linux/device.h index b52773b0598d..b53d063c0cdf 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -27,6 +27,7 @@ #include #include #include +#include #include struct device; @@ -666,9 +667,12 @@ static inline void *devm_kzalloc(struct device *dev, size_t size, gfp_t gfp) static inline void *devm_kmalloc_array(struct device *dev, size_t n, size_t size, gfp_t flags) { - if (size != 0 && n > SIZE_MAX / size) + size_t bytes; + + if (unlikely(check_mul_overflow(n, size, &bytes))) return NULL; - return devm_kmalloc(dev, n * size, flags); + + return devm_kmalloc(dev, bytes, flags); } static inline void *devm_kcalloc(struct device *dev, size_t n, size_t size, gfp_t flags) From 1d51bfe37704d929ec803ccc9fa7df4457fe1f51 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 7 Jun 2018 07:57:15 -0700 Subject: [PATCH 568/592] UPSTREAM: Convert virtio_console to struct_size Signed-off-by: Matthew Wilcox Signed-off-by: Kees Cook (cherry picked from commit 5b572e25c3649235969e4ada67cde27b5bb24979) Signed-off-by: Nathan Chancellor Signed-off-by: Adam W. Willis Signed-off-by: UtsavBalar1231 --- drivers/char/virtio_console.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 6a57237e46db..6f0104d7c7a5 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -433,8 +433,7 @@ static struct port_buffer *alloc_buf(struct virtio_device *vdev, size_t buf_size * Allocate buffer and the sg list. The sg list array is allocated * directly after the port_buffer struct. */ - buf = kmalloc(sizeof(*buf) + sizeof(struct scatterlist) * pages, - GFP_KERNEL); + buf = kmalloc(struct_size(buf, sg, pages), GFP_KERNEL); if (!buf) goto fail; From ed930ccbb1e4a6dd1fdf5d44865a4d72d011a8b4 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 7 Jun 2018 07:57:17 -0700 Subject: [PATCH 569/592] UPSTREAM: Convert v4l2 event to struct_size Signed-off-by: Matthew Wilcox Signed-off-by: Kees Cook (cherry picked from commit c817e6ccb2c36b8f564209d474bc6c8308c498e2) Signed-off-by: Nathan Chancellor Signed-off-by: Adam W. Willis Signed-off-by: UtsavBalar1231 --- drivers/media/v4l2-core/v4l2-event.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-event.c b/drivers/media/v4l2-core/v4l2-event.c index 011907eff660..481e3c65cf97 100644 --- a/drivers/media/v4l2-core/v4l2-event.c +++ b/drivers/media/v4l2-core/v4l2-event.c @@ -224,8 +224,7 @@ int v4l2_event_subscribe(struct v4l2_fh *fh, if (elems < 1) elems = 1; - sev = kvzalloc(sizeof(*sev) + sizeof(struct v4l2_kevent) * elems, - GFP_KERNEL); + sev = kvzalloc(struct_size(sev, events, elems), GFP_KERNEL); if (!sev) return -ENOMEM; for (i = 0; i < elems; i++) From 0f37f111de0df6c46b7ec6d7ded6f6873b2a25d5 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 8 May 2018 13:45:50 -0700 Subject: [PATCH 570/592] treewide: Use struct_size() for kmalloc()-family One of the more common cases of allocation size calculations is finding the size of a structure that has a zero-sized array at the end, along with memory for some number of elements for that array. For example: struct foo { int stuff; void *entry[]; }; instance = kmalloc(sizeof(struct foo) + sizeof(void *) * count, GFP_KERNEL); Instead of leaving these open-coded and prone to type mistakes, we can now use the new struct_size() helper: instance = kmalloc(struct_size(instance, entry, count), GFP_KERNEL); This patch makes the changes for kmalloc()-family (and kvmalloc()-family) uses. It was done via automatic conversion with manual review for the "CHECKME" non-standard cases noted below, using the following Coccinelle script: // pkey_cache = kmalloc(sizeof *pkey_cache + tprops->pkey_tbl_len * // sizeof *pkey_cache->table, GFP_KERNEL); @@ identifier alloc =~ "kmalloc|kzalloc|kvmalloc|kvzalloc"; expression GFP; identifier VAR, ELEMENT; expression COUNT; @@ - alloc(sizeof(*VAR) + COUNT * sizeof(*VAR->ELEMENT), GFP) + alloc(struct_size(VAR, ELEMENT, COUNT), GFP) // mr = kzalloc(sizeof(*mr) + m * sizeof(mr->map[0]), GFP_KERNEL); @@ identifier alloc =~ "kmalloc|kzalloc|kvmalloc|kvzalloc"; expression GFP; identifier VAR, ELEMENT; expression COUNT; @@ - alloc(sizeof(*VAR) + COUNT * sizeof(VAR->ELEMENT[0]), GFP) + alloc(struct_size(VAR, ELEMENT, COUNT), GFP) // Same pattern, but can't trivially locate the trailing element name, // or variable name. @@ identifier alloc =~ "kmalloc|kzalloc|kvmalloc|kvzalloc"; expression GFP; expression SOMETHING, COUNT, ELEMENT; @@ - alloc(sizeof(SOMETHING) + COUNT * sizeof(ELEMENT), GFP) + alloc(CHECKME_struct_size(&SOMETHING, ELEMENT, COUNT), GFP) Signed-off-by: Kees Cook Signed-off-by: Adam W. Willis Signed-off-by: UtsavBalar1231 --- drivers/clk/berlin/bg2.c | 3 +-- drivers/clk/berlin/bg2q.c | 3 +-- drivers/clk/clk-asm9260.c | 3 +-- drivers/clk/clk-efm32gg.c | 4 ++-- drivers/clk/clk-gemini.c | 5 ++--- drivers/clk/clk-stm32h7.c | 5 ++--- drivers/cpufreq/cpufreq_times.c | 3 +-- drivers/dma/edma.c | 9 +++------ drivers/dma/moxart-dma.c | 2 +- drivers/dma/omap-dma.c | 2 +- drivers/dma/sa11x0-dma.c | 4 ++-- drivers/dma/sh/usb-dmac.c | 2 +- drivers/firewire/core-topology.c | 3 +-- drivers/gpio/gpiolib.c | 3 +-- drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c | 4 ++-- drivers/infiniband/core/cache.c | 8 ++++---- drivers/infiniband/core/uverbs_ioctl_merge.c | 17 ++++++----------- drivers/infiniband/hw/mthca/mthca_memfree.c | 4 ++-- drivers/input/input-leds.c | 3 +-- drivers/input/input-mt.c | 2 +- drivers/input/misc/gpio_input.c | 4 ++-- drivers/input/misc/gpio_matrix.c | 4 ++-- drivers/md/dm-raid.c | 2 +- drivers/misc/vexpress-syscfg.c | 3 +-- .../net/ethernet/mellanox/mlx5/core/debugfs.c | 2 +- .../net/ethernet/mellanox/mlx5/core/fs_core.c | 3 +-- .../net/wireless/intel/iwlwifi/mvm/mac80211.c | 4 +--- drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 4 +--- drivers/reset/core.c | 3 +-- drivers/s390/cio/ccwgroup.c | 3 +-- drivers/usb/gadget/function/f_midi.c | 5 ++--- drivers/zorro/zorro.c | 3 +-- kernel/cgroup/cgroup.c | 4 ++-- kernel/module.c | 3 +-- kernel/workqueue.c | 3 +-- net/ceph/mon_client.c | 2 +- net/ceph/osd_client.c | 3 +-- net/netfilter/xt_recent.c | 3 +-- 38 files changed, 58 insertions(+), 89 deletions(-) diff --git a/drivers/clk/berlin/bg2.c b/drivers/clk/berlin/bg2.c index e7331ace0337..45fb888bf0a0 100644 --- a/drivers/clk/berlin/bg2.c +++ b/drivers/clk/berlin/bg2.c @@ -509,8 +509,7 @@ static void __init berlin2_clock_setup(struct device_node *np) u8 avpll_flags = 0; int n, ret; - clk_data = kzalloc(sizeof(*clk_data) + - sizeof(*clk_data->hws) * MAX_CLKS, GFP_KERNEL); + clk_data = kzalloc(struct_size(clk_data, hws, MAX_CLKS), GFP_KERNEL); if (!clk_data) return; clk_data->num = MAX_CLKS; diff --git a/drivers/clk/berlin/bg2q.c b/drivers/clk/berlin/bg2q.c index 67c270b143f7..db7364e15c8b 100644 --- a/drivers/clk/berlin/bg2q.c +++ b/drivers/clk/berlin/bg2q.c @@ -295,8 +295,7 @@ static void __init berlin2q_clock_setup(struct device_node *np) struct clk_hw **hws; int n, ret; - clk_data = kzalloc(sizeof(*clk_data) + - sizeof(*clk_data->hws) * MAX_CLKS, GFP_KERNEL); + clk_data = kzalloc(struct_size(clk_data, hws, MAX_CLKS), GFP_KERNEL); if (!clk_data) return; clk_data->num = MAX_CLKS; diff --git a/drivers/clk/clk-asm9260.c b/drivers/clk/clk-asm9260.c index bf0582cbbf38..44b544157121 100644 --- a/drivers/clk/clk-asm9260.c +++ b/drivers/clk/clk-asm9260.c @@ -273,8 +273,7 @@ static void __init asm9260_acc_init(struct device_node *np) int n; u32 accuracy = 0; - clk_data = kzalloc(sizeof(*clk_data) + - sizeof(*clk_data->hws) * MAX_CLKS, GFP_KERNEL); + clk_data = kzalloc(struct_size(clk_data, hws, MAX_CLKS), GFP_KERNEL); if (!clk_data) return; clk_data->num = MAX_CLKS; diff --git a/drivers/clk/clk-efm32gg.c b/drivers/clk/clk-efm32gg.c index f674778fb3ac..f37cf08ff7aa 100644 --- a/drivers/clk/clk-efm32gg.c +++ b/drivers/clk/clk-efm32gg.c @@ -25,8 +25,8 @@ static void __init efm32gg_cmu_init(struct device_node *np) void __iomem *base; struct clk_hw **hws; - clk_data = kzalloc(sizeof(*clk_data) + - sizeof(*clk_data->hws) * CMU_MAX_CLKS, GFP_KERNEL); + clk_data = kzalloc(struct_size(clk_data, hws, CMU_MAX_CLKS), + GFP_KERNEL); if (!clk_data) return; diff --git a/drivers/clk/clk-gemini.c b/drivers/clk/clk-gemini.c index 5e66e6c0205e..5f044063f410 100644 --- a/drivers/clk/clk-gemini.c +++ b/drivers/clk/clk-gemini.c @@ -399,9 +399,8 @@ static void __init gemini_cc_init(struct device_node *np) int ret; int i; - gemini_clk_data = kzalloc(sizeof(*gemini_clk_data) + - sizeof(*gemini_clk_data->hws) * GEMINI_NUM_CLKS, - GFP_KERNEL); + gemini_clk_data = kzalloc(struct_size(gemini_clk_data, hws, GEMINI_NUM_CLKS), + GFP_KERNEL); if (!gemini_clk_data) return; diff --git a/drivers/clk/clk-stm32h7.c b/drivers/clk/clk-stm32h7.c index 61c3e40507d3..61d327836c34 100644 --- a/drivers/clk/clk-stm32h7.c +++ b/drivers/clk/clk-stm32h7.c @@ -1214,9 +1214,8 @@ static void __init stm32h7_rcc_init(struct device_node *np) const char *hse_clk, *lse_clk, *i2s_clk; struct regmap *pdrm; - clk_data = kzalloc(sizeof(*clk_data) + - sizeof(*clk_data->hws) * STM32H7_MAX_CLKS, - GFP_KERNEL); + clk_data = kzalloc(struct_size(clk_data, hws, STM32H7_MAX_CLKS), + GFP_KERNEL); if (!clk_data) return; diff --git a/drivers/cpufreq/cpufreq_times.c b/drivers/cpufreq/cpufreq_times.c index d5f95a4edc1b..735900c3a1e5 100644 --- a/drivers/cpufreq/cpufreq_times.c +++ b/drivers/cpufreq/cpufreq_times.c @@ -489,8 +489,7 @@ void cpufreq_times_create_policy(struct cpufreq_policy *policy) cpufreq_for_each_valid_entry(pos, table) count++; - tmp = kzalloc(sizeof(*freqs) + sizeof(freqs->freq_table[0]) * count, - GFP_KERNEL); + tmp = kzalloc(struct_size(freqs, freq_table, count), GFP_KERNEL); if (!tmp) return; diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c index 57a49fe713fd..d4e60ac2f7e0 100644 --- a/drivers/dma/edma.c +++ b/drivers/dma/edma.c @@ -1073,8 +1073,7 @@ static struct dma_async_tx_descriptor *edma_prep_slave_sg( return NULL; } - edesc = kzalloc(sizeof(*edesc) + sg_len * sizeof(edesc->pset[0]), - GFP_ATOMIC); + edesc = kzalloc(struct_size(edesc, pset, sg_len), GFP_ATOMIC); if (!edesc) return NULL; @@ -1191,8 +1190,7 @@ static struct dma_async_tx_descriptor *edma_prep_dma_memcpy( nslots = 2; } - edesc = kzalloc(sizeof(*edesc) + nslots * sizeof(edesc->pset[0]), - GFP_ATOMIC); + edesc = kzalloc(struct_size(edesc, pset, nslots), GFP_ATOMIC); if (!edesc) return NULL; @@ -1314,8 +1312,7 @@ static struct dma_async_tx_descriptor *edma_prep_dma_cyclic( } } - edesc = kzalloc(sizeof(*edesc) + nslots * sizeof(edesc->pset[0]), - GFP_ATOMIC); + edesc = kzalloc(struct_size(edesc, pset, nslots), GFP_ATOMIC); if (!edesc) return NULL; diff --git a/drivers/dma/moxart-dma.c b/drivers/dma/moxart-dma.c index e1a5c2242f6f..e04499c1f27f 100644 --- a/drivers/dma/moxart-dma.c +++ b/drivers/dma/moxart-dma.c @@ -309,7 +309,7 @@ static struct dma_async_tx_descriptor *moxart_prep_slave_sg( return NULL; } - d = kzalloc(sizeof(*d) + sg_len * sizeof(d->sg[0]), GFP_ATOMIC); + d = kzalloc(struct_size(d, sg, sg_len), GFP_ATOMIC); if (!d) return NULL; diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index 14b560facf77..8297ff7a7e27 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -917,7 +917,7 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( } /* Now allocate and setup the descriptor. */ - d = kzalloc(sizeof(*d) + sglen * sizeof(d->sg[0]), GFP_ATOMIC); + d = kzalloc(struct_size(d, sg, sglen), GFP_ATOMIC); if (!d) return NULL; diff --git a/drivers/dma/sa11x0-dma.c b/drivers/dma/sa11x0-dma.c index 1adeb3265085..0137d5316571 100644 --- a/drivers/dma/sa11x0-dma.c +++ b/drivers/dma/sa11x0-dma.c @@ -557,7 +557,7 @@ static struct dma_async_tx_descriptor *sa11x0_dma_prep_slave_sg( } } - txd = kzalloc(sizeof(*txd) + j * sizeof(txd->sg[0]), GFP_ATOMIC); + txd = kzalloc(struct_size(txd, sg, j), GFP_ATOMIC); if (!txd) { dev_dbg(chan->device->dev, "vchan %p: kzalloc failed\n", &c->vc); return NULL; @@ -627,7 +627,7 @@ static struct dma_async_tx_descriptor *sa11x0_dma_prep_dma_cyclic( if (sglen == 0) return NULL; - txd = kzalloc(sizeof(*txd) + sglen * sizeof(txd->sg[0]), GFP_ATOMIC); + txd = kzalloc(struct_size(txd, sg, sglen), GFP_ATOMIC); if (!txd) { dev_dbg(chan->device->dev, "vchan %p: kzalloc failed\n", &c->vc); return NULL; diff --git a/drivers/dma/sh/usb-dmac.c b/drivers/dma/sh/usb-dmac.c index 31a145154e9f..1bb1a8e09025 100644 --- a/drivers/dma/sh/usb-dmac.c +++ b/drivers/dma/sh/usb-dmac.c @@ -269,7 +269,7 @@ static int usb_dmac_desc_alloc(struct usb_dmac_chan *chan, unsigned int sg_len, struct usb_dmac_desc *desc; unsigned long flags; - desc = kzalloc(sizeof(*desc) + sg_len * sizeof(desc->sg[0]), gfp); + desc = kzalloc(struct_size(desc, sg, sg_len), gfp); if (!desc) return -ENOMEM; diff --git a/drivers/firewire/core-topology.c b/drivers/firewire/core-topology.c index 939d259ddf19..7db234d3fbdd 100644 --- a/drivers/firewire/core-topology.c +++ b/drivers/firewire/core-topology.c @@ -112,8 +112,7 @@ static struct fw_node *fw_node_create(u32 sid, int port_count, int color) { struct fw_node *node; - node = kzalloc(sizeof(*node) + port_count * sizeof(node->ports[0]), - GFP_ATOMIC); + node = kzalloc(struct_size(node, ports, port_count), GFP_ATOMIC); if (node == NULL) return NULL; diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index d5b42cc86d71..fdf39dcf6e95 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -3579,8 +3579,7 @@ struct gpio_descs *__must_check gpiod_get_array(struct device *dev, if (count < 0) return ERR_PTR(count); - descs = kzalloc(sizeof(*descs) + sizeof(descs->desc[0]) * count, - GFP_KERNEL); + descs = kzalloc(struct_size(descs, desc, count), GFP_KERNEL); if (!descs) return ERR_PTR(-ENOMEM); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c index dde89a4a0f5b..be89ad80b0f5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c @@ -779,8 +779,8 @@ nvkm_perfdom_new(struct nvkm_pm *pm, const char *name, u32 mask, sdom = spec; while (sdom->signal_nr) { - dom = kzalloc(sizeof(*dom) + sdom->signal_nr * - sizeof(*dom->signal), GFP_KERNEL); + dom = kzalloc(struct_size(dom, signal, sdom->signal_nr), + GFP_KERNEL); if (!dom) return -ENOMEM; diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c index 896cfd9303b0..7a32af7fee30 100644 --- a/drivers/infiniband/core/cache.c +++ b/drivers/infiniband/core/cache.c @@ -1074,16 +1074,16 @@ static void ib_cache_update(struct ib_device *device, goto err; } - pkey_cache = kmalloc(sizeof *pkey_cache + tprops->pkey_tbl_len * - sizeof *pkey_cache->table, GFP_KERNEL); + pkey_cache = kmalloc(struct_size(pkey_cache, table, tprops->pkey_tbl_len), + GFP_KERNEL); if (!pkey_cache) goto err; pkey_cache->table_len = tprops->pkey_tbl_len; if (!use_roce_gid_table) { - gid_cache = kmalloc(sizeof(*gid_cache) + tprops->gid_tbl_len * - sizeof(*gid_cache->table), GFP_KERNEL); + gid_cache = kmalloc(struct_size(gid_cache, table, tprops->gid_tbl_len), + GFP_KERNEL); if (!gid_cache) goto err; diff --git a/drivers/infiniband/core/uverbs_ioctl_merge.c b/drivers/infiniband/core/uverbs_ioctl_merge.c index 48a99dce976c..a73ae212f63d 100644 --- a/drivers/infiniband/core/uverbs_ioctl_merge.c +++ b/drivers/infiniband/core/uverbs_ioctl_merge.c @@ -297,8 +297,7 @@ static struct uverbs_method_spec *build_method_with_attrs(const struct uverbs_me if (max_attr_buckets >= 0) num_attr_buckets = max_attr_buckets + 1; - method = kzalloc(sizeof(*method) + - num_attr_buckets * sizeof(*method->attr_buckets), + method = kzalloc(struct_size(method, attr_buckets, num_attr_buckets), GFP_KERNEL); if (!method) return ERR_PTR(-ENOMEM); @@ -446,9 +445,8 @@ static struct uverbs_object_spec *build_object_with_methods(const struct uverbs_ if (max_method_buckets >= 0) num_method_buckets = max_method_buckets + 1; - object = kzalloc(sizeof(*object) + - num_method_buckets * - sizeof(*object->method_buckets), GFP_KERNEL); + object = kzalloc(struct_size(object, method_buckets, num_method_buckets), + GFP_KERNEL); if (!object) return ERR_PTR(-ENOMEM); @@ -469,8 +467,7 @@ static struct uverbs_object_spec *build_object_with_methods(const struct uverbs_ if (methods_max_bucket < 0) continue; - hash = kzalloc(sizeof(*hash) + - sizeof(*hash->methods) * (methods_max_bucket + 1), + hash = kzalloc(struct_size(hash, methods, (methods_max_bucket + 1)), GFP_KERNEL); if (!hash) { res = -ENOMEM; @@ -579,8 +576,7 @@ struct uverbs_root_spec *uverbs_alloc_spec_tree(unsigned int num_trees, if (max_object_buckets >= 0) num_objects_buckets = max_object_buckets + 1; - root_spec = kzalloc(sizeof(*root_spec) + - num_objects_buckets * sizeof(*root_spec->object_buckets), + root_spec = kzalloc(struct_size(root_spec, object_buckets, num_objects_buckets), GFP_KERNEL); if (!root_spec) return ERR_PTR(-ENOMEM); @@ -603,8 +599,7 @@ struct uverbs_root_spec *uverbs_alloc_spec_tree(unsigned int num_trees, if (objects_max_bucket < 0) continue; - hash = kzalloc(sizeof(*hash) + - sizeof(*hash->objects) * (objects_max_bucket + 1), + hash = kzalloc(struct_size(hash, objects, (objects_max_bucket + 1)), GFP_KERNEL); if (!hash) { res = -ENOMEM; diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.c b/drivers/infiniband/hw/mthca/mthca_memfree.c index c6fe89d79248..553ccbf59593 100644 --- a/drivers/infiniband/hw/mthca/mthca_memfree.c +++ b/drivers/infiniband/hw/mthca/mthca_memfree.c @@ -367,7 +367,7 @@ struct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev, obj_per_chunk = MTHCA_TABLE_CHUNK_SIZE / obj_size; num_icm = DIV_ROUND_UP(nobj, obj_per_chunk); - table = kmalloc(sizeof *table + num_icm * sizeof *table->icm, GFP_KERNEL); + table = kmalloc(struct_size(table, icm, num_icm), GFP_KERNEL); if (!table) return NULL; @@ -529,7 +529,7 @@ struct mthca_user_db_table *mthca_init_user_db_tab(struct mthca_dev *dev) return NULL; npages = dev->uar_table.uarc_size / MTHCA_ICM_PAGE_SIZE; - db_tab = kmalloc(sizeof *db_tab + npages * sizeof *db_tab->page, GFP_KERNEL); + db_tab = kmalloc(struct_size(db_tab, page, npages), GFP_KERNEL); if (!db_tab) return ERR_PTR(-ENOMEM); diff --git a/drivers/input/input-leds.c b/drivers/input/input-leds.c index 5f04b2d94635..99cc784e1264 100644 --- a/drivers/input/input-leds.c +++ b/drivers/input/input-leds.c @@ -98,8 +98,7 @@ static int input_leds_connect(struct input_handler *handler, if (!num_leds) return -ENXIO; - leds = kzalloc(sizeof(*leds) + num_leds * sizeof(*leds->leds), - GFP_KERNEL); + leds = kzalloc(struct_size(leds, leds, num_leds), GFP_KERNEL); if (!leds) return -ENOMEM; diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c index a1bbec9cda8d..cf30523c6ef6 100644 --- a/drivers/input/input-mt.c +++ b/drivers/input/input-mt.c @@ -49,7 +49,7 @@ int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots, if (mt) return mt->num_slots != num_slots ? -EINVAL : 0; - mt = kzalloc(sizeof(*mt) + num_slots * sizeof(*mt->slots), GFP_KERNEL); + mt = kzalloc(struct_size(mt, slots, num_slots), GFP_KERNEL); if (!mt) goto err_mem; diff --git a/drivers/input/misc/gpio_input.c b/drivers/input/misc/gpio_input.c index dc266cb9f8fd..94c58e0cf5c7 100644 --- a/drivers/input/misc/gpio_input.c +++ b/drivers/input/misc/gpio_input.c @@ -287,8 +287,8 @@ int gpio_event_input_func(struct gpio_event_input_devs *input_devs, if (ktime_to_ns(di->poll_time) <= 0) di->poll_time = ktime_set(0, 20 * NSEC_PER_MSEC); - *data = ds = kzalloc(sizeof(*ds) + sizeof(ds->key_state[0]) * - di->keymap_size, GFP_KERNEL); + *data = ds = kzalloc(struct_size(ds, key_state, di->keymap_size), + GFP_KERNEL); if (ds == NULL) { ret = -ENOMEM; pr_err("gpio_event_input_func: " diff --git a/drivers/input/misc/gpio_matrix.c b/drivers/input/misc/gpio_matrix.c index 08769dd88f56..92aa6b89d71c 100644 --- a/drivers/input/misc/gpio_matrix.c +++ b/drivers/input/misc/gpio_matrix.c @@ -327,8 +327,8 @@ int gpio_event_matrix_func(struct gpio_event_input_devs *input_devs, } key_count = mi->ninputs * mi->noutputs; - *data = kp = kzalloc(sizeof(*kp) + sizeof(kp->keys_pressed[0]) * - BITS_TO_LONGS(key_count), GFP_KERNEL); + *data = kp = kzalloc(struct_size(kp, keys_pressed, BITS_TO_LONGS(key_count)), + GFP_KERNEL); if (kp == NULL) { err = -ENOMEM; pr_err("gpiomatrix: Failed to allocate private data\n"); diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c index 2c5912e75514..5f63bd1ac14b 100644 --- a/drivers/md/dm-raid.c +++ b/drivers/md/dm-raid.c @@ -740,7 +740,7 @@ static struct raid_set *raid_set_alloc(struct dm_target *ti, struct raid_type *r return ERR_PTR(-EINVAL); } - rs = kzalloc(sizeof(*rs) + raid_devs * sizeof(rs->dev[0]), GFP_KERNEL); + rs = kzalloc(struct_size(rs, dev, raid_devs), GFP_KERNEL); if (!rs) { ti->error = "Cannot allocate raid context"; return ERR_PTR(-ENOMEM); diff --git a/drivers/misc/vexpress-syscfg.c b/drivers/misc/vexpress-syscfg.c index 9b4eba41ee5d..9c56f73532e7 100644 --- a/drivers/misc/vexpress-syscfg.c +++ b/drivers/misc/vexpress-syscfg.c @@ -182,8 +182,7 @@ static struct regmap *vexpress_syscfg_regmap_init(struct device *dev, val = energy_quirk; } - func = kzalloc(sizeof(*func) + sizeof(*func->template) * num, - GFP_KERNEL); + func = kzalloc(struct_size(func, template, num), GFP_KERNEL); if (!func) return ERR_PTR(-ENOMEM); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c b/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c index 7ecadb501743..413080a312a7 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c @@ -494,7 +494,7 @@ static int add_res_tree(struct mlx5_core_dev *dev, enum dbg_rsc_type type, int err; int i; - d = kzalloc(sizeof(*d) + nfile * sizeof(d->fields[0]), GFP_KERNEL); + d = kzalloc(struct_size(d, fields, nfile), GFP_KERNEL); if (!d) return -ENOMEM; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c index 24d1b0be5a68..bfa54d1f785c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c @@ -1053,8 +1053,7 @@ static struct mlx5_flow_handle *alloc_handle(int num_rules) { struct mlx5_flow_handle *handle; - handle = kzalloc(sizeof(*handle) + sizeof(handle->rule[0]) * - num_rules, GFP_KERNEL); + handle = kzalloc(struct_size(handle, rule, num_rules), GFP_KERNEL); if (!handle) return NULL; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index b86c7a36d3f1..0627b2382d85 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -3020,9 +3020,7 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw, mvmsta = iwl_mvm_sta_from_mac80211(sta); WARN_ON(rcu_access_pointer(mvmsta->ptk_pn[keyidx])); - ptk_pn = kzalloc(sizeof(*ptk_pn) + - mvm->trans->num_rx_queues * - sizeof(ptk_pn->q[0]), + ptk_pn = kzalloc(struct_size(ptk_pn, q, mvm->trans->num_rx_queues), GFP_KERNEL); if (!ptk_pn) { ret = -ENOMEM; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index d9ab85c8eb6a..1b835cee62e0 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -2223,9 +2223,7 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, * Allocate here so if allocation fails we can bail out early * before starting the BA session in the firmware */ - baid_data = kzalloc(sizeof(*baid_data) + - mvm->trans->num_rx_queues * - sizeof(baid_data->reorder_buf[0]), + baid_data = kzalloc(struct_size(baid_data, reorder_buf, mvm->trans->num_rx_queues), GFP_KERNEL); if (!baid_data) return -ENOMEM; diff --git a/drivers/reset/core.c b/drivers/reset/core.c index 7e0a14211c88..d40afaee7a08 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -638,8 +638,7 @@ of_reset_control_array_get(struct device_node *np, bool shared, bool optional) if (num < 0) return optional ? NULL : ERR_PTR(num); - resets = kzalloc(sizeof(*resets) + sizeof(resets->rstc[0]) * num, - GFP_KERNEL); + resets = kzalloc(struct_size(resets, rstc, num), GFP_KERNEL); if (!resets) return ERR_PTR(-ENOMEM); diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index 158b5ce45b3b..dffb15311211 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c @@ -322,8 +322,7 @@ int ccwgroup_create_dev(struct device *parent, struct ccwgroup_driver *gdrv, struct ccw_dev_id dev_id; int rc, i; - gdev = kzalloc(sizeof(*gdev) + num_devices * sizeof(gdev->cdev[0]), - GFP_KERNEL); + gdev = kzalloc(struct_size(gdev, cdev, num_devices), GFP_KERNEL); if (!gdev) return -ENOMEM; diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c index 6b8b80879ec8..7400027bcf7e 100644 --- a/drivers/usb/gadget/function/f_midi.c +++ b/drivers/usb/gadget/function/f_midi.c @@ -1353,9 +1353,8 @@ static struct usb_function *f_midi_alloc(struct usb_function_instance *fi) } /* allocate and initialize one new instance */ - midi = kzalloc( - sizeof(*midi) + opts->in_ports * sizeof(*midi->in_ports_array), - GFP_KERNEL); + midi = kzalloc(struct_size(midi, in_ports_array, opts->in_ports), + GFP_KERNEL); if (!midi) { status = -ENOMEM; goto setup_fail; diff --git a/drivers/zorro/zorro.c b/drivers/zorro/zorro.c index 47728477297e..875e569bf123 100644 --- a/drivers/zorro/zorro.c +++ b/drivers/zorro/zorro.c @@ -136,8 +136,7 @@ static int __init amiga_zorro_probe(struct platform_device *pdev) int error; /* Initialize the Zorro bus */ - bus = kzalloc(sizeof(*bus) + - zorro_num_autocon * sizeof(bus->devices[0]), + bus = kzalloc(struct_size(bus, devices, zorro_num_autocon), GFP_KERNEL); if (!bus) return -ENOMEM; diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c index 44ea596376f8..3a5ea06b28b7 100644 --- a/kernel/cgroup/cgroup.c +++ b/kernel/cgroup/cgroup.c @@ -4894,8 +4894,8 @@ static struct cgroup *cgroup_create(struct cgroup *parent) int ret; /* allocate the cgroup and its ID, 0 is reserved for the root */ - cgrp = kzalloc(sizeof(*cgrp) + - sizeof(cgrp->ancestor_ids[0]) * (level + 1), GFP_KERNEL); + cgrp = kzalloc(struct_size(cgrp, ancestor_ids, (level + 1)), + GFP_KERNEL); if (!cgrp) return ERR_PTR(-ENOMEM); diff --git a/kernel/module.c b/kernel/module.c index 71a744ed22fe..8ae34b071d38 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -1599,8 +1599,7 @@ static void add_notes_attrs(struct module *mod, const struct load_info *info) if (notes == 0) return; - notes_attrs = kzalloc(sizeof(*notes_attrs) - + notes * sizeof(notes_attrs->attrs[0]), + notes_attrs = kzalloc(struct_size(notes_attrs, attrs, notes), GFP_KERNEL); if (notes_attrs == NULL) return; diff --git a/kernel/workqueue.c b/kernel/workqueue.c index f93f40dd7aaf..8263b5f54923 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -3713,8 +3713,7 @@ apply_wqattrs_prepare(struct workqueue_struct *wq, lockdep_assert_held(&wq_pool_mutex); - ctx = kzalloc(sizeof(*ctx) + nr_node_ids * sizeof(ctx->pwq_tbl[0]), - GFP_KERNEL); + ctx = kzalloc(struct_size(ctx, pwq_tbl, nr_node_ids), GFP_KERNEL); new_attrs = alloc_workqueue_attrs(GFP_KERNEL); tmp_attrs = alloc_workqueue_attrs(GFP_KERNEL); diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index daca0af59942..30def9d1220c 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c @@ -62,7 +62,7 @@ struct ceph_monmap *ceph_monmap_decode(void *p, void *end) if (num_mon >= CEPH_MAX_MON) goto bad; - m = kmalloc(sizeof(*m) + sizeof(m->mon_inst[0])*num_mon, GFP_NOFS); + m = kmalloc(struct_size(m, mon_inst, num_mon), GFP_NOFS); if (m == NULL) return ERR_PTR(-ENOMEM); m->fsid = fsid; diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index b026128a89d7..2a52ebb1a9e2 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -527,8 +527,7 @@ struct ceph_osd_request *ceph_osdc_alloc_request(struct ceph_osd_client *osdc, req = kmem_cache_alloc(ceph_osd_request_cache, gfp_flags); } else { BUG_ON(num_ops > CEPH_OSD_MAX_OPS); - req = kmalloc(sizeof(*req) + num_ops * sizeof(req->r_ops[0]), - gfp_flags); + req = kmalloc(struct_size(req, r_ops, num_ops), gfp_flags); } if (unlikely(!req)) return NULL; diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c index cf96d230e5a3..441a70b043f4 100644 --- a/net/netfilter/xt_recent.c +++ b/net/netfilter/xt_recent.c @@ -184,8 +184,7 @@ recent_entry_init(struct recent_table *t, const union nf_inet_addr *addr, } nstamps_max += 1; - e = kmalloc(sizeof(*e) + sizeof(e->stamps[0]) * nstamps_max, - GFP_ATOMIC); + e = kmalloc(struct_size(e, stamps, nstamps_max), GFP_ATOMIC); if (e == NULL) return NULL; memcpy(&e->addr, addr, sizeof(e->addr)); From c9457ea5fff4a665f64ef771507569a384ae68e6 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 8 May 2018 15:56:34 -0700 Subject: [PATCH 571/592] treewide: Use struct_size() for vmalloc()-family This only finds one hit in the entire tree, but here's the Coccinelle: // Directly refer to structure's field @@ identifier alloc =~ "vmalloc|vzalloc"; identifier VAR, ELEMENT; expression COUNT; @@ - alloc(sizeof(*VAR) + COUNT * sizeof(*VAR->ELEMENT)) + alloc(struct_size(VAR, ELEMENT, COUNT)) // mr = kzalloc(sizeof(*mr) + m * sizeof(mr->map[0]), GFP_KERNEL); @@ identifier alloc =~ "vmalloc|vzalloc"; identifier VAR, ELEMENT; expression COUNT; @@ - alloc(sizeof(*VAR) + COUNT * sizeof(VAR->ELEMENT[0])) + alloc(struct_size(VAR, ELEMENT, COUNT)) // Same pattern, but can't trivially locate the trailing element name, // or variable name. @@ identifier alloc =~ "vmalloc|vzalloc"; expression SOMETHING, COUNT, ELEMENT; @@ - alloc(sizeof(SOMETHING) + COUNT * sizeof(ELEMENT)) + alloc(CHECKME_struct_size(&SOMETHING, ELEMENT, COUNT)) Signed-off-by: Kees Cook Signed-off-by: Adam W. Willis Signed-off-by: UtsavBalar1231 --- drivers/gpu/drm/nouveau/nvkm/core/ramht.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/core/ramht.c b/drivers/gpu/drm/nouveau/nvkm/core/ramht.c index 89da47234016..9031f0ea0081 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/ramht.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/ramht.c @@ -143,8 +143,7 @@ nvkm_ramht_new(struct nvkm_device *device, u32 size, u32 align, struct nvkm_ramht *ramht; int ret, i; - if (!(ramht = *pramht = vzalloc(sizeof(*ramht) + - (size >> 3) * sizeof(*ramht->data)))) + if (!(ramht = *pramht = vzalloc(struct_size(ramht, data, (size >> 3))))) return -ENOMEM; ramht->device = device; From 9793ac46056b506d73cffaa46fa4a70276deeb62 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 8 May 2018 16:08:53 -0700 Subject: [PATCH 572/592] treewide: Use struct_size() for devm_kmalloc() and friends Replaces open-coded struct size calculations with struct_size() for devm_*, f2fs_*, and sock_* allocations. Automatically generated (and manually adjusted) from the following Coccinelle script: // Direct reference to struct field. @@ identifier alloc =~ "devm_kmalloc|devm_kzalloc|sock_kmalloc|f2fs_kmalloc|f2fs_kzalloc"; expression HANDLE; expression GFP; identifier VAR, ELEMENT; expression COUNT; @@ - alloc(HANDLE, sizeof(*VAR) + COUNT * sizeof(*VAR->ELEMENT), GFP) + alloc(HANDLE, struct_size(VAR, ELEMENT, COUNT), GFP) // mr = kzalloc(sizeof(*mr) + m * sizeof(mr->map[0]), GFP_KERNEL); @@ identifier alloc =~ "devm_kmalloc|devm_kzalloc|sock_kmalloc|f2fs_kmalloc|f2fs_kzalloc"; expression HANDLE; expression GFP; identifier VAR, ELEMENT; expression COUNT; @@ - alloc(HANDLE, sizeof(*VAR) + COUNT * sizeof(VAR->ELEMENT[0]), GFP) + alloc(HANDLE, struct_size(VAR, ELEMENT, COUNT), GFP) // Same pattern, but can't trivially locate the trailing element name, // or variable name. @@ identifier alloc =~ "devm_kmalloc|devm_kzalloc|sock_kmalloc|f2fs_kmalloc|f2fs_kzalloc"; expression HANDLE; expression GFP; expression SOMETHING, COUNT, ELEMENT; @@ - alloc(HANDLE, sizeof(SOMETHING) + COUNT * sizeof(ELEMENT), GFP) + alloc(HANDLE, CHECKME_struct_size(&SOMETHING, ELEMENT, COUNT), GFP) Signed-off-by: Kees Cook Signed-off-by: Adam W. Willis Signed-off-by: UtsavBalar1231 --- crypto/af_alg.c | 4 ++-- drivers/clk/bcm/clk-bcm2835-aux.c | 5 +++-- drivers/clk/clk-s2mps11.c | 4 ++-- drivers/clk/mvebu/armada-37xx-tbg.c | 4 ++-- drivers/clk/qcom/clk-spmi-pmic-div.c | 3 +-- drivers/clk/samsung/clk-exynos-audss.c | 3 +-- drivers/clk/samsung/clk-s5pv210-audss.c | 3 +-- drivers/dma/bcm-sba-raid.c | 5 ++--- drivers/dma/nbpfaxi.c | 4 ++-- drivers/input/keyboard/cap11xx.c | 3 +-- drivers/mfd/qcom-pm8xxx.c | 4 ++-- drivers/misc/cb710/core.c | 4 ++-- drivers/mtd/spi-nor/aspeed-smc.c | 5 +++-- drivers/net/can/peak_canfd/peak_pciefd_main.c | 3 +-- drivers/pinctrl/samsung/pinctrl-s3c64xx.c | 4 ++-- drivers/pinctrl/uniphier/pinctrl-uniphier-core.c | 3 +-- drivers/regulator/mc13783-regulator.c | 6 +++--- drivers/regulator/mc13892-regulator.c | 6 +++--- drivers/soc/actions/owl-sps.c | 4 ++-- drivers/soc/rockchip/pm_domains.c | 6 ++---- 20 files changed, 38 insertions(+), 45 deletions(-) diff --git a/crypto/af_alg.c b/crypto/af_alg.c index 3f3b57f80bdb..10a7d6b0e85b 100644 --- a/crypto/af_alg.c +++ b/crypto/af_alg.c @@ -528,8 +528,8 @@ int af_alg_alloc_tsgl(struct sock *sk) sg = sgl->sg; if (!sg || sgl->cur >= MAX_SGL_ENTS) { - sgl = sock_kmalloc(sk, sizeof(*sgl) + - sizeof(sgl->sg[0]) * (MAX_SGL_ENTS + 1), + sgl = sock_kmalloc(sk, + struct_size(sgl, sg, (MAX_SGL_ENTS + 1)), GFP_KERNEL); if (!sgl) return -ENOMEM; diff --git a/drivers/clk/bcm/clk-bcm2835-aux.c b/drivers/clk/bcm/clk-bcm2835-aux.c index bd750cf2238d..72b9d7bf8f0a 100644 --- a/drivers/clk/bcm/clk-bcm2835-aux.c +++ b/drivers/clk/bcm/clk-bcm2835-aux.c @@ -41,8 +41,9 @@ static int bcm2835_aux_clk_probe(struct platform_device *pdev) if (IS_ERR(reg)) return PTR_ERR(reg); - onecell = devm_kmalloc(dev, sizeof(*onecell) + sizeof(*onecell->hws) * - BCM2835_AUX_CLOCK_COUNT, GFP_KERNEL); + onecell = devm_kmalloc(dev, + struct_size(onecell, hws, BCM2835_AUX_CLOCK_COUNT), + GFP_KERNEL); if (!onecell) return -ENOMEM; onecell->num = BCM2835_AUX_CLOCK_COUNT; diff --git a/drivers/clk/clk-s2mps11.c b/drivers/clk/clk-s2mps11.c index f5d74e8db432..4080d4e78e8e 100644 --- a/drivers/clk/clk-s2mps11.c +++ b/drivers/clk/clk-s2mps11.c @@ -147,8 +147,8 @@ static int s2mps11_clk_probe(struct platform_device *pdev) if (!s2mps11_clks) return -ENOMEM; - clk_data = devm_kzalloc(&pdev->dev, sizeof(*clk_data) + - sizeof(*clk_data->hws) * S2MPS11_CLKS_NUM, + clk_data = devm_kzalloc(&pdev->dev, + struct_size(clk_data, hws, S2MPS11_CLKS_NUM), GFP_KERNEL); if (!clk_data) return -ENOMEM; diff --git a/drivers/clk/mvebu/armada-37xx-tbg.c b/drivers/clk/mvebu/armada-37xx-tbg.c index aa80db11f543..7ff041f73b55 100644 --- a/drivers/clk/mvebu/armada-37xx-tbg.c +++ b/drivers/clk/mvebu/armada-37xx-tbg.c @@ -91,8 +91,8 @@ static int armada_3700_tbg_clock_probe(struct platform_device *pdev) void __iomem *reg; int i, ret; - hw_tbg_data = devm_kzalloc(&pdev->dev, sizeof(*hw_tbg_data) - + sizeof(*hw_tbg_data->hws) * NUM_TBG, + hw_tbg_data = devm_kzalloc(&pdev->dev, + struct_size(hw_tbg_data, hws, NUM_TBG), GFP_KERNEL); if (!hw_tbg_data) return -ENOMEM; diff --git a/drivers/clk/qcom/clk-spmi-pmic-div.c b/drivers/clk/qcom/clk-spmi-pmic-div.c index c22eccacc860..7bae2ef6a755 100644 --- a/drivers/clk/qcom/clk-spmi-pmic-div.c +++ b/drivers/clk/qcom/clk-spmi-pmic-div.c @@ -240,8 +240,7 @@ static int spmi_pmic_clkdiv_probe(struct platform_device *pdev) if (!nclks) return -EINVAL; - cc = devm_kzalloc(dev, sizeof(*cc) + sizeof(*cc->clks) * nclks, - GFP_KERNEL); + cc = devm_kzalloc(dev, struct_size(cc, clks, nclks), GFP_KERNEL); if (!cc) return -ENOMEM; cc->nclks = nclks; diff --git a/drivers/clk/samsung/clk-exynos-audss.c b/drivers/clk/samsung/clk-exynos-audss.c index b117783ed404..2c3b15b48586 100644 --- a/drivers/clk/samsung/clk-exynos-audss.c +++ b/drivers/clk/samsung/clk-exynos-audss.c @@ -151,8 +151,7 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) epll = ERR_PTR(-ENODEV); clk_data = devm_kzalloc(&pdev->dev, - sizeof(*clk_data) + - sizeof(*clk_data->hws) * EXYNOS_AUDSS_MAX_CLKS, + struct_size(clk_data, hws, EXYNOS_AUDSS_MAX_CLKS), GFP_KERNEL); if (!clk_data) return -ENOMEM; diff --git a/drivers/clk/samsung/clk-s5pv210-audss.c b/drivers/clk/samsung/clk-s5pv210-audss.c index b9641414ddc6..22b18e728b88 100644 --- a/drivers/clk/samsung/clk-s5pv210-audss.c +++ b/drivers/clk/samsung/clk-s5pv210-audss.c @@ -81,8 +81,7 @@ static int s5pv210_audss_clk_probe(struct platform_device *pdev) } clk_data = devm_kzalloc(&pdev->dev, - sizeof(*clk_data) + - sizeof(*clk_data->hws) * AUDSS_MAX_CLKS, + struct_size(clk_data, hws, AUDSS_MAX_CLKS), GFP_KERNEL); if (!clk_data) diff --git a/drivers/dma/bcm-sba-raid.c b/drivers/dma/bcm-sba-raid.c index 6c2c44724637..eae1cde3f059 100644 --- a/drivers/dma/bcm-sba-raid.c +++ b/drivers/dma/bcm-sba-raid.c @@ -1513,9 +1513,8 @@ static int sba_prealloc_channel_resources(struct sba_device *sba) for (i = 0; i < sba->max_req; i++) { req = devm_kzalloc(sba->dev, - sizeof(*req) + - sba->max_cmd_per_req * sizeof(req->cmds[0]), - GFP_KERNEL); + struct_size(req, cmds, sba->max_cmd_per_req), + GFP_KERNEL); if (!req) { ret = -ENOMEM; goto fail_free_cmds_pool; diff --git a/drivers/dma/nbpfaxi.c b/drivers/dma/nbpfaxi.c index d3f918a9ee76..a45889e0fc93 100644 --- a/drivers/dma/nbpfaxi.c +++ b/drivers/dma/nbpfaxi.c @@ -1306,8 +1306,8 @@ static int nbpf_probe(struct platform_device *pdev) cfg = of_id->data; num_channels = cfg->num_channels; - nbpf = devm_kzalloc(dev, sizeof(*nbpf) + num_channels * - sizeof(nbpf->chan[0]), GFP_KERNEL); + nbpf = devm_kzalloc(dev, struct_size(nbpf, chan, num_channels), + GFP_KERNEL); if (!nbpf) return -ENOMEM; diff --git a/drivers/input/keyboard/cap11xx.c b/drivers/input/keyboard/cap11xx.c index 87fb48143859..73686c2460ce 100644 --- a/drivers/input/keyboard/cap11xx.c +++ b/drivers/input/keyboard/cap11xx.c @@ -344,8 +344,7 @@ static int cap11xx_i2c_probe(struct i2c_client *i2c_client, } priv = devm_kzalloc(dev, - sizeof(*priv) + - cap->num_channels * sizeof(priv->keycodes[0]), + struct_size(priv, keycodes, cap->num_channels), GFP_KERNEL); if (!priv) return -ENOMEM; diff --git a/drivers/mfd/qcom-pm8xxx.c b/drivers/mfd/qcom-pm8xxx.c index f08758f6b418..e6e8d81c15fd 100644 --- a/drivers/mfd/qcom-pm8xxx.c +++ b/drivers/mfd/qcom-pm8xxx.c @@ -563,8 +563,8 @@ static int pm8xxx_probe(struct platform_device *pdev) pr_info("PMIC revision 2: %02X\n", val); rev |= val << BITS_PER_BYTE; - chip = devm_kzalloc(&pdev->dev, sizeof(*chip) + - sizeof(chip->config[0]) * data->num_irqs, + chip = devm_kzalloc(&pdev->dev, + struct_size(chip, config, data->num_irqs), GFP_KERNEL); if (!chip) return -ENOMEM; diff --git a/drivers/misc/cb710/core.c b/drivers/misc/cb710/core.c index fb397e7d1cce..4d4acf763b65 100644 --- a/drivers/misc/cb710/core.c +++ b/drivers/misc/cb710/core.c @@ -232,8 +232,8 @@ static int cb710_probe(struct pci_dev *pdev, if (val & CB710_SLOT_SM) ++n; - chip = devm_kzalloc(&pdev->dev, - sizeof(*chip) + n * sizeof(*chip->slot), GFP_KERNEL); + chip = devm_kzalloc(&pdev->dev, struct_size(chip, slot, n), + GFP_KERNEL); if (!chip) return -ENOMEM; diff --git a/drivers/mtd/spi-nor/aspeed-smc.c b/drivers/mtd/spi-nor/aspeed-smc.c index 8d3cbe27efb6..95e54468cf7d 100644 --- a/drivers/mtd/spi-nor/aspeed-smc.c +++ b/drivers/mtd/spi-nor/aspeed-smc.c @@ -861,8 +861,9 @@ static int aspeed_smc_probe(struct platform_device *pdev) return -ENODEV; info = match->data; - controller = devm_kzalloc(&pdev->dev, sizeof(*controller) + - info->nce * sizeof(controller->chips[0]), GFP_KERNEL); + controller = devm_kzalloc(&pdev->dev, + struct_size(controller, chips, info->nce), + GFP_KERNEL); if (!controller) return -ENOMEM; controller->info = info; diff --git a/drivers/net/can/peak_canfd/peak_pciefd_main.c b/drivers/net/can/peak_canfd/peak_pciefd_main.c index fa689854f16b..455a3797a200 100644 --- a/drivers/net/can/peak_canfd/peak_pciefd_main.c +++ b/drivers/net/can/peak_canfd/peak_pciefd_main.c @@ -756,8 +756,7 @@ static int peak_pciefd_probe(struct pci_dev *pdev, can_count = 1; /* allocate board structure object */ - pciefd = devm_kzalloc(&pdev->dev, sizeof(*pciefd) + - can_count * sizeof(*pciefd->can), + pciefd = devm_kzalloc(&pdev->dev, struct_size(pciefd, can, can_count), GFP_KERNEL); if (!pciefd) { err = -ENOMEM; diff --git a/drivers/pinctrl/samsung/pinctrl-s3c64xx.c b/drivers/pinctrl/samsung/pinctrl-s3c64xx.c index cf3a3af82321..6550239cb311 100644 --- a/drivers/pinctrl/samsung/pinctrl-s3c64xx.c +++ b/drivers/pinctrl/samsung/pinctrl-s3c64xx.c @@ -488,8 +488,8 @@ static int s3c64xx_eint_gpio_init(struct samsung_pinctrl_drv_data *d) ++nr_domains; } - data = devm_kzalloc(dev, sizeof(*data) - + nr_domains * sizeof(*data->domains), GFP_KERNEL); + data = devm_kzalloc(dev, struct_size(data, domains, nr_domains), + GFP_KERNEL); if (!data) return -ENOMEM; data->drvdata = d; diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c index f9267fabe6b0..ea08afa25fde 100644 --- a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c +++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c @@ -751,8 +751,7 @@ static int uniphier_pinctrl_add_reg_region(struct device *dev, nregs = DIV_ROUND_UP(count * width, 32); - region = devm_kzalloc(dev, - sizeof(*region) + sizeof(region->vals[0]) * nregs, + region = devm_kzalloc(dev, struct_size(region, vals, nregs), GFP_KERNEL); if (!region) return -ENOMEM; diff --git a/drivers/regulator/mc13783-regulator.c b/drivers/regulator/mc13783-regulator.c index fe4c7d677f9c..0e0277bd91a8 100644 --- a/drivers/regulator/mc13783-regulator.c +++ b/drivers/regulator/mc13783-regulator.c @@ -409,9 +409,9 @@ static int mc13783_regulator_probe(struct platform_device *pdev) if (num_regulators <= 0) return -EINVAL; - priv = devm_kzalloc(&pdev->dev, sizeof(*priv) + - num_regulators * sizeof(priv->regulators[0]), - GFP_KERNEL); + priv = devm_kzalloc(&pdev->dev, + struct_size(priv, regulators, num_regulators), + GFP_KERNEL); if (!priv) return -ENOMEM; diff --git a/drivers/regulator/mc13892-regulator.c b/drivers/regulator/mc13892-regulator.c index 0d17c9206816..15dd7bc7b529 100644 --- a/drivers/regulator/mc13892-regulator.c +++ b/drivers/regulator/mc13892-regulator.c @@ -547,9 +547,9 @@ static int mc13892_regulator_probe(struct platform_device *pdev) if (num_regulators <= 0) return -EINVAL; - priv = devm_kzalloc(&pdev->dev, sizeof(*priv) + - num_regulators * sizeof(priv->regulators[0]), - GFP_KERNEL); + priv = devm_kzalloc(&pdev->dev, + struct_size(priv, regulators, num_regulators), + GFP_KERNEL); if (!priv) return -ENOMEM; diff --git a/drivers/soc/actions/owl-sps.c b/drivers/soc/actions/owl-sps.c index 875225bfa21c..077a8305890e 100644 --- a/drivers/soc/actions/owl-sps.c +++ b/drivers/soc/actions/owl-sps.c @@ -116,8 +116,8 @@ static int owl_sps_probe(struct platform_device *pdev) sps_info = match->data; - sps = devm_kzalloc(&pdev->dev, sizeof(*sps) + - sps_info->num_domains * sizeof(sps->domains[0]), + sps = devm_kzalloc(&pdev->dev, + struct_size(sps, domains, sps_info->num_domains), GFP_KERNEL); if (!sps) return -ENOMEM; diff --git a/drivers/soc/rockchip/pm_domains.c b/drivers/soc/rockchip/pm_domains.c index ba009bb9d82b..e1d835324bfe 100644 --- a/drivers/soc/rockchip/pm_domains.c +++ b/drivers/soc/rockchip/pm_domains.c @@ -403,8 +403,7 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu, } clk_cnt = of_count_phandle_with_args(node, "clocks", "#clock-cells"); - pd = devm_kzalloc(pmu->dev, - sizeof(*pd) + clk_cnt * sizeof(pd->clks[0]), + pd = devm_kzalloc(pmu->dev, struct_size(pd, clks, clk_cnt), GFP_KERNEL); if (!pd) return -ENOMEM; @@ -637,8 +636,7 @@ static int rockchip_pm_domain_probe(struct platform_device *pdev) pmu_info = match->data; pmu = devm_kzalloc(dev, - sizeof(*pmu) + - pmu_info->num_domains * sizeof(pmu->domains[0]), + struct_size(pmu, domains, pmu_info->num_domains), GFP_KERNEL); if (!pmu) return -ENOMEM; From 88739c48797b0f06f6ae1ff9b445d2b515529a8b Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 12 Jun 2018 13:55:00 -0700 Subject: [PATCH 573/592] treewide: kmalloc() -> kmalloc_array() The kmalloc() function has a 2-factor argument form, kmalloc_array(). This patch replaces cases of: kmalloc(a * b, gfp) with: kmalloc_array(a * b, gfp) as well as handling cases of: kmalloc(a * b * c, gfp) with: kmalloc(array3_size(a, b, c), gfp) as it's slightly less ugly than: kmalloc_array(array_size(a, b), c, gfp) This does, however, attempt to ignore constant size factors like: kmalloc(4 * 1024, gfp) though any constants defined via macros get caught up in the conversion. Any factors with a sizeof() of "unsigned char", "char", and "u8" were dropped, since they're redundant. The tools/ directory was manually excluded, since it has its own implementation of kmalloc(). The Coccinelle script used for this was: // Fix redundant parens around sizeof(). @@ type TYPE; expression THING, E; @@ ( kmalloc( - (sizeof(TYPE)) * E + sizeof(TYPE) * E , ...) | kmalloc( - (sizeof(THING)) * E + sizeof(THING) * E , ...) ) // Drop single-byte sizes and redundant parens. @@ expression COUNT; typedef u8; typedef __u8; @@ ( kmalloc( - sizeof(u8) * (COUNT) + COUNT , ...) | kmalloc( - sizeof(__u8) * (COUNT) + COUNT , ...) | kmalloc( - sizeof(char) * (COUNT) + COUNT , ...) | kmalloc( - sizeof(unsigned char) * (COUNT) + COUNT , ...) | kmalloc( - sizeof(u8) * COUNT + COUNT , ...) | kmalloc( - sizeof(__u8) * COUNT + COUNT , ...) | kmalloc( - sizeof(char) * COUNT + COUNT , ...) | kmalloc( - sizeof(unsigned char) * COUNT + COUNT , ...) ) // 2-factor product with sizeof(type/expression) and identifier or constant. @@ type TYPE; expression THING; identifier COUNT_ID; constant COUNT_CONST; @@ ( - kmalloc + kmalloc_array ( - sizeof(TYPE) * (COUNT_ID) + COUNT_ID, sizeof(TYPE) , ...) | - kmalloc + kmalloc_array ( - sizeof(TYPE) * COUNT_ID + COUNT_ID, sizeof(TYPE) , ...) | - kmalloc + kmalloc_array ( - sizeof(TYPE) * (COUNT_CONST) + COUNT_CONST, sizeof(TYPE) , ...) | - kmalloc + kmalloc_array ( - sizeof(TYPE) * COUNT_CONST + COUNT_CONST, sizeof(TYPE) , ...) | - kmalloc + kmalloc_array ( - sizeof(THING) * (COUNT_ID) + COUNT_ID, sizeof(THING) , ...) | - kmalloc + kmalloc_array ( - sizeof(THING) * COUNT_ID + COUNT_ID, sizeof(THING) , ...) | - kmalloc + kmalloc_array ( - sizeof(THING) * (COUNT_CONST) + COUNT_CONST, sizeof(THING) , ...) | - kmalloc + kmalloc_array ( - sizeof(THING) * COUNT_CONST + COUNT_CONST, sizeof(THING) , ...) ) // 2-factor product, only identifiers. @@ identifier SIZE, COUNT; @@ - kmalloc + kmalloc_array ( - SIZE * COUNT + COUNT, SIZE , ...) // 3-factor product with 1 sizeof(type) or sizeof(expression), with // redundant parens removed. @@ expression THING; identifier STRIDE, COUNT; type TYPE; @@ ( kmalloc( - sizeof(TYPE) * (COUNT) * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | kmalloc( - sizeof(TYPE) * (COUNT) * STRIDE + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | kmalloc( - sizeof(TYPE) * COUNT * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | kmalloc( - sizeof(TYPE) * COUNT * STRIDE + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | kmalloc( - sizeof(THING) * (COUNT) * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) | kmalloc( - sizeof(THING) * (COUNT) * STRIDE + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) | kmalloc( - sizeof(THING) * COUNT * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) | kmalloc( - sizeof(THING) * COUNT * STRIDE + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) ) // 3-factor product with 2 sizeof(variable), with redundant parens removed. @@ expression THING1, THING2; identifier COUNT; type TYPE1, TYPE2; @@ ( kmalloc( - sizeof(TYPE1) * sizeof(TYPE2) * COUNT + array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2)) , ...) | kmalloc( - sizeof(TYPE1) * sizeof(THING2) * (COUNT) + array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2)) , ...) | kmalloc( - sizeof(THING1) * sizeof(THING2) * COUNT + array3_size(COUNT, sizeof(THING1), sizeof(THING2)) , ...) | kmalloc( - sizeof(THING1) * sizeof(THING2) * (COUNT) + array3_size(COUNT, sizeof(THING1), sizeof(THING2)) , ...) | kmalloc( - sizeof(TYPE1) * sizeof(THING2) * COUNT + array3_size(COUNT, sizeof(TYPE1), sizeof(THING2)) , ...) | kmalloc( - sizeof(TYPE1) * sizeof(THING2) * (COUNT) + array3_size(COUNT, sizeof(TYPE1), sizeof(THING2)) , ...) ) // 3-factor product, only identifiers, with redundant parens removed. @@ identifier STRIDE, SIZE, COUNT; @@ ( kmalloc( - (COUNT) * STRIDE * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) | kmalloc( - COUNT * (STRIDE) * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) | kmalloc( - COUNT * STRIDE * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | kmalloc( - (COUNT) * (STRIDE) * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) | kmalloc( - COUNT * (STRIDE) * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | kmalloc( - (COUNT) * STRIDE * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | kmalloc( - (COUNT) * (STRIDE) * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | kmalloc( - COUNT * STRIDE * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) ) // Any remaining multi-factor products, first at least 3-factor products, // when they're not all constants... @@ expression E1, E2, E3; constant C1, C2, C3; @@ ( kmalloc(C1 * C2 * C3, ...) | kmalloc( - (E1) * E2 * E3 + array3_size(E1, E2, E3) , ...) | kmalloc( - (E1) * (E2) * E3 + array3_size(E1, E2, E3) , ...) | kmalloc( - (E1) * (E2) * (E3) + array3_size(E1, E2, E3) , ...) | kmalloc( - E1 * E2 * E3 + array3_size(E1, E2, E3) , ...) ) // And then all remaining 2 factors products when they're not all constants, // keeping sizeof() as the second factor argument. @@ expression THING, E1, E2; type TYPE; constant C1, C2, C3; @@ ( kmalloc(sizeof(THING) * C2, ...) | kmalloc(sizeof(TYPE) * C2, ...) | kmalloc(C1 * C2 * C3, ...) | kmalloc(C1 * C2, ...) | - kmalloc + kmalloc_array ( - sizeof(TYPE) * (E2) + E2, sizeof(TYPE) , ...) | - kmalloc + kmalloc_array ( - sizeof(TYPE) * E2 + E2, sizeof(TYPE) , ...) | - kmalloc + kmalloc_array ( - sizeof(THING) * (E2) + E2, sizeof(THING) , ...) | - kmalloc + kmalloc_array ( - sizeof(THING) * E2 + E2, sizeof(THING) , ...) | - kmalloc + kmalloc_array ( - (E1) * E2 + E1, E2 , ...) | - kmalloc + kmalloc_array ( - (E1) * (E2) + E1, E2 , ...) | - kmalloc + kmalloc_array ( - E1 * E2 + E1, E2 , ...) ) Signed-off-by: Kees Cook Signed-off-by: Adam W. Willis Signed-off-by: UtsavBalar1231 --- arch/arm/kernel/sys_oabi-compat.c | 4 +-- arch/arm/mm/pgd.c | 2 +- arch/arm/probes/kprobes/test-core.c | 5 +-- arch/blackfin/mm/isram-driver.c | 2 +- arch/cris/arch-v32/drivers/cryptocop.c | 16 ++++++--- arch/ia64/kernel/mca_drv.c | 3 +- arch/ia64/mm/tlb.c | 5 +-- arch/ia64/sn/kernel/irq.c | 3 +- arch/mips/alchemy/common/dbdma.c | 4 +-- arch/powerpc/lib/rheap.c | 2 +- arch/powerpc/platforms/4xx/hsta_msi.c | 3 +- arch/powerpc/platforms/4xx/msi.c | 2 +- arch/powerpc/sysdev/mpic.c | 5 +-- arch/s390/hypfs/hypfs_diag0c.c | 3 +- arch/s390/include/asm/idals.h | 4 +-- arch/s390/kernel/debug.c | 8 ++--- arch/s390/kernel/perf_cpum_cf_events.c | 2 +- arch/s390/mm/extmem.c | 2 +- arch/sparc/kernel/nmi.c | 3 +- arch/sparc/kernel/sys_sparc_64.c | 5 +-- arch/sparc/net/bpf_jit_comp_32.c | 2 +- arch/um/drivers/ubd_kern.c | 12 +++---- arch/unicore32/kernel/pm.c | 5 +-- arch/x86/events/core.c | 2 +- arch/x86/kernel/hpet.c | 4 +-- arch/x86/kernel/ksysfs.c | 2 +- arch/x86/net/bpf_jit_comp.c | 2 +- arch/x86/platform/uv/tlb_uv.c | 2 +- block/partitions/ldm.c | 2 +- crypto/testmgr.c | 3 +- drivers/acpi/acpi_video.c | 5 +-- drivers/acpi/apei/hest.c | 3 +- drivers/acpi/processor_perflib.c | 5 +-- drivers/acpi/processor_throttling.c | 5 +-- drivers/atm/solos-pci.c | 3 +- drivers/auxdisplay/cfag12864b.c | 4 +-- drivers/block/DAC960.c | 4 +-- drivers/block/loop.c | 3 +- drivers/block/z2ram.c | 5 +-- drivers/cdrom/cdrom.c | 2 +- drivers/char/agp/compat_ioctl.c | 8 +++-- drivers/char/agp/isoch.c | 2 +- drivers/char/agp/sgi-agp.c | 6 ++-- drivers/char/agp/uninorth-agp.c | 4 ++- drivers/char/tile-srom.c | 2 +- drivers/char/virtio_console.c | 15 +++++---- drivers/cpufreq/bmips-cpufreq.c | 2 +- drivers/crypto/stm32/stm32-hash.c | 5 +-- drivers/dma/bestcomm/bestcomm.c | 3 +- drivers/dma/mv_xor.c | 2 +- drivers/firewire/core-iso.c | 4 +-- drivers/firewire/net.c | 2 +- drivers/gpu/drm/drm_edid.c | 3 +- drivers/gpu/drm/gma500/mid_bios.c | 2 +- .../drm/nouveau/nvkm/subdev/bios/iccsense.c | 3 +- .../gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c | 2 +- drivers/gpu/drm/omapdrm/omap_dmm_tiler.c | 4 +-- drivers/gpu/drm/omapdrm/omap_gem.c | 2 +- drivers/gpu/drm/qxl/qxl_kms.c | 4 +-- drivers/gpu/drm/savage/savage_bci.c | 5 +-- drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c | 4 +-- drivers/gpu/drm/tinydrm/repaper.c | 2 +- drivers/gpu/drm/ttm/ttm_page_alloc.c | 8 +++-- drivers/gpu/drm/ttm/ttm_page_alloc_dma.c | 8 +++-- drivers/gpu/drm/vc4/vc4_plane.c | 2 +- drivers/hid/hid-core.c | 6 ++-- drivers/hid/hid-debug.c | 2 +- drivers/hid/hid-picolcd_fb.c | 3 +- drivers/hid/hidraw.c | 2 +- drivers/i2c/i2c-dev.c | 3 +- drivers/ide/ide-probe.c | 5 +-- drivers/infiniband/core/cma.c | 4 +-- drivers/infiniband/core/fmr_pool.c | 5 +-- drivers/infiniband/hw/cxgb4/id_table.c | 4 +-- drivers/infiniband/hw/mlx4/main.c | 12 ++++--- drivers/infiniband/hw/mlx4/qp.c | 4 +-- drivers/infiniband/hw/mthca/mthca_allocator.c | 18 ++++++---- drivers/infiniband/hw/mthca/mthca_cmd.c | 6 ++-- drivers/infiniband/hw/mthca/mthca_eq.c | 6 ++-- drivers/infiniband/hw/mthca/mthca_memfree.c | 6 ++-- drivers/infiniband/hw/mthca/mthca_mr.c | 2 +- drivers/infiniband/hw/mthca/mthca_qp.c | 4 +-- drivers/infiniband/hw/mthca/mthca_srq.c | 2 +- drivers/infiniband/hw/nes/nes_nic.c | 2 +- drivers/infiniband/hw/ocrdma/ocrdma_verbs.c | 3 +- drivers/infiniband/hw/qib/qib_iba6120.c | 9 ++--- drivers/infiniband/hw/qib/qib_iba7220.c | 9 ++--- drivers/infiniband/hw/qib/qib_iba7322.c | 29 +++++++++------- drivers/infiniband/ulp/iser/iser_initiator.c | 5 +-- drivers/infiniband/ulp/srp/ib_srp.c | 9 ++--- drivers/infiniband/ulp/srpt/ib_srpt.c | 2 +- drivers/input/joystick/joydump.c | 2 +- drivers/input/keyboard/bf54x-keys.c | 4 +-- drivers/iommu/io-pgtable-fast.c | 2 +- drivers/irqchip/irq-gic-v3-its.c | 4 +-- drivers/isdn/capi/capidrv.c | 3 +- drivers/isdn/gigaset/capi.c | 4 +-- drivers/isdn/gigaset/common.c | 4 +-- drivers/isdn/hisax/hfc_2bds0.c | 2 +- drivers/isdn/hisax/hfc_2bs0.c | 2 +- drivers/isdn/hisax/netjet.c | 8 ++--- drivers/isdn/i4l/isdn_common.c | 5 +-- drivers/md/bitmap.c | 4 +-- drivers/md/dm-integrity.c | 3 +- drivers/md/dm-snap.c | 9 ++--- drivers/md/dm-stats.c | 4 ++- drivers/md/dm-table.c | 2 +- drivers/md/raid1.c | 4 +-- drivers/md/raid10.c | 2 +- drivers/media/pci/bt8xx/bttv-risc.c | 2 +- drivers/media/pci/ivtv/ivtvfb.c | 2 +- drivers/media/pci/zoran/zoran_driver.c | 2 +- .../camera_v2/sensor/actuator/msm_actuator.c | 33 ++++++++++--------- .../msm/camera_v2/sensor/ois/msm_ois.c | 7 ++-- .../media/platform/msm/vidc/msm_vidc_common.c | 5 +-- drivers/media/platform/vivid/vivid-core.c | 5 +-- drivers/media/usb/cpia2/cpia2_usb.c | 3 +- drivers/media/usb/cx231xx/cx231xx-audio.c | 2 +- drivers/media/usb/em28xx/em28xx-cards.c | 5 +-- drivers/media/usb/go7007/go7007-usb.c | 3 +- drivers/media/usb/gspca/t613.c | 2 +- drivers/media/usb/stk1160/stk1160-core.c | 5 +-- drivers/media/usb/tm6000/tm6000-video.c | 13 +++++--- drivers/media/usb/usbvision/usbvision-video.c | 3 +- drivers/media/usb/uvc/uvc_driver.c | 2 +- drivers/media/usb/uvc/uvc_video.c | 4 +-- drivers/media/v4l2-core/videobuf-dma-sg.c | 3 +- drivers/memstick/core/ms_block.c | 6 ++-- drivers/message/fusion/mptlan.c | 7 ++-- drivers/misc/eeprom/idt_89hpesx.c | 2 +- drivers/misc/vmw_vmci/vmci_queue_pair.c | 6 ++-- drivers/mtd/chips/cfi_cmdset_0001.c | 4 ++- drivers/mtd/chips/cfi_cmdset_0002.c | 5 +-- drivers/mtd/chips/cfi_cmdset_0020.c | 5 +-- drivers/mtd/ftl.c | 13 ++++---- drivers/mtd/inftlmount.c | 6 ++-- drivers/mtd/lpddr/lpddr_cmds.c | 2 +- drivers/mtd/maps/vmu-flash.c | 8 ++--- drivers/mtd/mtdconcat.c | 5 +-- drivers/mtd/mtdswap.c | 2 +- drivers/mtd/nand/nand_bch.c | 2 +- drivers/mtd/nftlmount.c | 7 ++-- drivers/mtd/sm_ftl.c | 2 +- drivers/mtd/ssfdc.c | 5 +-- drivers/mtd/tests/stresstest.c | 2 +- drivers/mtd/ubi/eba.c | 14 ++++---- drivers/net/ethernet/amd/lance.c | 8 ++--- .../ethernet/atheros/atl1c/atl1c_ethtool.c | 4 +-- .../ethernet/atheros/atl1e/atl1e_ethtool.c | 4 +-- drivers/net/ethernet/atheros/atlx/atl2.c | 4 +-- drivers/net/ethernet/broadcom/bnx2.c | 2 +- drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c | 4 +-- .../ethernet/chelsio/cxgb4/cxgb4_debugfs.c | 2 +- .../net/ethernet/chelsio/cxgb4/cxgb4_main.c | 6 ++-- drivers/net/ethernet/freescale/ucc_geth.c | 12 +++---- drivers/net/ethernet/ibm/ibmveth.c | 2 +- .../net/ethernet/intel/e1000/e1000_ethtool.c | 4 +-- drivers/net/ethernet/intel/e1000e/ethtool.c | 4 +-- drivers/net/ethernet/intel/igb/igb_ethtool.c | 8 ++--- .../net/ethernet/intel/ixgb/ixgb_ethtool.c | 5 +-- drivers/net/ethernet/intel/ixgb/ixgb_main.c | 5 +-- .../net/ethernet/intel/ixgbe/ixgbe_ethtool.c | 2 +- drivers/net/ethernet/mellanox/mlx4/cmd.c | 6 ++-- drivers/net/ethernet/mellanox/mlx4/eq.c | 5 +-- .../ethernet/mellanox/mlx4/resource_tracker.c | 10 +++--- drivers/net/ethernet/moxa/moxart_ether.c | 8 ++--- drivers/net/ethernet/nvidia/forcedeth.c | 6 ++-- .../ethernet/oki-semi/pch_gbe/pch_gbe_main.c | 2 +- drivers/net/ethernet/qlogic/qlge/qlge_main.c | 3 +- drivers/net/gtp.c | 8 ++--- drivers/net/hippi/rrunner.c | 2 +- drivers/net/team/team.c | 3 +- drivers/net/usb/asix_common.c | 8 ++--- drivers/net/usb/ax88179_178a.c | 4 +-- drivers/net/usb/usbnet.c | 4 +-- drivers/net/virtio_net.c | 4 +-- drivers/net/wireless/ath/ath5k/phy.c | 3 +- drivers/net/wireless/ath/ath9k/ar9003_paprd.c | 2 +- drivers/net/wireless/ath/ath9k/hw.c | 4 +-- .../broadcom/brcm80211/brcmsmac/phy/phy_lcn.c | 8 ++--- .../broadcom/brcm80211/brcmsmac/phy/phy_n.c | 5 +-- drivers/net/wireless/cisco/airo.c | 2 +- drivers/net/wireless/intel/ipw2x00/ipw2100.c | 11 ++++--- drivers/net/wireless/intel/ipw2x00/ipw2200.c | 10 +++--- .../wireless/intersil/hostap/hostap_info.c | 5 +-- .../wireless/intersil/hostap/hostap_ioctl.c | 4 +-- drivers/net/wireless/zydas/zd1211rw/zd_mac.c | 3 +- drivers/pcmcia/cistpl.c | 4 +-- drivers/pinctrl/freescale/pinctrl-imx.c | 3 +- drivers/pinctrl/freescale/pinctrl-imx1-core.c | 3 +- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 2 +- drivers/s390/block/dasd_eer.c | 4 +-- drivers/s390/char/tty3270.c | 3 +- drivers/s390/crypto/pkey_api.c | 2 +- drivers/scsi/aacraid/aachba.c | 2 +- drivers/scsi/aha1542.c | 3 +- drivers/scsi/aic7xxx/aic79xx_core.c | 3 +- drivers/scsi/aic94xx/aic94xx_hwi.c | 7 ++-- drivers/scsi/arm/queue.c | 2 +- drivers/scsi/be2iscsi/be_main.c | 14 ++++---- drivers/scsi/fcoe/fcoe_ctlr.c | 4 +-- drivers/scsi/hpsa.c | 14 ++++---- drivers/scsi/lpfc/lpfc_mem.c | 5 +-- drivers/scsi/mac53c94.c | 5 +-- drivers/scsi/megaraid.c | 3 +- drivers/scsi/megaraid/megaraid_mm.c | 10 +++--- drivers/scsi/osst.c | 4 ++- drivers/scsi/qla2xxx/qla_nx.c | 2 +- drivers/scsi/qla4xxx/ql4_nx.c | 2 +- drivers/scsi/smartpqi/smartpqi_init.c | 5 +-- drivers/scsi/st.c | 2 +- drivers/scsi/ufs/ufs_test.c | 4 +-- drivers/scsi/virtio_scsi.c | 7 ++-- drivers/soc/fsl/qbman/qman.c | 2 +- drivers/soc/qcom/service-locator.c | 6 ++-- drivers/staging/irda/net/discovery.c | 8 +++-- .../media/atomisp/pci/atomisp2/atomisp_fops.c | 2 +- .../pci/atomisp2/css2400/sh_css_firmware.c | 6 ++-- .../media/atomisp/pci/atomisp2/hmm/hmm_bo.c | 12 +++---- .../pci/atomisp2/hmm/hmm_reserved_pool.c | 4 +-- .../staging/rtl8192u/ieee80211/ieee80211_rx.c | 5 +-- drivers/staging/rtl8192u/r8192U_core.c | 4 +-- .../interface/vchiq_arm/vchiq_arm.c | 2 +- drivers/tty/hvc/hvcs.c | 3 +- drivers/tty/isicom.c | 2 +- drivers/tty/serial/atmel_serial.c | 5 +-- drivers/tty/vt/consolemap.c | 7 ++-- drivers/tty/vt/keyboard.c | 4 +-- drivers/tty/vt/selection.c | 3 +- drivers/usb/core/devio.c | 7 ++-- drivers/usb/core/message.c | 6 ++-- drivers/usb/gadget/ci13xxx_udc.c | 2 +- drivers/usb/host/fhci-tds.c | 2 +- drivers/usb/host/ohci-dbg.c | 2 +- drivers/usb/host/xhci-mem.c | 10 +++--- drivers/usb/misc/ldusb.c | 4 ++- drivers/usb/serial/iuu_phoenix.c | 4 +-- drivers/usb/storage/alauda.c | 2 +- drivers/usb/storage/ene_ub6250.c | 16 ++++++--- drivers/usb/storage/sddr09.c | 4 +-- drivers/usb/storage/sddr55.c | 6 ++-- drivers/uwb/est.c | 2 +- drivers/uwb/i1480/dfu/usb.c | 2 +- drivers/vhost/net.c | 7 ++-- drivers/vhost/scsi.c | 2 +- drivers/vhost/test.c | 2 +- drivers/vhost/vhost.c | 11 ++++--- drivers/vhost/vringh.c | 2 +- drivers/video/fbdev/core/bitblit.c | 4 +-- drivers/video/fbdev/core/fbcon.c | 3 +- drivers/video/fbdev/core/fbcon_ccw.c | 7 ++-- drivers/video/fbdev/core/fbcon_cw.c | 7 ++-- drivers/video/fbdev/core/fbcon_rotate.c | 2 +- drivers/video/fbdev/core/fbcon_ud.c | 4 +-- drivers/video/fbdev/core/fbmem.c | 7 ++-- drivers/video/fbdev/core/fbmon.c | 2 +- drivers/video/fbdev/imxfb.c | 2 +- drivers/video/fbdev/mb862xx/mb862xxfb_accel.c | 2 +- drivers/video/fbdev/nvidia/nvidia.c | 2 +- drivers/video/fbdev/pvr2fb.c | 2 +- drivers/video/fbdev/riva/fbdev.c | 2 +- drivers/video/fbdev/via/viafbdev.c | 3 +- drivers/video/fbdev/w100fb.c | 3 +- drivers/virtio/virtio_pci_common.c | 5 +-- drivers/virtio/virtio_ring.c | 2 +- drivers/vservices/devio.c | 2 +- drivers/xen/grant-table.c | 7 ++-- drivers/xen/xen-pciback/pciback_ops.c | 2 +- fs/9p/fid.c | 2 +- fs/adfs/super.c | 2 +- fs/afs/cmservice.c | 7 ++-- fs/binfmt_elf.c | 2 +- fs/binfmt_elf_fdpic.c | 3 +- fs/block_dev.c | 3 +- fs/ceph/addr.c | 11 ++++--- fs/ceph/mds_client.c | 5 +-- fs/cifs/asn1.c | 2 +- fs/cifs/cifsacl.c | 4 +-- fs/cifs/inode.c | 2 +- fs/cifs/smb2pdu.c | 6 ++-- fs/cifs/transport.c | 2 +- fs/exofs/inode.c | 4 +-- fs/ext2/super.c | 4 ++- fs/ext4/resize.c | 10 +++--- fs/fat/namei_vfat.c | 2 +- fs/fuse/dev.c | 14 +++++--- fs/gfs2/dir.c | 6 ++-- fs/gfs2/glock.c | 3 +- fs/gfs2/quota.c | 2 +- fs/gfs2/rgrp.c | 5 +-- fs/gfs2/super.c | 2 +- fs/hpfs/dnode.c | 2 +- fs/hpfs/map.c | 2 +- fs/jbd2/revoke.c | 2 +- fs/jffs2/wbuf.c | 2 +- fs/jfs/jfs_dmap.c | 2 +- fs/jfs/jfs_dtree.c | 9 ++--- fs/jfs/jfs_unicode.c | 2 +- fs/mbcache.c | 5 +-- fs/namei.c | 4 +-- fs/nfsd/nfs4recover.c | 5 +-- fs/nfsd/nfs4state.c | 20 ++++++----- fs/ntfs/compress.c | 2 +- fs/ocfs2/cluster/tcp.c | 2 +- fs/ocfs2/dlm/dlmdomain.c | 2 +- fs/ocfs2/filecheck.c | 2 +- fs/proc/base.c | 3 +- fs/proc/task_mmu.c | 2 +- fs/read_write.c | 4 +-- fs/reiserfs/journal.c | 10 +++--- fs/select.c | 2 +- fs/splice.c | 7 ++-- fs/ubifs/journal.c | 2 +- fs/ubifs/lpt.c | 16 +++++---- fs/ubifs/super.c | 3 +- fs/ubifs/tnc.c | 5 +-- fs/ubifs/tnc_commit.c | 5 +-- fs/ufs/super.c | 2 +- kernel/cgroup/cgroup-v1.c | 2 +- kernel/cgroup/cpuset.c | 5 +-- kernel/debug/kdb/kdb_main.c | 9 ++--- kernel/locking/locktorture.c | 8 +++-- kernel/relay.c | 3 +- kernel/sched/fair.c | 3 +- kernel/sched/topology.c | 2 +- kernel/trace/ftrace.c | 24 +++++++------- kernel/trace/trace.c | 9 ++--- lib/argv_split.c | 2 +- lib/interval_tree_test.c | 5 +-- lib/kfifo.c | 2 +- lib/mpi/mpiutil.c | 2 +- lib/rbtree_test.c | 2 +- lib/reed_solomon/reed_solomon.c | 6 ++-- lib/scatterlist.c | 2 +- mm/huge_memory.c | 4 +-- mm/hugetlb.c | 3 +- mm/slub.c | 12 ++++--- net/9p/protocol.c | 11 ++++--- net/9p/trans_virtio.c | 3 +- net/atm/mpc.c | 2 +- net/bluetooth/hci_core.c | 2 +- net/bluetooth/l2cap_core.c | 2 +- net/can/bcm.c | 10 +++--- net/ceph/osdmap.c | 5 +-- net/ceph/pagevec.c | 4 +-- net/core/dev.c | 2 +- net/core/ethtool.c | 2 +- net/dcb/dcbnl.c | 3 +- net/dccp/ccids/ccid2.c | 3 +- net/ipv4/netfilter/nf_nat_snmp_basic.c | 2 +- net/ipv4/route.c | 3 +- net/mac80211/main.c | 2 +- net/mac80211/rc80211_minstrel.c | 2 +- net/mac80211/rc80211_minstrel_ht.c | 2 +- net/netfilter/nf_conntrack_proto.c | 6 ++-- net/netfilter/nf_nat_core.c | 5 +-- net/netfilter/nf_tables_api.c | 4 +-- net/netlink/genetlink.c | 10 +++--- net/openvswitch/datapath.c | 5 +-- net/rds/info.c | 2 +- net/rxrpc/rxkad.c | 2 +- net/sctp/protocol.c | 2 +- net/sunrpc/auth_gss/auth_gss.c | 3 +- net/tipc/netlink_compat.c | 5 +-- sound/core/pcm_compat.c | 2 +- sound/core/pcm_native.c | 4 +-- sound/core/seq/seq_midi_emul.c | 2 +- sound/firewire/packets-buffer.c | 2 +- sound/oss/dmasound/dmasound_core.c | 2 +- sound/pci/cs46xx/cs46xx_lib.c | 7 ++-- sound/pci/cs46xx/dsp_spos.c | 4 ++- sound/pci/emu10k1/emufx.c | 6 ++-- sound/pci/hda/hda_codec.c | 4 +-- sound/pci/hda/hda_proc.c | 5 +-- sound/pci/via82xx.c | 4 ++- sound/pci/via82xx_modem.c | 4 ++- sound/pci/ymfpci/ymfpci_main.c | 4 +-- sound/soc/codecs/wm8904.c | 5 +-- sound/soc/codecs/wm8958-dsp2.c | 20 ++++++----- sound/usb/caiaq/audio.c | 7 ++-- sound/usb/format.c | 5 +-- sound/usb/line6/pcm.c | 4 +-- sound/usb/mixer.c | 2 +- sound/usb/pcm.c | 2 +- sound/usb/usx2y/usbusx2y.c | 2 +- sound/usb/usx2y/usbusx2yaudio.c | 7 ++-- techpack/audio/4.0/dsp/q6asm.c | 4 +-- techpack/audio/dsp/q6asm.c | 4 +-- 388 files changed, 1024 insertions(+), 783 deletions(-) diff --git a/arch/arm/kernel/sys_oabi-compat.c b/arch/arm/kernel/sys_oabi-compat.c index a87684532327..40da0872170f 100644 --- a/arch/arm/kernel/sys_oabi-compat.c +++ b/arch/arm/kernel/sys_oabi-compat.c @@ -287,7 +287,7 @@ asmlinkage long sys_oabi_epoll_wait(int epfd, return -EINVAL; if (!access_ok(VERIFY_WRITE, events, sizeof(*events) * maxevents)) return -EFAULT; - kbuf = kmalloc(sizeof(*kbuf) * maxevents, GFP_KERNEL); + kbuf = kmalloc_array(maxevents, sizeof(*kbuf), GFP_KERNEL); if (!kbuf) return -ENOMEM; fs = get_fs(); @@ -328,7 +328,7 @@ asmlinkage long sys_oabi_semtimedop(int semid, return -EINVAL; if (!access_ok(VERIFY_READ, tsops, sizeof(*tsops) * nsops)) return -EFAULT; - sops = kmalloc(sizeof(*sops) * nsops, GFP_KERNEL); + sops = kmalloc_array(nsops, sizeof(*sops), GFP_KERNEL); if (!sops) return -ENOMEM; err = 0; diff --git a/arch/arm/mm/pgd.c b/arch/arm/mm/pgd.c index 006421cc9257..10664bebd903 100644 --- a/arch/arm/mm/pgd.c +++ b/arch/arm/mm/pgd.c @@ -20,7 +20,7 @@ #include "mm.h" #ifdef CONFIG_ARM_LPAE -#define __pgd_alloc() kmalloc(PTRS_PER_PGD * sizeof(pgd_t), GFP_KERNEL) +#define __pgd_alloc() kmalloc_array(PTRS_PER_PGD, sizeof(pgd_t), GFP_KERNEL) #define __pgd_free(pgd) kfree(pgd) #else #define __pgd_alloc() (pgd_t *)__get_free_pages(GFP_KERNEL, 2) diff --git a/arch/arm/probes/kprobes/test-core.c b/arch/arm/probes/kprobes/test-core.c index a10d7187ad2c..a2bf5e1286b6 100644 --- a/arch/arm/probes/kprobes/test-core.c +++ b/arch/arm/probes/kprobes/test-core.c @@ -823,8 +823,9 @@ static int coverage_start_fn(const struct decode_header *h, void *args) static int coverage_start(const union decode_item *table) { - coverage.base = kmalloc(MAX_COVERAGE_ENTRIES * - sizeof(struct coverage_entry), GFP_KERNEL); + coverage.base = kmalloc_array(MAX_COVERAGE_ENTRIES, + sizeof(struct coverage_entry), + GFP_KERNEL); coverage.num_entries = 0; coverage.nesting = 0; return table_iter(table, coverage_start_fn, &coverage); diff --git a/arch/blackfin/mm/isram-driver.c b/arch/blackfin/mm/isram-driver.c index aaa1e64b753b..3aa8545f0351 100644 --- a/arch/blackfin/mm/isram-driver.c +++ b/arch/blackfin/mm/isram-driver.c @@ -370,7 +370,7 @@ static __init int isram_test_init(void) pr_info("INFO: testing %#x bytes (%p - %p)\n", test_len, l1inst, l1inst + test_len); - sdram = kmalloc(test_len * 2, GFP_KERNEL); + sdram = kmalloc_array(test_len, 2, GFP_KERNEL); if (!sdram) { sram_free(l1inst); pr_warning("SKIP: could not allocate sdram\n"); diff --git a/arch/cris/arch-v32/drivers/cryptocop.c b/arch/cris/arch-v32/drivers/cryptocop.c index d688fe117dca..fbe4dc49aabb 100644 --- a/arch/cris/arch-v32/drivers/cryptocop.c +++ b/arch/cris/arch-v32/drivers/cryptocop.c @@ -1533,7 +1533,9 @@ int cryptocop_new_session(cryptocop_session_id *sid, struct cryptocop_transform_ return -ENOMEM; } - sess->tfrm_ctx = kmalloc(no_tfrms * sizeof(struct cryptocop_transform_ctx), alloc_flag); + sess->tfrm_ctx = kmalloc_array(no_tfrms, + sizeof(struct cryptocop_transform_ctx), + alloc_flag); if (!sess->tfrm_ctx) { DEBUG_API(printk("cryptocop_new_session, kmalloc cryptocop_transform_ctx\n")); kfree(sess); @@ -2698,7 +2700,7 @@ static int cryptocop_ioctl_process(struct inode *inode, struct file *filp, unsig /* Map user pages for in and out data of the operation. */ noinpages = (((unsigned long int)(oper.indata + prev_ix) & ~PAGE_MASK) + oper.inlen - 1 - prev_ix + ~PAGE_MASK) >> PAGE_SHIFT; DEBUG(printk("cryptocop_ioctl_process: noinpages=%d\n", noinpages)); - inpages = kmalloc(noinpages * sizeof(struct page*), GFP_KERNEL); + inpages = kmalloc_array(noinpages, sizeof(struct page *), GFP_KERNEL); if (!inpages){ DEBUG_API(printk("cryptocop_ioctl_process: kmalloc inpages\n")); nooutpages = noinpages = 0; @@ -2708,7 +2710,8 @@ static int cryptocop_ioctl_process(struct inode *inode, struct file *filp, unsig if (oper.do_cipher){ nooutpages = (((unsigned long int)oper.cipher_outdata & ~PAGE_MASK) + oper.cipher_outlen - 1 + ~PAGE_MASK) >> PAGE_SHIFT; DEBUG(printk("cryptocop_ioctl_process: nooutpages=%d\n", nooutpages)); - outpages = kmalloc(nooutpages * sizeof(struct page*), GFP_KERNEL); + outpages = kmalloc_array(nooutpages, sizeof(struct page *), + GFP_KERNEL); if (!outpages){ DEBUG_API(printk("cryptocop_ioctl_process: kmalloc outpages\n")); nooutpages = noinpages = 0; @@ -2752,8 +2755,11 @@ static int cryptocop_ioctl_process(struct inode *inode, struct file *filp, unsig /* Add 6 to nooutpages to make room for possibly inserted buffers for storing digest and * csum output and splits when units are (dis-)connected. */ - cop->tfrm_op.indata = kmalloc((noinpages) * sizeof(struct iovec), GFP_KERNEL); - cop->tfrm_op.outdata = kmalloc((6 + nooutpages) * sizeof(struct iovec), GFP_KERNEL); + cop->tfrm_op.indata = kmalloc_array(noinpages, sizeof(struct iovec), + GFP_KERNEL); + cop->tfrm_op.outdata = kmalloc_array(6 + nooutpages, + sizeof(struct iovec), + GFP_KERNEL); if (!cop->tfrm_op.indata || !cop->tfrm_op.outdata) { DEBUG_API(printk("cryptocop_ioctl_process: kmalloc iovecs\n")); err = -ENOMEM; diff --git a/arch/ia64/kernel/mca_drv.c b/arch/ia64/kernel/mca_drv.c index 94f8bf777afa..dfe40cbdf3b3 100644 --- a/arch/ia64/kernel/mca_drv.c +++ b/arch/ia64/kernel/mca_drv.c @@ -350,7 +350,8 @@ init_record_index_pools(void) /* - 3 - */ slidx_pool.max_idx = (rec_max_size/sect_min_size) * 2 + 1; slidx_pool.buffer = - kmalloc(slidx_pool.max_idx * sizeof(slidx_list_t), GFP_KERNEL); + kmalloc_array(slidx_pool.max_idx, sizeof(slidx_list_t), + GFP_KERNEL); return slidx_pool.buffer ? 0 : -ENOMEM; } diff --git a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c index 46ecc5d948aa..acf10eb9da15 100644 --- a/arch/ia64/mm/tlb.c +++ b/arch/ia64/mm/tlb.c @@ -430,8 +430,9 @@ int ia64_itr_entry(u64 target_mask, u64 va, u64 pte, u64 log_size) int cpu = smp_processor_id(); if (!ia64_idtrs[cpu]) { - ia64_idtrs[cpu] = kmalloc(2 * IA64_TR_ALLOC_MAX * - sizeof (struct ia64_tr_entry), GFP_KERNEL); + ia64_idtrs[cpu] = kmalloc_array(2 * IA64_TR_ALLOC_MAX, + sizeof(struct ia64_tr_entry), + GFP_KERNEL); if (!ia64_idtrs[cpu]) return -ENOMEM; } diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c index 85d095154902..d9b576df4f82 100644 --- a/arch/ia64/sn/kernel/irq.c +++ b/arch/ia64/sn/kernel/irq.c @@ -474,7 +474,8 @@ void __init sn_irq_lh_init(void) { int i; - sn_irq_lh = kmalloc(sizeof(struct list_head *) * NR_IRQS, GFP_KERNEL); + sn_irq_lh = kmalloc_array(NR_IRQS, sizeof(struct list_head *), + GFP_KERNEL); if (!sn_irq_lh) panic("SN PCI INIT: Failed to allocate memory for PCI init\n"); diff --git a/arch/mips/alchemy/common/dbdma.c b/arch/mips/alchemy/common/dbdma.c index fc482d900ddd..067a7bd17182 100644 --- a/arch/mips/alchemy/common/dbdma.c +++ b/arch/mips/alchemy/common/dbdma.c @@ -411,8 +411,8 @@ u32 au1xxx_dbdma_ring_alloc(u32 chanid, int entries) * and if we try that first we are likely to not waste larger * slabs of memory. */ - desc_base = (u32)kmalloc(entries * sizeof(au1x_ddma_desc_t), - GFP_KERNEL|GFP_DMA); + desc_base = (u32) kmalloc_array(entries, sizeof(au1x_ddma_desc_t), + GFP_KERNEL|GFP_DMA); if (desc_base == 0) return 0; diff --git a/arch/powerpc/lib/rheap.c b/arch/powerpc/lib/rheap.c index 94058c21a482..6aa774aa5b16 100644 --- a/arch/powerpc/lib/rheap.c +++ b/arch/powerpc/lib/rheap.c @@ -54,7 +54,7 @@ static int grow(rh_info_t * info, int max_blocks) new_blocks = max_blocks - info->max_blocks; - block = kmalloc(sizeof(rh_block_t) * max_blocks, GFP_ATOMIC); + block = kmalloc_array(max_blocks, sizeof(rh_block_t), GFP_ATOMIC); if (block == NULL) return -ENOMEM; diff --git a/arch/powerpc/platforms/4xx/hsta_msi.c b/arch/powerpc/platforms/4xx/hsta_msi.c index 9926ad67af76..1c18f2955f7d 100644 --- a/arch/powerpc/platforms/4xx/hsta_msi.c +++ b/arch/powerpc/platforms/4xx/hsta_msi.c @@ -156,7 +156,8 @@ static int hsta_msi_probe(struct platform_device *pdev) if (ret) goto out; - ppc4xx_hsta_msi.irq_map = kmalloc(sizeof(int) * irq_count, GFP_KERNEL); + ppc4xx_hsta_msi.irq_map = kmalloc_array(irq_count, sizeof(int), + GFP_KERNEL); if (!ppc4xx_hsta_msi.irq_map) { ret = -ENOMEM; goto out1; diff --git a/arch/powerpc/platforms/4xx/msi.c b/arch/powerpc/platforms/4xx/msi.c index d50417e23add..79a953af2d62 100644 --- a/arch/powerpc/platforms/4xx/msi.c +++ b/arch/powerpc/platforms/4xx/msi.c @@ -89,7 +89,7 @@ static int ppc4xx_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) if (type == PCI_CAP_ID_MSIX) pr_debug("ppc4xx msi: MSI-X untested, trying anyway.\n"); - msi_data->msi_virqs = kmalloc((msi_irqs) * sizeof(int), GFP_KERNEL); + msi_data->msi_virqs = kmalloc_array(msi_irqs, sizeof(int), GFP_KERNEL); if (!msi_data->msi_virqs) return -ENOMEM; diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 205dec18d6b5..62e1b4321b58 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -1641,8 +1641,9 @@ void __init mpic_init(struct mpic *mpic) #ifdef CONFIG_PM /* allocate memory to save mpic state */ - mpic->save_data = kmalloc(mpic->num_sources * sizeof(*mpic->save_data), - GFP_KERNEL); + mpic->save_data = kmalloc_array(mpic->num_sources, + sizeof(*mpic->save_data), + GFP_KERNEL); BUG_ON(mpic->save_data == NULL); #endif diff --git a/arch/s390/hypfs/hypfs_diag0c.c b/arch/s390/hypfs/hypfs_diag0c.c index dce87f1bec94..cebf05150cc1 100644 --- a/arch/s390/hypfs/hypfs_diag0c.c +++ b/arch/s390/hypfs/hypfs_diag0c.c @@ -49,7 +49,8 @@ static void *diag0c_store(unsigned int *count) get_online_cpus(); cpu_count = num_online_cpus(); - cpu_vec = kmalloc(sizeof(*cpu_vec) * num_possible_cpus(), GFP_KERNEL); + cpu_vec = kmalloc_array(num_possible_cpus(), sizeof(*cpu_vec), + GFP_KERNEL); if (!cpu_vec) goto fail_put_online_cpus; /* Note: Diag 0c needs 8 byte alignment and real storage */ diff --git a/arch/s390/include/asm/idals.h b/arch/s390/include/asm/idals.h index 15578fd762f6..ba5cf3cbf2a6 100644 --- a/arch/s390/include/asm/idals.h +++ b/arch/s390/include/asm/idals.h @@ -77,8 +77,8 @@ set_normalized_cda(struct ccw1 * ccw, void *vaddr) return -EINVAL; nridaws = idal_nr_words(vaddr, ccw->count); if (nridaws > 0) { - idal = kmalloc(nridaws * sizeof(unsigned long), - GFP_ATOMIC | GFP_DMA ); + idal = kmalloc_array(nridaws, sizeof(unsigned long), + GFP_ATOMIC | GFP_DMA ); if (idal == NULL) return -ENOMEM; idal_create_words(idal, vaddr, ccw->count); diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c index 05a9cf4ae9c2..6b8d06f425b5 100644 --- a/arch/s390/kernel/debug.c +++ b/arch/s390/kernel/debug.c @@ -197,14 +197,14 @@ debug_areas_alloc(int pages_per_area, int nr_areas) debug_entry_t*** areas; int i,j; - areas = kmalloc(nr_areas * - sizeof(debug_entry_t**), + areas = kmalloc_array(nr_areas, sizeof(debug_entry_t **), GFP_KERNEL); if (!areas) goto fail_malloc_areas; for (i = 0; i < nr_areas; i++) { - areas[i] = kmalloc(pages_per_area * - sizeof(debug_entry_t*),GFP_KERNEL); + areas[i] = kmalloc_array(pages_per_area, + sizeof(debug_entry_t *), + GFP_KERNEL); if (!areas[i]) { goto fail_malloc_areas2; } diff --git a/arch/s390/kernel/perf_cpum_cf_events.c b/arch/s390/kernel/perf_cpum_cf_events.c index 08bfa17ba0a0..fb8a769c7f22 100644 --- a/arch/s390/kernel/perf_cpum_cf_events.c +++ b/arch/s390/kernel/perf_cpum_cf_events.c @@ -390,7 +390,7 @@ static __init struct attribute **merge_attr(struct attribute **a, j++; j++; - new = kmalloc(sizeof(struct attribute *) * j, GFP_KERNEL); + new = kmalloc_array(j, sizeof(struct attribute *), GFP_KERNEL); if (!new) return NULL; j = 0; diff --git a/arch/s390/mm/extmem.c b/arch/s390/mm/extmem.c index 290e71e57541..84111a43ea29 100644 --- a/arch/s390/mm/extmem.c +++ b/arch/s390/mm/extmem.c @@ -103,7 +103,7 @@ static int scode_set; static int dcss_set_subcodes(void) { - char *name = kmalloc(8 * sizeof(char), GFP_KERNEL | GFP_DMA); + char *name = kmalloc(8, GFP_KERNEL | GFP_DMA); unsigned long rx, ry; int rc; diff --git a/arch/sparc/kernel/nmi.c b/arch/sparc/kernel/nmi.c index 048ad783ea3f..8babbeb30adf 100644 --- a/arch/sparc/kernel/nmi.c +++ b/arch/sparc/kernel/nmi.c @@ -166,7 +166,8 @@ static int __init check_nmi_watchdog(void) if (!atomic_read(&nmi_active)) return 0; - prev_nmi_count = kmalloc(nr_cpu_ids * sizeof(unsigned int), GFP_KERNEL); + prev_nmi_count = kmalloc_array(nr_cpu_ids, sizeof(unsigned int), + GFP_KERNEL); if (!prev_nmi_count) { err = -ENOMEM; goto error; diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c index d79c1c74873c..fb228d16b1d7 100644 --- a/arch/sparc/kernel/sys_sparc_64.c +++ b/arch/sparc/kernel/sys_sparc_64.c @@ -587,8 +587,9 @@ SYSCALL_DEFINE5(utrap_install, utrap_entry_t, type, unsigned long *p = current_thread_info()->utraps; current_thread_info()->utraps = - kmalloc((UT_TRAP_INSTRUCTION_31+1)*sizeof(long), - GFP_KERNEL); + kmalloc_array(UT_TRAP_INSTRUCTION_31 + 1, + sizeof(long), + GFP_KERNEL); if (!current_thread_info()->utraps) { current_thread_info()->utraps = p; return -ENOMEM; diff --git a/arch/sparc/net/bpf_jit_comp_32.c b/arch/sparc/net/bpf_jit_comp_32.c index 3bd8ca95e521..a5ff88643d5c 100644 --- a/arch/sparc/net/bpf_jit_comp_32.c +++ b/arch/sparc/net/bpf_jit_comp_32.c @@ -335,7 +335,7 @@ void bpf_jit_compile(struct bpf_prog *fp) if (!bpf_jit_enable) return; - addrs = kmalloc(flen * sizeof(*addrs), GFP_KERNEL); + addrs = kmalloc_array(flen, sizeof(*addrs), GFP_KERNEL); if (addrs == NULL) return; diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index b55fe9bf5d3e..cf7126c095eb 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -1139,9 +1139,9 @@ static int __init ubd_init(void) return -1; } - irq_req_buffer = kmalloc( - sizeof(struct io_thread_req *) * UBD_REQ_BUFFER_SIZE, - GFP_KERNEL + irq_req_buffer = kmalloc_array(UBD_REQ_BUFFER_SIZE, + sizeof(struct io_thread_req *), + GFP_KERNEL ); irq_remainder = 0; @@ -1149,9 +1149,9 @@ static int __init ubd_init(void) printk(KERN_ERR "Failed to initialize ubd buffering\n"); return -1; } - io_req_buffer = kmalloc( - sizeof(struct io_thread_req *) * UBD_REQ_BUFFER_SIZE, - GFP_KERNEL + io_req_buffer = kmalloc_array(UBD_REQ_BUFFER_SIZE, + sizeof(struct io_thread_req *), + GFP_KERNEL ); io_remainder = 0; diff --git a/arch/unicore32/kernel/pm.c b/arch/unicore32/kernel/pm.c index 784bc2db3b28..6f8164d91dc2 100644 --- a/arch/unicore32/kernel/pm.c +++ b/arch/unicore32/kernel/pm.c @@ -109,8 +109,9 @@ static int __init puv3_pm_init(void) return -EINVAL; } - sleep_save = kmalloc(puv3_cpu_pm_fns->save_count - * sizeof(unsigned long), GFP_KERNEL); + sleep_save = kmalloc_array(puv3_cpu_pm_fns->save_count, + sizeof(unsigned long), + GFP_KERNEL); if (!sleep_save) { printk(KERN_ERR "failed to alloc memory for pm save\n"); return -ENOMEM; diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c index c1f7b3cb84a9..7a60f48e631a 100644 --- a/arch/x86/events/core.c +++ b/arch/x86/events/core.c @@ -1615,7 +1615,7 @@ __init struct attribute **merge_attr(struct attribute **a, struct attribute **b) j++; j++; - new = kmalloc(sizeof(struct attribute *) * j, GFP_KERNEL); + new = kmalloc_array(j, sizeof(struct attribute *), GFP_KERNEL); if (!new) return NULL; diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index df767e6de8dd..7e26c1eaf00d 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c @@ -969,8 +969,8 @@ int __init hpet_enable(void) #endif cfg = hpet_readl(HPET_CFG); - hpet_boot_cfg = kmalloc((last + 2) * sizeof(*hpet_boot_cfg), - GFP_KERNEL); + hpet_boot_cfg = kmalloc_array(last + 2, sizeof(*hpet_boot_cfg), + GFP_KERNEL); if (hpet_boot_cfg) *hpet_boot_cfg = cfg; else diff --git a/arch/x86/kernel/ksysfs.c b/arch/x86/kernel/ksysfs.c index 8c1cc08f514f..163ae706a0d4 100644 --- a/arch/x86/kernel/ksysfs.c +++ b/arch/x86/kernel/ksysfs.c @@ -283,7 +283,7 @@ static int __init create_setup_data_nodes(struct kobject *parent) if (ret) goto out_setup_data_kobj; - kobjp = kmalloc(sizeof(*kobjp) * nr, GFP_KERNEL); + kobjp = kmalloc_array(nr, sizeof(*kobjp), GFP_KERNEL); if (!kobjp) { ret = -ENOMEM; goto out_setup_data_kobj; diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c index 14a043f66669..2dfbe49947fc 100644 --- a/arch/x86/net/bpf_jit_comp.c +++ b/arch/x86/net/bpf_jit_comp.c @@ -1146,7 +1146,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog) prog = tmp; } - addrs = kmalloc(prog->len * sizeof(*addrs), GFP_KERNEL); + addrs = kmalloc_array(prog->len, sizeof(*addrs), GFP_KERNEL); if (!addrs) { prog = orig_prog; goto out; diff --git a/arch/x86/platform/uv/tlb_uv.c b/arch/x86/platform/uv/tlb_uv.c index 34f9a9ce6236..cff0550ad391 100644 --- a/arch/x86/platform/uv/tlb_uv.c +++ b/arch/x86/platform/uv/tlb_uv.c @@ -2142,7 +2142,7 @@ static int __init init_per_cpu(int nuvhubs, int base_part_pnode) if (is_uv3_hub() || is_uv2_hub() || is_uv1_hub()) timeout_us = calculate_destination_timeout(); - vp = kmalloc(nuvhubs * sizeof(struct uvhub_desc), GFP_KERNEL); + vp = kmalloc_array(nuvhubs, sizeof(struct uvhub_desc), GFP_KERNEL); uvhub_descs = (struct uvhub_desc *)vp; memset(uvhub_descs, 0, nuvhubs * sizeof(struct uvhub_desc)); uvhub_mask = kzalloc((nuvhubs+7)/8, GFP_KERNEL); diff --git a/block/partitions/ldm.c b/block/partitions/ldm.c index 2a365c756648..0417937dfe99 100644 --- a/block/partitions/ldm.c +++ b/block/partitions/ldm.c @@ -378,7 +378,7 @@ static bool ldm_validate_tocblocks(struct parsed_partitions *state, BUG_ON(!state || !ldb); ph = &ldb->ph; tb[0] = &ldb->toc; - tb[1] = kmalloc(sizeof(*tb[1]) * 3, GFP_KERNEL); + tb[1] = kmalloc_array(3, sizeof(*tb[1]), GFP_KERNEL); if (!tb[1]) { ldm_crit("Out of memory."); goto err; diff --git a/crypto/testmgr.c b/crypto/testmgr.c index db88375bb40a..2074532a355d 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -604,7 +604,8 @@ static int __test_aead(struct crypto_aead *tfm, int enc, goto out_nooutbuf; /* avoid "the frame size is larger than 1024 bytes" compiler warning */ - sg = kmalloc(sizeof(*sg) * 8 * (diff_dst ? 4 : 2), GFP_KERNEL); + sg = kmalloc(array3_size(sizeof(*sg), 8, (diff_dst ? 4 : 2)), + GFP_KERNEL); if (!sg) goto out_nosg; sgout = &sg[16]; diff --git a/drivers/acpi/acpi_video.c b/drivers/acpi/acpi_video.c index 7df7abde1fcb..45e4a1f4b36b 100644 --- a/drivers/acpi/acpi_video.c +++ b/drivers/acpi/acpi_video.c @@ -861,8 +861,9 @@ int acpi_video_get_levels(struct acpi_device *device, * in order to account for buggy BIOS which don't export the first two * special levels (see below) */ - br->levels = kmalloc((obj->package.count + ACPI_VIDEO_FIRST_LEVEL) * - sizeof(*br->levels), GFP_KERNEL); + br->levels = kmalloc_array(obj->package.count + ACPI_VIDEO_FIRST_LEVEL, + sizeof(*br->levels), + GFP_KERNEL); if (!br->levels) { result = -ENOMEM; goto out_free; diff --git a/drivers/acpi/apei/hest.c b/drivers/acpi/apei/hest.c index 9cb74115a43d..b1e9f81ebeea 100644 --- a/drivers/acpi/apei/hest.c +++ b/drivers/acpi/apei/hest.c @@ -195,7 +195,8 @@ static int __init hest_ghes_dev_register(unsigned int ghes_count) struct ghes_arr ghes_arr; ghes_arr.count = 0; - ghes_arr.ghes_devs = kmalloc(sizeof(void *) * ghes_count, GFP_KERNEL); + ghes_arr.ghes_devs = kmalloc_array(ghes_count, sizeof(void *), + GFP_KERNEL); if (!ghes_arr.ghes_devs) return -ENOMEM; diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index c7cf48ad5cb9..588a8b27d4e1 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c @@ -343,8 +343,9 @@ static int acpi_processor_get_performance_states(struct acpi_processor *pr) pr->performance->state_count = pss->package.count; pr->performance->states = - kmalloc(sizeof(struct acpi_processor_px) * pss->package.count, - GFP_KERNEL); + kmalloc_array(pss->package.count, + sizeof(struct acpi_processor_px), + GFP_KERNEL); if (!pr->performance->states) { result = -ENOMEM; goto end; diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index 9fdc13a2f2d5..62c0fe9ef412 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c @@ -534,8 +534,9 @@ static int acpi_processor_get_throttling_states(struct acpi_processor *pr) pr->throttling.state_count = tss->package.count; pr->throttling.states_tss = - kmalloc(sizeof(struct acpi_processor_tx_tss) * tss->package.count, - GFP_KERNEL); + kmalloc_array(tss->package.count, + sizeof(struct acpi_processor_tx_tss), + GFP_KERNEL); if (!pr->throttling.states_tss) { result = -ENOMEM; goto end; diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index 0df1a1c80b00..17283018269f 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -1291,7 +1291,8 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) card->using_dma = 1; if (1) { /* All known FPGA versions so far */ card->dma_alignment = 3; - card->dma_bounce = kmalloc(card->nr_ports * BUF_SIZE, GFP_KERNEL); + card->dma_bounce = kmalloc_array(card->nr_ports, + BUF_SIZE, GFP_KERNEL); if (!card->dma_bounce) { dev_warn(&card->dev->dev, "Failed to allocate DMA bounce buffers\n"); err = -ENOMEM; diff --git a/drivers/auxdisplay/cfag12864b.c b/drivers/auxdisplay/cfag12864b.c index 41ce4bd96813..d688e94635bb 100644 --- a/drivers/auxdisplay/cfag12864b.c +++ b/drivers/auxdisplay/cfag12864b.c @@ -347,8 +347,8 @@ static int __init cfag12864b_init(void) goto none; } - cfag12864b_cache = kmalloc(sizeof(unsigned char) * - CFAG12864B_SIZE, GFP_KERNEL); + cfag12864b_cache = kmalloc(CFAG12864B_SIZE, + GFP_KERNEL); if (cfag12864b_cache == NULL) { printk(KERN_ERR CFAG12864B_NAME ": ERROR: " "can't alloc cache buffer (%i bytes)\n", diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c index 255591ab3716..33ed2f9ff70c 100644 --- a/drivers/block/DAC960.c +++ b/drivers/block/DAC960.c @@ -5727,8 +5727,8 @@ static bool DAC960_CheckStatusBuffer(DAC960_Controller_T *Controller, Controller->CombinedStatusBufferLength = NewStatusBufferLength; return true; } - NewStatusBuffer = kmalloc(2 * Controller->CombinedStatusBufferLength, - GFP_ATOMIC); + NewStatusBuffer = kmalloc_array(2, Controller->CombinedStatusBufferLength, + GFP_ATOMIC); if (NewStatusBuffer == NULL) { DAC960_Warning("Unable to expand Combined Status Buffer - Truncating\n", diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 71a25e3dec92..a1aaba8cbb83 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -513,7 +513,8 @@ static int lo_rw_aio(struct loop_device *lo, struct loop_cmd *cmd, __rq_for_each_bio(bio, rq) segments += bio_segments(bio); - bvec = kmalloc(sizeof(struct bio_vec) * segments, GFP_NOIO); + bvec = kmalloc_array(segments, sizeof(struct bio_vec), + GFP_NOIO); if (!bvec) return -EIO; cmd->bvec = bvec; diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c index 41c95c9b2ab4..87cefee10f36 100644 --- a/drivers/block/z2ram.c +++ b/drivers/block/z2ram.c @@ -197,8 +197,9 @@ static int z2_open(struct block_device *bdev, fmode_t mode) vaddr = (unsigned long)z_remap_nocache_nonser(paddr, size); #endif z2ram_map = - kmalloc((size/Z2RAM_CHUNKSIZE)*sizeof(z2ram_map[0]), - GFP_KERNEL); + kmalloc_array(size / Z2RAM_CHUNKSIZE, + sizeof(z2ram_map[0]), + GFP_KERNEL); if ( z2ram_map == NULL ) { printk( KERN_ERR DEVICE_NAME diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index 1c90da4af94f..229dae26758a 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -2139,7 +2139,7 @@ static int cdrom_read_cdda_old(struct cdrom_device_info *cdi, __u8 __user *ubuf, */ nr = nframes; do { - cgc.buffer = kmalloc(CD_FRAMESIZE_RAW * nr, GFP_KERNEL); + cgc.buffer = kmalloc_array(nr, CD_FRAMESIZE_RAW, GFP_KERNEL); if (cgc.buffer) break; diff --git a/drivers/char/agp/compat_ioctl.c b/drivers/char/agp/compat_ioctl.c index 2053f70ef66b..52ffe1706ce0 100644 --- a/drivers/char/agp/compat_ioctl.c +++ b/drivers/char/agp/compat_ioctl.c @@ -98,11 +98,15 @@ static int compat_agpioc_reserve_wrap(struct agp_file_private *priv, void __user if (ureserve.seg_count >= 16384) return -EINVAL; - usegment = kmalloc(sizeof(*usegment) * ureserve.seg_count, GFP_KERNEL); + usegment = kmalloc_array(ureserve.seg_count, + sizeof(*usegment), + GFP_KERNEL); if (!usegment) return -ENOMEM; - ksegment = kmalloc(sizeof(*ksegment) * kreserve.seg_count, GFP_KERNEL); + ksegment = kmalloc_array(kreserve.seg_count, + sizeof(*ksegment), + GFP_KERNEL); if (!ksegment) { kfree(usegment); return -ENOMEM; diff --git a/drivers/char/agp/isoch.c b/drivers/char/agp/isoch.c index fc8e1bc3347d..4d5241124406 100644 --- a/drivers/char/agp/isoch.c +++ b/drivers/char/agp/isoch.c @@ -93,7 +93,7 @@ static int agp_3_5_isochronous_node_enable(struct agp_bridge_data *bridge, * We'll work with an array of isoch_data's (one for each * device in dev_list) throughout this function. */ - if ((master = kmalloc(ndevs * sizeof(*master), GFP_KERNEL)) == NULL) { + if ((master = kmalloc_array(ndevs, sizeof(*master), GFP_KERNEL)) == NULL) { ret = -ENOMEM; goto get_out; } diff --git a/drivers/char/agp/sgi-agp.c b/drivers/char/agp/sgi-agp.c index 3051c73bc383..e7d5bdc02d93 100644 --- a/drivers/char/agp/sgi-agp.c +++ b/drivers/char/agp/sgi-agp.c @@ -280,9 +280,9 @@ static int agp_sgi_init(void) else return 0; - sgi_tioca_agp_bridges = kmalloc(tioca_gart_found * - sizeof(struct agp_bridge_data *), - GFP_KERNEL); + sgi_tioca_agp_bridges = kmalloc_array(tioca_gart_found, + sizeof(struct agp_bridge_data *), + GFP_KERNEL); if (!sgi_tioca_agp_bridges) return -ENOMEM; diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c index 79d8c84693a1..31fcd0430426 100644 --- a/drivers/char/agp/uninorth-agp.c +++ b/drivers/char/agp/uninorth-agp.c @@ -402,7 +402,9 @@ static int uninorth_create_gatt_table(struct agp_bridge_data *bridge) if (table == NULL) return -ENOMEM; - uninorth_priv.pages_arr = kmalloc((1 << page_order) * sizeof(struct page*), GFP_KERNEL); + uninorth_priv.pages_arr = kmalloc_array(1 << page_order, + sizeof(struct page *), + GFP_KERNEL); if (uninorth_priv.pages_arr == NULL) goto enomem; diff --git a/drivers/char/tile-srom.c b/drivers/char/tile-srom.c index 3d4cca64b2d4..8bc5c0f6c1c8 100644 --- a/drivers/char/tile-srom.c +++ b/drivers/char/tile-srom.c @@ -362,7 +362,7 @@ static int srom_init(void) * Start with a plausible number of partitions; the krealloc() call * below will yield about log(srom_devs) additional allocations. */ - srom_devices = kmalloc(4 * sizeof(struct srom_dev), GFP_KERNEL); + srom_devices = kmalloc_array(4, sizeof(struct srom_dev), GFP_KERNEL); /* Discover the number of srom partitions. */ for (i = 0; ; i++) { diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 6f0104d7c7a5..747d03b90011 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -1893,13 +1893,14 @@ static int init_vqs(struct ports_device *portdev) nr_ports = portdev->max_nr_ports; nr_queues = use_multiport(portdev) ? (nr_ports + 1) * 2 : 2; - vqs = kmalloc(nr_queues * sizeof(struct virtqueue *), GFP_KERNEL); - io_callbacks = kmalloc(nr_queues * sizeof(vq_callback_t *), GFP_KERNEL); - io_names = kmalloc(nr_queues * sizeof(char *), GFP_KERNEL); - portdev->in_vqs = kmalloc(nr_ports * sizeof(struct virtqueue *), - GFP_KERNEL); - portdev->out_vqs = kmalloc(nr_ports * sizeof(struct virtqueue *), - GFP_KERNEL); + vqs = kmalloc_array(nr_queues, sizeof(struct virtqueue *), GFP_KERNEL); + io_callbacks = kmalloc_array(nr_queues, sizeof(vq_callback_t *), + GFP_KERNEL); + io_names = kmalloc_array(nr_queues, sizeof(char *), GFP_KERNEL); + portdev->in_vqs = kmalloc_array(nr_ports, sizeof(struct virtqueue *), + GFP_KERNEL); + portdev->out_vqs = kmalloc_array(nr_ports, sizeof(struct virtqueue *), + GFP_KERNEL); if (!vqs || !io_callbacks || !io_names || !portdev->in_vqs || !portdev->out_vqs) { err = -ENOMEM; diff --git a/drivers/cpufreq/bmips-cpufreq.c b/drivers/cpufreq/bmips-cpufreq.c index 1653151b77df..56a4ebbf00e0 100644 --- a/drivers/cpufreq/bmips-cpufreq.c +++ b/drivers/cpufreq/bmips-cpufreq.c @@ -71,7 +71,7 @@ bmips_cpufreq_get_freq_table(const struct cpufreq_policy *policy) cpu_freq = htp_freq_to_cpu_freq(priv->clk_mult); - table = kmalloc((priv->max_freqs + 1) * sizeof(*table), GFP_KERNEL); + table = kmalloc_array(priv->max_freqs + 1, sizeof(*table), GFP_KERNEL); if (!table) return ERR_PTR(-ENOMEM); diff --git a/drivers/crypto/stm32/stm32-hash.c b/drivers/crypto/stm32/stm32-hash.c index 4909f820e953..230922ed6987 100644 --- a/drivers/crypto/stm32/stm32-hash.c +++ b/drivers/crypto/stm32/stm32-hash.c @@ -968,8 +968,9 @@ static int stm32_hash_export(struct ahash_request *req, void *out) while (!(stm32_hash_read(hdev, HASH_SR) & HASH_SR_DATA_INPUT_READY)) cpu_relax(); - rctx->hw_context = kmalloc(sizeof(u32) * (3 + HASH_CSR_REGISTER_NUMBER), - GFP_KERNEL); + rctx->hw_context = kmalloc_array(3 + HASH_CSR_REGISTER_NUMBER, + sizeof(u32), + GFP_KERNEL); preg = rctx->hw_context; diff --git a/drivers/dma/bestcomm/bestcomm.c b/drivers/dma/bestcomm/bestcomm.c index 7a67b8345092..d91cbbe7a48f 100644 --- a/drivers/dma/bestcomm/bestcomm.c +++ b/drivers/dma/bestcomm/bestcomm.c @@ -87,7 +87,8 @@ bcom_task_alloc(int bd_count, int bd_size, int priv_size) /* Init the BDs, if needed */ if (bd_count) { - tsk->cookie = kmalloc(sizeof(void*) * bd_count, GFP_KERNEL); + tsk->cookie = kmalloc_array(bd_count, sizeof(void *), + GFP_KERNEL); if (!tsk->cookie) goto error; diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c index 1c57577f49fe..25a52d8b7ee0 100644 --- a/drivers/dma/mv_xor.c +++ b/drivers/dma/mv_xor.c @@ -777,7 +777,7 @@ static int mv_chan_memcpy_self_test(struct mv_xor_chan *mv_chan) struct dmaengine_unmap_data *unmap; int err = 0; - src = kmalloc(sizeof(u8) * PAGE_SIZE, GFP_KERNEL); + src = kmalloc(PAGE_SIZE, GFP_KERNEL); if (!src) return -ENOMEM; diff --git a/drivers/firewire/core-iso.c b/drivers/firewire/core-iso.c index 38c0aa60b2cb..051327a951b1 100644 --- a/drivers/firewire/core-iso.c +++ b/drivers/firewire/core-iso.c @@ -45,8 +45,8 @@ int fw_iso_buffer_alloc(struct fw_iso_buffer *buffer, int page_count) buffer->page_count = 0; buffer->page_count_mapped = 0; - buffer->pages = kmalloc(page_count * sizeof(buffer->pages[0]), - GFP_KERNEL); + buffer->pages = kmalloc_array(page_count, sizeof(buffer->pages[0]), + GFP_KERNEL); if (buffer->pages == NULL) return -ENOMEM; diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c index 215f4f71b943..2479c5b475d1 100644 --- a/drivers/firewire/net.c +++ b/drivers/firewire/net.c @@ -1125,7 +1125,7 @@ static int fwnet_broadcast_start(struct fwnet_device *dev) max_receive = 1U << (dev->card->max_receive + 1); num_packets = (FWNET_ISO_PAGE_COUNT * PAGE_SIZE) / max_receive; - ptrptr = kmalloc(sizeof(void *) * num_packets, GFP_KERNEL); + ptrptr = kmalloc_array(num_packets, sizeof(void *), GFP_KERNEL); if (!ptrptr) { retval = -ENOMEM; goto failed; diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index df5fe163cfec..ee1a76e1a632 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -1618,7 +1618,8 @@ struct edid *drm_do_get_edid(struct drm_connector *connector, edid[EDID_LENGTH-1] += edid[0x7e] - valid_extensions; edid[0x7e] = valid_extensions; - new = kmalloc((valid_extensions + 1) * EDID_LENGTH, GFP_KERNEL); + new = kmalloc_array(valid_extensions + 1, EDID_LENGTH, + GFP_KERNEL); if (!new) goto out; diff --git a/drivers/gpu/drm/gma500/mid_bios.c b/drivers/gpu/drm/gma500/mid_bios.c index d75ecb3bdee7..a833568c782b 100644 --- a/drivers/gpu/drm/gma500/mid_bios.c +++ b/drivers/gpu/drm/gma500/mid_bios.c @@ -235,7 +235,7 @@ static int mid_get_vbt_data_r10(struct drm_psb_private *dev_priv, u32 addr) if (read_vbt_r10(addr, &vbt)) return -1; - gct = kmalloc(sizeof(*gct) * vbt.panel_count, GFP_KERNEL); + gct = kmalloc_array(vbt.panel_count, sizeof(*gct), GFP_KERNEL); if (!gct) return -1; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/iccsense.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/iccsense.c index 23caef8df17f..12b5046ac475 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/iccsense.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/iccsense.c @@ -73,7 +73,8 @@ nvbios_iccsense_parse(struct nvkm_bios *bios, struct nvbios_iccsense *iccsense) } iccsense->nr_entry = cnt; - iccsense->rail = kmalloc(sizeof(struct pwr_rail_t) * cnt, GFP_KERNEL); + iccsense->rail = kmalloc_array(cnt, sizeof(struct pwr_rail_t), + GFP_KERNEL); if (!iccsense->rail) return -ENOMEM; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c index f10664372161..0cf2098b3ebe 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c @@ -170,7 +170,7 @@ gt215_link_train(struct gt215_ram *ram) return -ENOSYS; /* XXX: Multiple partitions? */ - result = kmalloc(64 * sizeof(u32), GFP_KERNEL); + result = kmalloc_array(64, sizeof(u32), GFP_KERNEL); if (!result) return -ENOMEM; diff --git a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c index 32901c6fe3df..46d2621b988e 100644 --- a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c +++ b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c @@ -939,8 +939,8 @@ int tiler_map_show(struct seq_file *s, void *arg) h_adj = omap_dmm->container_height / ydiv; w_adj = omap_dmm->container_width / xdiv; - map = kmalloc(h_adj * sizeof(*map), GFP_KERNEL); - global_map = kmalloc((w_adj + 1) * h_adj, GFP_KERNEL); + map = kmalloc_array(h_adj, sizeof(*map), GFP_KERNEL); + global_map = kmalloc_array(w_adj + 1, h_adj, GFP_KERNEL); if (!map || !global_map) goto error; diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c index 5c5c86ddd6f4..ef55fcaa4e50 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem.c +++ b/drivers/gpu/drm/omapdrm/omap_gem.c @@ -246,7 +246,7 @@ static int omap_gem_attach_pages(struct drm_gem_object *obj) * DSS, GPU, etc. are not cache coherent: */ if (omap_obj->flags & (OMAP_BO_WC|OMAP_BO_UNCACHED)) { - addrs = kmalloc(npages * sizeof(*addrs), GFP_KERNEL); + addrs = kmalloc_array(npages, sizeof(*addrs), GFP_KERNEL); if (!addrs) { ret = -ENOMEM; goto free_pages; diff --git a/drivers/gpu/drm/qxl/qxl_kms.c b/drivers/gpu/drm/qxl/qxl_kms.c index 20ca0a75e685..2412d317d992 100644 --- a/drivers/gpu/drm/qxl/qxl_kms.c +++ b/drivers/gpu/drm/qxl/qxl_kms.c @@ -200,8 +200,8 @@ int qxl_device_init(struct qxl_device *qdev, (~(uint64_t)0) >> (qdev->slot_id_bits + qdev->slot_gen_bits); qdev->mem_slots = - kmalloc(qdev->n_mem_slots * sizeof(struct qxl_memslot), - GFP_KERNEL); + kmalloc_array(qdev->n_mem_slots, sizeof(struct qxl_memslot), + GFP_KERNEL); idr_init(&qdev->release_idr); spin_lock_init(&qdev->release_idr_lock); diff --git a/drivers/gpu/drm/savage/savage_bci.c b/drivers/gpu/drm/savage/savage_bci.c index 2a5b8466d806..35dc74883f83 100644 --- a/drivers/gpu/drm/savage/savage_bci.c +++ b/drivers/gpu/drm/savage/savage_bci.c @@ -298,8 +298,9 @@ static int savage_dma_init(drm_savage_private_t * dev_priv) dev_priv->nr_dma_pages = dev_priv->cmd_dma->size / (SAVAGE_DMA_PAGE_SIZE * 4); - dev_priv->dma_pages = kmalloc(sizeof(drm_savage_dma_page_t) * - dev_priv->nr_dma_pages, GFP_KERNEL); + dev_priv->dma_pages = kmalloc_array(dev_priv->nr_dma_pages, + sizeof(drm_savage_dma_page_t), + GFP_KERNEL); if (dev_priv->dma_pages == NULL) return -ENOMEM; diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c b/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c index 623a9140493c..84d765866ffb 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c @@ -32,8 +32,8 @@ static int __init kfree_table_init(struct kfree_table *kft) { kft->total = 32; kft->num = 0; - kft->table = kmalloc(kft->total * sizeof(*kft->table), - GFP_KERNEL); + kft->table = kmalloc_array(kft->total, sizeof(*kft->table), + GFP_KERNEL); if (!kft->table) return -ENOMEM; diff --git a/drivers/gpu/drm/tinydrm/repaper.c b/drivers/gpu/drm/tinydrm/repaper.c index 30dc97b3ff21..cd36ec4e862a 100644 --- a/drivers/gpu/drm/tinydrm/repaper.c +++ b/drivers/gpu/drm/tinydrm/repaper.c @@ -554,7 +554,7 @@ static int repaper_fb_dirty(struct drm_framebuffer *fb, DRM_DEBUG("Flushing [FB:%d] st=%ums\n", fb->base.id, epd->factored_stage_time); - buf = kmalloc(fb->width * fb->height, GFP_KERNEL); + buf = kmalloc_array(fb->width, fb->height, GFP_KERNEL); if (!buf) { ret = -ENOMEM; goto out_unlock; diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c b/drivers/gpu/drm/ttm/ttm_page_alloc.c index 91f9263f3c3b..b84e0d0023e4 100644 --- a/drivers/gpu/drm/ttm/ttm_page_alloc.c +++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c @@ -318,8 +318,9 @@ static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free, if (use_static) pages_to_free = static_buf; else - pages_to_free = kmalloc(npages_to_free * sizeof(struct page *), - GFP_KERNEL); + pages_to_free = kmalloc_array(npages_to_free, + sizeof(struct page *), + GFP_KERNEL); if (!pages_to_free) { pr_err("Failed to allocate memory for pool free operation\n"); return 0; @@ -504,7 +505,8 @@ static int ttm_alloc_new_pages(struct list_head *pages, gfp_t gfp_flags, (unsigned)(PAGE_SIZE/sizeof(struct page *))); /* allocate array for page caching change */ - caching_array = kmalloc(max_cpages*sizeof(struct page *), GFP_KERNEL); + caching_array = kmalloc_array(max_cpages, sizeof(struct page *), + GFP_KERNEL); if (!caching_array) { pr_err("Unable to allocate table for new pages\n"); diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c index 90ddbdca93bd..bc824c8e089f 100644 --- a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c +++ b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c @@ -442,8 +442,9 @@ static unsigned ttm_dma_page_pool_free(struct dma_pool *pool, unsigned nr_free, if (use_static) pages_to_free = static_buf; else - pages_to_free = kmalloc(npages_to_free * sizeof(struct page *), - GFP_KERNEL); + pages_to_free = kmalloc_array(npages_to_free, + sizeof(struct page *), + GFP_KERNEL); if (!pages_to_free) { pr_err("%s: Failed to allocate memory for pool free operation\n", @@ -729,7 +730,8 @@ static int ttm_dma_pool_alloc_new_pages(struct dma_pool *pool, (unsigned)(PAGE_SIZE/sizeof(struct page *))); /* allocate array for page caching change */ - caching_array = kmalloc(max_cpages*sizeof(struct page *), GFP_KERNEL); + caching_array = kmalloc_array(max_cpages, sizeof(struct page *), + GFP_KERNEL); if (!caching_array) { pr_err("%s: Unable to allocate table for new pages\n", diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index 6277a3f2d5d1..01966db9eb34 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c @@ -241,7 +241,7 @@ static void vc4_dlist_write(struct vc4_plane_state *vc4_state, u32 val) { if (vc4_state->dlist_count == vc4_state->dlist_size) { u32 new_size = max(4u, vc4_state->dlist_count * 2); - u32 *new_dlist = kmalloc(new_size * 4, GFP_KERNEL); + u32 *new_dlist = kmalloc_array(new_size, 4, GFP_KERNEL); if (!new_dlist) return; diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index b8ada634c977..c790c1e0be83 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -131,8 +131,8 @@ static int open_collection(struct hid_parser *parser, unsigned type) } if (parser->device->maxcollection == parser->device->collection_size) { - collection = kmalloc(sizeof(struct hid_collection) * - parser->device->collection_size * 2, GFP_KERNEL); + collection = kmalloc(array3_size(sizeof(struct hid_collection), parser->device->collection_size, 2), + GFP_KERNEL); if (collection == NULL) { hid_err(parser->device, "failed to reallocate collection array\n"); return -ENOMEM; @@ -1360,7 +1360,7 @@ static void hid_input_field(struct hid_device *hid, struct hid_field *field, __s32 max = field->logical_maximum; __s32 *value; - value = kmalloc(sizeof(__s32) * count, GFP_ATOMIC); + value = kmalloc_array(count, sizeof(__s32), GFP_ATOMIC); if (!value) return; diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c index a0bcbb633b67..b96d5f0d1524 100644 --- a/drivers/hid/hid-debug.c +++ b/drivers/hid/hid-debug.c @@ -681,7 +681,7 @@ void hid_dump_report(struct hid_device *hid, int type, u8 *data, char *buf; unsigned int i; - buf = kmalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_ATOMIC); + buf = kmalloc(HID_DEBUG_BUFSIZE, GFP_ATOMIC); if (!buf) return; diff --git a/drivers/hid/hid-picolcd_fb.c b/drivers/hid/hid-picolcd_fb.c index 7f965e231433..864a084b6cba 100644 --- a/drivers/hid/hid-picolcd_fb.c +++ b/drivers/hid/hid-picolcd_fb.c @@ -394,7 +394,8 @@ static int picolcd_set_par(struct fb_info *info) return -EINVAL; o_fb = fbdata->bitmap; - tmp_fb = kmalloc(PICOLCDFB_SIZE*info->var.bits_per_pixel, GFP_KERNEL); + tmp_fb = kmalloc_array(PICOLCDFB_SIZE, info->var.bits_per_pixel, + GFP_KERNEL); if (!tmp_fb) return -ENOMEM; diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index 5243c4120819..ac8a3f5926d5 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c @@ -218,7 +218,7 @@ static ssize_t hidraw_get_report(struct file *file, char __user *buffer, size_t goto out; } - buf = kmalloc(count * sizeof(__u8), GFP_KERNEL); + buf = kmalloc(count, GFP_KERNEL); if (!buf) { ret = -ENOMEM; goto out; diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index c4066276eb7b..dd7dd7daba63 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c @@ -262,7 +262,8 @@ static noinline int i2cdev_ioctl_rdwr(struct i2c_client *client, if (IS_ERR(rdwr_pa)) return PTR_ERR(rdwr_pa); - data_ptrs = kmalloc(rdwr_arg.nmsgs * sizeof(u8 __user *), GFP_KERNEL); + data_ptrs = kmalloc_array(rdwr_arg.nmsgs, sizeof(u8 __user *), + GFP_KERNEL); if (data_ptrs == NULL) { kfree(rdwr_pa); return -ENOMEM; diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index eaf39e5db08b..cb0f42102a63 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -989,8 +989,9 @@ static int hwif_init(ide_hwif_t *hwif) if (!hwif->sg_max_nents) hwif->sg_max_nents = PRD_ENTRIES; - hwif->sg_table = kmalloc(sizeof(struct scatterlist)*hwif->sg_max_nents, - GFP_KERNEL); + hwif->sg_table = kmalloc_array(hwif->sg_max_nents, + sizeof(struct scatterlist), + GFP_KERNEL); if (!hwif->sg_table) { printk(KERN_ERR "%s: unable to allocate SG table.\n", hwif->name); goto out; diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 6e8af2b91492..9d1f92782936 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -1878,8 +1878,8 @@ static struct rdma_id_private *cma_new_conn_id(struct rdma_cm_id *listen_id, rt = &id->route; rt->num_paths = ib_event->param.req_rcvd.alternate_path ? 2 : 1; - rt->path_rec = kmalloc(sizeof *rt->path_rec * rt->num_paths, - GFP_KERNEL); + rt->path_rec = kmalloc_array(rt->num_paths, sizeof(*rt->path_rec), + GFP_KERNEL); if (!rt->path_rec) goto err; diff --git a/drivers/infiniband/core/fmr_pool.c b/drivers/infiniband/core/fmr_pool.c index 84d2615b5d4b..c89b7abed72f 100644 --- a/drivers/infiniband/core/fmr_pool.c +++ b/drivers/infiniband/core/fmr_pool.c @@ -235,8 +235,9 @@ struct ib_fmr_pool *ib_create_fmr_pool(struct ib_pd *pd, if (params->cache) { pool->cache_bucket = - kmalloc(IB_FMR_HASH_SIZE * sizeof *pool->cache_bucket, - GFP_KERNEL); + kmalloc_array(IB_FMR_HASH_SIZE, + sizeof(*pool->cache_bucket), + GFP_KERNEL); if (!pool->cache_bucket) { ret = -ENOMEM; goto out_free_pool; diff --git a/drivers/infiniband/hw/cxgb4/id_table.c b/drivers/infiniband/hw/cxgb4/id_table.c index 0161ae6ad629..1304ab4ab50b 100644 --- a/drivers/infiniband/hw/cxgb4/id_table.c +++ b/drivers/infiniband/hw/cxgb4/id_table.c @@ -93,8 +93,8 @@ int c4iw_id_table_alloc(struct c4iw_id_table *alloc, u32 start, u32 num, alloc->last = 0; alloc->max = num; spin_lock_init(&alloc->lock); - alloc->table = kmalloc(BITS_TO_LONGS(num) * sizeof(long), - GFP_KERNEL); + alloc->table = kmalloc_array(BITS_TO_LONGS(num), sizeof(long), + GFP_KERNEL); if (!alloc->table) return -ENOMEM; diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c index 3f8511104c5b..859d3f576785 100644 --- a/drivers/infiniband/hw/mlx4/main.c +++ b/drivers/infiniband/hw/mlx4/main.c @@ -305,7 +305,8 @@ static int mlx4_ib_add_gid(struct ib_device *device, ctx->refcount++; } if (!ret && hw_update) { - gids = kmalloc(sizeof(*gids) * MLX4_MAX_PORT_GIDS, GFP_ATOMIC); + gids = kmalloc_array(MLX4_MAX_PORT_GIDS, sizeof(*gids), + GFP_ATOMIC); if (!gids) { ret = -ENOMEM; } else { @@ -360,7 +361,8 @@ static int mlx4_ib_del_gid(struct ib_device *device, if (!ret && hw_update) { int i; - gids = kmalloc(sizeof(*gids) * MLX4_MAX_PORT_GIDS, GFP_ATOMIC); + gids = kmalloc_array(MLX4_MAX_PORT_GIDS, sizeof(*gids), + GFP_ATOMIC); if (!gids) { ret = -ENOMEM; } else { @@ -2880,9 +2882,9 @@ static void *mlx4_ib_add(struct mlx4_dev *dev) goto err_counter; ibdev->ib_uc_qpns_bitmap = - kmalloc(BITS_TO_LONGS(ibdev->steer_qpn_count) * - sizeof(long), - GFP_KERNEL); + kmalloc_array(BITS_TO_LONGS(ibdev->steer_qpn_count), + sizeof(long), + GFP_KERNEL); if (!ibdev->ib_uc_qpns_bitmap) goto err_steer_qp_release; diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c index df1ecd29057f..f7261fe07d5b 100644 --- a/drivers/infiniband/hw/mlx4/qp.c +++ b/drivers/infiniband/hw/mlx4/qp.c @@ -573,8 +573,8 @@ static int alloc_proxy_bufs(struct ib_device *dev, struct mlx4_ib_qp *qp) int i; qp->sqp_proxy_rcv = - kmalloc(sizeof (struct mlx4_ib_buf) * qp->rq.wqe_cnt, - GFP_KERNEL); + kmalloc_array(qp->rq.wqe_cnt, sizeof(struct mlx4_ib_buf), + GFP_KERNEL); if (!qp->sqp_proxy_rcv) return -ENOMEM; for (i = 0; i < qp->rq.wqe_cnt; i++) { diff --git a/drivers/infiniband/hw/mthca/mthca_allocator.c b/drivers/infiniband/hw/mthca/mthca_allocator.c index b4e0cf4e95cd..aaf10dd5364d 100644 --- a/drivers/infiniband/hw/mthca/mthca_allocator.c +++ b/drivers/infiniband/hw/mthca/mthca_allocator.c @@ -90,8 +90,8 @@ int mthca_alloc_init(struct mthca_alloc *alloc, u32 num, u32 mask, alloc->max = num; alloc->mask = mask; spin_lock_init(&alloc->lock); - alloc->table = kmalloc(BITS_TO_LONGS(num) * sizeof (long), - GFP_KERNEL); + alloc->table = kmalloc_array(BITS_TO_LONGS(num), sizeof(long), + GFP_KERNEL); if (!alloc->table) return -ENOMEM; @@ -162,7 +162,8 @@ int mthca_array_init(struct mthca_array *array, int nent) int npage = (nent * sizeof (void *) + PAGE_SIZE - 1) / PAGE_SIZE; int i; - array->page_list = kmalloc(npage * sizeof *array->page_list, GFP_KERNEL); + array->page_list = kmalloc_array(npage, sizeof(*array->page_list), + GFP_KERNEL); if (!array->page_list) return -ENOMEM; @@ -220,7 +221,8 @@ int mthca_buf_alloc(struct mthca_dev *dev, int size, int max_direct, npages *= 2; } - dma_list = kmalloc(npages * sizeof *dma_list, GFP_KERNEL); + dma_list = kmalloc_array(npages, sizeof(*dma_list), + GFP_KERNEL); if (!dma_list) goto err_free; @@ -231,12 +233,14 @@ int mthca_buf_alloc(struct mthca_dev *dev, int size, int max_direct, npages = (size + PAGE_SIZE - 1) / PAGE_SIZE; shift = PAGE_SHIFT; - dma_list = kmalloc(npages * sizeof *dma_list, GFP_KERNEL); + dma_list = kmalloc_array(npages, sizeof(*dma_list), + GFP_KERNEL); if (!dma_list) return -ENOMEM; - buf->page_list = kmalloc(npages * sizeof *buf->page_list, - GFP_KERNEL); + buf->page_list = kmalloc_array(npages, + sizeof(*buf->page_list), + GFP_KERNEL); if (!buf->page_list) goto err_out; diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c index 419a2a20c047..83aa47eb81a9 100644 --- a/drivers/infiniband/hw/mthca/mthca_cmd.c +++ b/drivers/infiniband/hw/mthca/mthca_cmd.c @@ -565,9 +565,9 @@ int mthca_cmd_use_events(struct mthca_dev *dev) { int i; - dev->cmd.context = kmalloc(dev->cmd.max_cmds * - sizeof (struct mthca_cmd_context), - GFP_KERNEL); + dev->cmd.context = kmalloc_array(dev->cmd.max_cmds, + sizeof(struct mthca_cmd_context), + GFP_KERNEL); if (!dev->cmd.context) return -ENOMEM; diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c index 690201738993..30400ea4808b 100644 --- a/drivers/infiniband/hw/mthca/mthca_eq.c +++ b/drivers/infiniband/hw/mthca/mthca_eq.c @@ -479,15 +479,15 @@ static int mthca_create_eq(struct mthca_dev *dev, eq->nent = roundup_pow_of_two(max(nent, 2)); npages = ALIGN(eq->nent * MTHCA_EQ_ENTRY_SIZE, PAGE_SIZE) / PAGE_SIZE; - eq->page_list = kmalloc(npages * sizeof *eq->page_list, - GFP_KERNEL); + eq->page_list = kmalloc_array(npages, sizeof(*eq->page_list), + GFP_KERNEL); if (!eq->page_list) goto err_out; for (i = 0; i < npages; ++i) eq->page_list[i].buf = NULL; - dma_list = kmalloc(npages * sizeof *dma_list, GFP_KERNEL); + dma_list = kmalloc_array(npages, sizeof(*dma_list), GFP_KERNEL); if (!dma_list) goto err_out_free; diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.c b/drivers/infiniband/hw/mthca/mthca_memfree.c index 553ccbf59593..cdd045694942 100644 --- a/drivers/infiniband/hw/mthca/mthca_memfree.c +++ b/drivers/infiniband/hw/mthca/mthca_memfree.c @@ -713,9 +713,9 @@ int mthca_init_db_tab(struct mthca_dev *dev) dev->db_tab->max_group1 = 0; dev->db_tab->min_group2 = dev->db_tab->npages - 1; - dev->db_tab->page = kmalloc(dev->db_tab->npages * - sizeof *dev->db_tab->page, - GFP_KERNEL); + dev->db_tab->page = kmalloc_array(dev->db_tab->npages, + sizeof(*dev->db_tab->page), + GFP_KERNEL); if (!dev->db_tab->page) { kfree(dev->db_tab); return -ENOMEM; diff --git a/drivers/infiniband/hw/mthca/mthca_mr.c b/drivers/infiniband/hw/mthca/mthca_mr.c index ed9a989e501b..dc3c2346045c 100644 --- a/drivers/infiniband/hw/mthca/mthca_mr.c +++ b/drivers/infiniband/hw/mthca/mthca_mr.c @@ -153,7 +153,7 @@ static int mthca_buddy_init(struct mthca_buddy *buddy, int max_order) for (i = 0; i <= buddy->max_order; ++i) { s = BITS_TO_LONGS(1 << (buddy->max_order - i)); - buddy->bits[i] = kmalloc(s * sizeof (long), GFP_KERNEL); + buddy->bits[i] = kmalloc_array(s, sizeof(long), GFP_KERNEL); if (!buddy->bits[i]) goto err_out_free; bitmap_zero(buddy->bits[i], diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c index d21960cd9a49..af1c49d70b89 100644 --- a/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/drivers/infiniband/hw/mthca/mthca_qp.c @@ -1054,8 +1054,8 @@ static int mthca_alloc_wqe_buf(struct mthca_dev *dev, size = PAGE_ALIGN(qp->send_wqe_offset + (qp->sq.max << qp->sq.wqe_shift)); - qp->wrid = kmalloc((qp->rq.max + qp->sq.max) * sizeof (u64), - GFP_KERNEL); + qp->wrid = kmalloc_array(qp->rq.max + qp->sq.max, sizeof(u64), + GFP_KERNEL); if (!qp->wrid) goto err_out; diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c index d22f970480c0..f79732bc73b4 100644 --- a/drivers/infiniband/hw/mthca/mthca_srq.c +++ b/drivers/infiniband/hw/mthca/mthca_srq.c @@ -155,7 +155,7 @@ static int mthca_alloc_srq_buf(struct mthca_dev *dev, struct mthca_pd *pd, if (pd->ibpd.uobject) return 0; - srq->wrid = kmalloc(srq->max * sizeof (u64), GFP_KERNEL); + srq->wrid = kmalloc_array(srq->max, sizeof(u64), GFP_KERNEL); if (!srq->wrid) return -ENOMEM; diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c index 5921ea3d50ae..dd98401b7226 100644 --- a/drivers/infiniband/hw/nes/nes_nic.c +++ b/drivers/infiniband/hw/nes/nes_nic.c @@ -904,7 +904,7 @@ static void nes_netdev_set_multicast_list(struct net_device *netdev) int i; struct netdev_hw_addr *ha; - addrs = kmalloc(ETH_ALEN * mc_count, GFP_ATOMIC); + addrs = kmalloc_array(mc_count, ETH_ALEN, GFP_ATOMIC); if (!addrs) { set_allmulti(nesdev, nic_active_bit); goto unlock; diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c index 7683d13dad3d..1847696c17a6 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c @@ -1911,7 +1911,8 @@ struct ib_srq *ocrdma_create_srq(struct ib_pd *ibpd, srq->bit_fields_len = (srq->rq.max_cnt / 32) + (srq->rq.max_cnt % 32 ? 1 : 0); srq->idx_bit_fields = - kmalloc(srq->bit_fields_len * sizeof(u32), GFP_KERNEL); + kmalloc_array(srq->bit_fields_len, sizeof(u32), + GFP_KERNEL); if (srq->idx_bit_fields == NULL) goto arm_err; memset(srq->idx_bit_fields, 0xff, diff --git a/drivers/infiniband/hw/qib/qib_iba6120.c b/drivers/infiniband/hw/qib/qib_iba6120.c index 3259a60e4f4f..39808dc50277 100644 --- a/drivers/infiniband/hw/qib/qib_iba6120.c +++ b/drivers/infiniband/hw/qib/qib_iba6120.c @@ -2523,15 +2523,16 @@ static void init_6120_cntrnames(struct qib_devdata *dd) dd->cspec->cntrnamelen = sizeof(cntr6120names) - 1; else dd->cspec->cntrnamelen = 1 + s - cntr6120names; - dd->cspec->cntrs = kmalloc(dd->cspec->ncntrs - * sizeof(u64), GFP_KERNEL); + dd->cspec->cntrs = kmalloc_array(dd->cspec->ncntrs, sizeof(u64), + GFP_KERNEL); for (i = 0, s = (char *)portcntr6120names; s; i++) s = strchr(s + 1, '\n'); dd->cspec->nportcntrs = i - 1; dd->cspec->portcntrnamelen = sizeof(portcntr6120names) - 1; - dd->cspec->portcntrs = kmalloc(dd->cspec->nportcntrs - * sizeof(u64), GFP_KERNEL); + dd->cspec->portcntrs = kmalloc_array(dd->cspec->nportcntrs, + sizeof(u64), + GFP_KERNEL); } static u32 qib_read_6120cntrs(struct qib_devdata *dd, loff_t pos, char **namep, diff --git a/drivers/infiniband/hw/qib/qib_iba7220.c b/drivers/infiniband/hw/qib/qib_iba7220.c index 04bdd3d487b1..265034b7e03b 100644 --- a/drivers/infiniband/hw/qib/qib_iba7220.c +++ b/drivers/infiniband/hw/qib/qib_iba7220.c @@ -3170,15 +3170,16 @@ static void init_7220_cntrnames(struct qib_devdata *dd) dd->cspec->cntrnamelen = sizeof(cntr7220names) - 1; else dd->cspec->cntrnamelen = 1 + s - cntr7220names; - dd->cspec->cntrs = kmalloc(dd->cspec->ncntrs - * sizeof(u64), GFP_KERNEL); + dd->cspec->cntrs = kmalloc_array(dd->cspec->ncntrs, sizeof(u64), + GFP_KERNEL); for (i = 0, s = (char *)portcntr7220names; s; i++) s = strchr(s + 1, '\n'); dd->cspec->nportcntrs = i - 1; dd->cspec->portcntrnamelen = sizeof(portcntr7220names) - 1; - dd->cspec->portcntrs = kmalloc(dd->cspec->nportcntrs - * sizeof(u64), GFP_KERNEL); + dd->cspec->portcntrs = kmalloc_array(dd->cspec->nportcntrs, + sizeof(u64), + GFP_KERNEL); } static u32 qib_read_7220cntrs(struct qib_devdata *dd, loff_t pos, char **namep, diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c index a45e46098914..10d675a1991c 100644 --- a/drivers/infiniband/hw/qib/qib_iba7322.c +++ b/drivers/infiniband/hw/qib/qib_iba7322.c @@ -3677,8 +3677,9 @@ static int qib_do_7322_reset(struct qib_devdata *dd) if (msix_entries) { qib_7322_nomsix(dd); /* can be up to 512 bytes, too big for stack */ - msix_vecsave = kmalloc(2 * dd->cspec->num_msix_entries * - sizeof(u64), GFP_KERNEL); + msix_vecsave = kmalloc_array(2 * dd->cspec->num_msix_entries, + sizeof(u64), + GFP_KERNEL); } /* @@ -5038,16 +5039,17 @@ static void init_7322_cntrnames(struct qib_devdata *dd) dd->cspec->cntrnamelen = sizeof(cntr7322names) - 1; else dd->cspec->cntrnamelen = 1 + s - cntr7322names; - dd->cspec->cntrs = kmalloc(dd->cspec->ncntrs - * sizeof(u64), GFP_KERNEL); + dd->cspec->cntrs = kmalloc_array(dd->cspec->ncntrs, sizeof(u64), + GFP_KERNEL); for (i = 0, s = (char *)portcntr7322names; s; i++) s = strchr(s + 1, '\n'); dd->cspec->nportcntrs = i - 1; dd->cspec->portcntrnamelen = sizeof(portcntr7322names) - 1; for (i = 0; i < dd->num_pports; ++i) { - dd->pport[i].cpspec->portcntrs = kmalloc(dd->cspec->nportcntrs - * sizeof(u64), GFP_KERNEL); + dd->pport[i].cpspec->portcntrs = kmalloc_array(dd->cspec->nportcntrs, + sizeof(u64), + GFP_KERNEL); } } @@ -6445,12 +6447,15 @@ static int qib_init_7322_variables(struct qib_devdata *dd) sbufcnt = dd->piobcnt2k + dd->piobcnt4k + NUM_VL15_BUFS + BITS_PER_LONG - 1; sbufcnt /= BITS_PER_LONG; - dd->cspec->sendchkenable = kmalloc(sbufcnt * - sizeof(*dd->cspec->sendchkenable), GFP_KERNEL); - dd->cspec->sendgrhchk = kmalloc(sbufcnt * - sizeof(*dd->cspec->sendgrhchk), GFP_KERNEL); - dd->cspec->sendibchk = kmalloc(sbufcnt * - sizeof(*dd->cspec->sendibchk), GFP_KERNEL); + dd->cspec->sendchkenable = kmalloc_array(sbufcnt, + sizeof(*dd->cspec->sendchkenable), + GFP_KERNEL); + dd->cspec->sendgrhchk = kmalloc_array(sbufcnt, + sizeof(*dd->cspec->sendgrhchk), + GFP_KERNEL); + dd->cspec->sendibchk = kmalloc_array(sbufcnt, + sizeof(*dd->cspec->sendibchk), + GFP_KERNEL); if (!dd->cspec->sendchkenable || !dd->cspec->sendgrhchk || !dd->cspec->sendibchk) { ret = -ENOMEM; diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c index a126750b65a9..1f46c08efd2d 100644 --- a/drivers/infiniband/ulp/iser/iser_initiator.c +++ b/drivers/infiniband/ulp/iser/iser_initiator.c @@ -259,8 +259,9 @@ int iser_alloc_rx_descriptors(struct iser_conn *iser_conn, goto alloc_login_buf_fail; iser_conn->num_rx_descs = session->cmds_max; - iser_conn->rx_descs = kmalloc(iser_conn->num_rx_descs * - sizeof(struct iser_rx_desc), GFP_KERNEL); + iser_conn->rx_descs = kmalloc_array(iser_conn->num_rx_descs, + sizeof(struct iser_rx_desc), + GFP_KERNEL); if (!iser_conn->rx_descs) goto rx_desc_alloc_fail; diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 9f7287f45d06..a77315f70791 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -883,16 +883,17 @@ static int srp_alloc_req_data(struct srp_rdma_ch *ch) for (i = 0; i < target->req_ring_size; ++i) { req = &ch->req_ring[i]; - mr_list = kmalloc(target->mr_per_cmd * sizeof(void *), - GFP_KERNEL); + mr_list = kmalloc_array(target->mr_per_cmd, sizeof(void *), + GFP_KERNEL); if (!mr_list) goto out; if (srp_dev->use_fast_reg) { req->fr_list = mr_list; } else { req->fmr_list = mr_list; - req->map_page = kmalloc(srp_dev->max_pages_per_mr * - sizeof(void *), GFP_KERNEL); + req->map_page = kmalloc_array(srp_dev->max_pages_per_mr, + sizeof(void *), + GFP_KERNEL); if (!req->map_page) goto out; } diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c index 5f1055c94d66..8ae224280421 100644 --- a/drivers/infiniband/ulp/srpt/ib_srpt.c +++ b/drivers/infiniband/ulp/srpt/ib_srpt.c @@ -657,7 +657,7 @@ static struct srpt_ioctx **srpt_alloc_ioctx_ring(struct srpt_device *sdev, WARN_ON(ioctx_size != sizeof(struct srpt_recv_ioctx) && ioctx_size != sizeof(struct srpt_send_ioctx)); - ring = kmalloc(ring_size * sizeof(ring[0]), GFP_KERNEL); + ring = kmalloc_array(ring_size, sizeof(ring[0]), GFP_KERNEL); if (!ring) goto out; for (i = 0; i < ring_size; ++i) { diff --git a/drivers/input/joystick/joydump.c b/drivers/input/joystick/joydump.c index d1c6e4846a4a..7f4dff9a566f 100644 --- a/drivers/input/joystick/joydump.c +++ b/drivers/input/joystick/joydump.c @@ -80,7 +80,7 @@ static int joydump_connect(struct gameport *gameport, struct gameport_driver *dr timeout = gameport_time(gameport, 10000); /* 10 ms */ - buf = kmalloc(BUF_SIZE * sizeof(struct joydump), GFP_KERNEL); + buf = kmalloc_array(BUF_SIZE, sizeof(struct joydump), GFP_KERNEL); if (!buf) { printk(KERN_INFO "joydump: no memory for testing\n"); goto jd_end; diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c index 39bcbc38997f..ac1458005a02 100644 --- a/drivers/input/keyboard/bf54x-keys.c +++ b/drivers/input/keyboard/bf54x-keys.c @@ -201,8 +201,8 @@ static int bfin_kpad_probe(struct platform_device *pdev) platform_set_drvdata(pdev, bf54x_kpad); /* Allocate memory for keymap followed by private LUT */ - bf54x_kpad->keycode = kmalloc(pdata->keymapsize * - sizeof(unsigned short) * 2, GFP_KERNEL); + bf54x_kpad->keycode = kmalloc(array3_size(pdata->keymapsize, sizeof(unsigned short), 2), + GFP_KERNEL); if (!bf54x_kpad->keycode) { error = -ENOMEM; goto out; diff --git a/drivers/iommu/io-pgtable-fast.c b/drivers/iommu/io-pgtable-fast.c index 5a5d597a00a6..93d8c2d34b62 100644 --- a/drivers/iommu/io-pgtable-fast.c +++ b/drivers/iommu/io-pgtable-fast.c @@ -438,7 +438,7 @@ av8l_fast_prepopulate_pgtables(struct av8l_fast_io_pgtable *data, dma_addr_t pud, pmd; int pmd_pg_index; - pages = kmalloc(sizeof(*pages) * NUM_PGTBL_PAGES, __GFP_NOWARN | + pages = kmalloc_array(NUM_PGTBL_PAGES, sizeof(*pages), __GFP_NOWARN | __GFP_NORETRY); if (!pages) diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 84b23d902d5b..71e5e6c5e8da 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -3213,8 +3213,8 @@ static void __init acpi_table_parse_srat_its(void) if (count <= 0) return; - its_srat_maps = kmalloc(count * sizeof(struct its_srat_map), - GFP_KERNEL); + its_srat_maps = kmalloc_array(count, sizeof(struct its_srat_map), + GFP_KERNEL); if (!its_srat_maps) { pr_warn("SRAT: Failed to allocate memory for its_srat_maps!\n"); return; diff --git a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c index 89dd1303a98a..982fc1e26062 100644 --- a/drivers/isdn/capi/capidrv.c +++ b/drivers/isdn/capi/capidrv.c @@ -2268,7 +2268,8 @@ static int capidrv_addcontr(u16 contr, struct capi_profile *profp) strcpy(card->name, id); card->contrnr = contr; card->nbchan = profp->nbchannel; - card->bchans = kmalloc(sizeof(capidrv_bchan) * card->nbchan, GFP_ATOMIC); + card->bchans = kmalloc_array(card->nbchan, sizeof(capidrv_bchan), + GFP_ATOMIC); if (!card->bchans) { printk(KERN_WARNING "capidrv: (%s) Could not allocate bchan-structs.\n", id); diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c index ccec7778cad2..632002a95cb3 100644 --- a/drivers/isdn/gigaset/capi.c +++ b/drivers/isdn/gigaset/capi.c @@ -252,7 +252,7 @@ static inline void dump_rawmsg(enum debuglevel level, const char *tag, return; if (l > 64) l = 64; /* arbitrary limit */ - dbgline = kmalloc(3 * l, GFP_ATOMIC); + dbgline = kmalloc_array(3, l, GFP_ATOMIC); if (!dbgline) return; for (i = 0; i < l; i++) { @@ -272,7 +272,7 @@ static inline void dump_rawmsg(enum debuglevel level, const char *tag, return; if (l > 64) l = 64; /* arbitrary limit */ - dbgline = kmalloc(3 * l, GFP_ATOMIC); + dbgline = kmalloc_array(3, l, GFP_ATOMIC); if (!dbgline) return; data += CAPIMSG_LEN(data); diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index 7c7814497e3e..47894afb563e 100644 --- a/drivers/isdn/gigaset/common.c +++ b/drivers/isdn/gigaset/common.c @@ -710,7 +710,7 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, cs->mode = M_UNKNOWN; cs->mstate = MS_UNINITIALIZED; - cs->bcs = kmalloc(channels * sizeof(struct bc_state), GFP_KERNEL); + cs->bcs = kmalloc_array(channels, sizeof(struct bc_state), GFP_KERNEL); cs->inbuf = kmalloc(sizeof(struct inbuf_t), GFP_KERNEL); if (!cs->bcs || !cs->inbuf) { pr_err("out of memory\n"); @@ -1090,7 +1090,7 @@ struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors, drv->owner = owner; INIT_LIST_HEAD(&drv->list); - drv->cs = kmalloc(minors * sizeof *drv->cs, GFP_KERNEL); + drv->cs = kmalloc_array(minors, sizeof(*drv->cs), GFP_KERNEL); if (!drv->cs) goto error; diff --git a/drivers/isdn/hisax/hfc_2bds0.c b/drivers/isdn/hisax/hfc_2bds0.c index ad8597a1a07e..a6c378f8964e 100644 --- a/drivers/isdn/hisax/hfc_2bds0.c +++ b/drivers/isdn/hisax/hfc_2bds0.c @@ -1024,7 +1024,7 @@ static unsigned int int i; unsigned *send; - if (!(send = kmalloc(cnt * sizeof(unsigned int), GFP_ATOMIC))) { + if (!(send = kmalloc_array(cnt, sizeof(unsigned int), GFP_ATOMIC))) { printk(KERN_WARNING "HiSax: No memory for hfcd.send\n"); return (NULL); diff --git a/drivers/isdn/hisax/hfc_2bs0.c b/drivers/isdn/hisax/hfc_2bs0.c index 14dada42874e..3cc3a9f62538 100644 --- a/drivers/isdn/hisax/hfc_2bs0.c +++ b/drivers/isdn/hisax/hfc_2bs0.c @@ -557,7 +557,7 @@ init_send(struct BCState *bcs) { int i; - if (!(bcs->hw.hfc.send = kmalloc(32 * sizeof(unsigned int), GFP_ATOMIC))) { + if (!(bcs->hw.hfc.send = kmalloc_array(32, sizeof(unsigned int), GFP_ATOMIC))) { printk(KERN_WARNING "HiSax: No memory for hfc.send\n"); return; diff --git a/drivers/isdn/hisax/netjet.c b/drivers/isdn/hisax/netjet.c index b7f54fa29228..579654513fec 100644 --- a/drivers/isdn/hisax/netjet.c +++ b/drivers/isdn/hisax/netjet.c @@ -912,8 +912,8 @@ setstack_tiger(struct PStack *st, struct BCState *bcs) void inittiger(struct IsdnCardState *cs) { - if (!(cs->bcs[0].hw.tiger.send = kmalloc(NETJET_DMA_TXSIZE * sizeof(unsigned int), - GFP_KERNEL | GFP_DMA))) { + if (!(cs->bcs[0].hw.tiger.send = kmalloc_array(NETJET_DMA_TXSIZE, sizeof(unsigned int), + GFP_KERNEL | GFP_DMA))) { printk(KERN_WARNING "HiSax: No memory for tiger.send\n"); return; @@ -933,8 +933,8 @@ inittiger(struct IsdnCardState *cs) cs->hw.njet.base + NETJET_DMA_READ_IRQ); outl(virt_to_bus(cs->bcs[0].hw.tiger.s_end), cs->hw.njet.base + NETJET_DMA_READ_END); - if (!(cs->bcs[0].hw.tiger.rec = kmalloc(NETJET_DMA_RXSIZE * sizeof(unsigned int), - GFP_KERNEL | GFP_DMA))) { + if (!(cs->bcs[0].hw.tiger.rec = kmalloc_array(NETJET_DMA_RXSIZE, sizeof(unsigned int), + GFP_KERNEL | GFP_DMA))) { printk(KERN_WARNING "HiSax: No memory for tiger.rec\n"); return; diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c index 598724ffde4e..a5cd3f310091 100644 --- a/drivers/isdn/i4l/isdn_common.c +++ b/drivers/isdn/i4l/isdn_common.c @@ -2083,7 +2083,7 @@ isdn_add_channels(isdn_driver_t *d, int drvidx, int n, int adding) skb_queue_purge(&d->rpqueue[j]); kfree(d->rpqueue); } - if (!(d->rpqueue = kmalloc(sizeof(struct sk_buff_head) * m, GFP_ATOMIC))) { + if (!(d->rpqueue = kmalloc_array(m, sizeof(struct sk_buff_head), GFP_ATOMIC))) { printk(KERN_WARNING "register_isdn: Could not alloc rpqueue\n"); if (!adding) { kfree(d->rcvcount); @@ -2097,7 +2097,8 @@ isdn_add_channels(isdn_driver_t *d, int drvidx, int n, int adding) if ((adding) && (d->rcv_waitq)) kfree(d->rcv_waitq); - d->rcv_waitq = kmalloc(sizeof(wait_queue_head_t) * 2 * m, GFP_ATOMIC); + d->rcv_waitq = kmalloc(array3_size(sizeof(wait_queue_head_t), 2, m), + GFP_ATOMIC); if (!d->rcv_waitq) { printk(KERN_WARNING "register_isdn: Could not alloc rcv_waitq\n"); if (!adding) { diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 7eb76a1a2505..63090ec7d430 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -785,8 +785,8 @@ static int bitmap_storage_alloc(struct bitmap_storage *store, num_pages = DIV_ROUND_UP(bytes, PAGE_SIZE); offset = slot_number * num_pages; - store->filemap = kmalloc(sizeof(struct page *) - * num_pages, GFP_KERNEL); + store->filemap = kmalloc_array(num_pages, sizeof(struct page *), + GFP_KERNEL); if (!store->filemap) return -ENOMEM; diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c index b6ca5b1100db..4c436b7de827 100644 --- a/drivers/md/dm-integrity.c +++ b/drivers/md/dm-integrity.c @@ -2743,7 +2743,8 @@ static int create_journal(struct dm_integrity_c *ic, char **error) r = -ENOMEM; goto bad; } - section_req->iv = kmalloc(ivsize * 2, GFP_KERNEL); + section_req->iv = kmalloc_array(ivsize, 2, + GFP_KERNEL); if (!section_req->iv) { skcipher_request_free(section_req); *error = "Unable to allocate iv"; diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index 2170f6c118b8..c835ed4d08a2 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c @@ -342,8 +342,8 @@ static int init_origin_hash(void) { int i; - _origins = kmalloc(ORIGIN_HASH_SIZE * sizeof(struct list_head), - GFP_KERNEL); + _origins = kmalloc_array(ORIGIN_HASH_SIZE, sizeof(struct list_head), + GFP_KERNEL); if (!_origins) { DMERR("unable to allocate memory for _origins"); return -ENOMEM; @@ -351,8 +351,9 @@ static int init_origin_hash(void) for (i = 0; i < ORIGIN_HASH_SIZE; i++) INIT_LIST_HEAD(_origins + i); - _dm_origins = kmalloc(ORIGIN_HASH_SIZE * sizeof(struct list_head), - GFP_KERNEL); + _dm_origins = kmalloc_array(ORIGIN_HASH_SIZE, + sizeof(struct list_head), + GFP_KERNEL); if (!_dm_origins) { DMERR("unable to allocate memory for _dm_origins"); kfree(_origins); diff --git a/drivers/md/dm-stats.c b/drivers/md/dm-stats.c index a7868503d135..935c2fc9274b 100644 --- a/drivers/md/dm-stats.c +++ b/drivers/md/dm-stats.c @@ -914,7 +914,9 @@ static int parse_histogram(const char *h, unsigned *n_histogram_entries, if (*q == ',') (*n_histogram_entries)++; - *histogram_boundaries = kmalloc(*n_histogram_entries * sizeof(unsigned long long), GFP_KERNEL); + *histogram_boundaries = kmalloc_array(*n_histogram_entries, + sizeof(unsigned long long), + GFP_KERNEL); if (!*histogram_boundaries) return -ENOMEM; diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 0f9a8087e1a0..1a25e7185628 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -561,7 +561,7 @@ static char **realloc_argv(unsigned *size, char **old_argv) new_size = 8; gfp = GFP_NOIO; } - argv = kmalloc(new_size * sizeof(*argv), gfp); + argv = kmalloc_array(new_size, sizeof(*argv), gfp); if (argv) { memcpy(argv, old_argv, *size * sizeof(*argv)); *size = new_size; diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 0a9d623b13c2..0a0deb340b0a 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -127,8 +127,8 @@ static void * r1buf_pool_alloc(gfp_t gfp_flags, void *data) if (!r1_bio) return NULL; - rps = kmalloc(sizeof(struct resync_pages) * pi->raid_disks, - gfp_flags); + rps = kmalloc_array(pi->raid_disks, sizeof(struct resync_pages), + gfp_flags); if (!rps) goto out_free_r1bio; diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index d08d77b9674f..b910124c9b13 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -172,7 +172,7 @@ static void * r10buf_pool_alloc(gfp_t gfp_flags, void *data) nalloc_rp = nalloc; else nalloc_rp = nalloc * 2; - rps = kmalloc(sizeof(struct resync_pages) * nalloc_rp, gfp_flags); + rps = kmalloc_array(nalloc_rp, sizeof(struct resync_pages), gfp_flags); if (!rps) goto out_free_r10bio; diff --git a/drivers/media/pci/bt8xx/bttv-risc.c b/drivers/media/pci/bt8xx/bttv-risc.c index 3859dde98be2..39c941b29ed6 100644 --- a/drivers/media/pci/bt8xx/bttv-risc.c +++ b/drivers/media/pci/bt8xx/bttv-risc.c @@ -255,7 +255,7 @@ bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc, u32 addr; /* skip list for window clipping */ - if (NULL == (skips = kmalloc(sizeof(*skips) * ov->nclips,GFP_KERNEL))) + if (NULL == (skips = kmalloc_array(ov->nclips, sizeof(*skips),GFP_KERNEL))) return -ENOMEM; /* estimate risc mem: worst case is (1.5*clip+1) * lines instructions diff --git a/drivers/media/pci/ivtv/ivtvfb.c b/drivers/media/pci/ivtv/ivtvfb.c index 621b2f613d81..9b8abebefeed 100644 --- a/drivers/media/pci/ivtv/ivtvfb.c +++ b/drivers/media/pci/ivtv/ivtvfb.c @@ -1079,7 +1079,7 @@ static int ivtvfb_init_vidmode(struct ivtv *itv) /* Allocate the pseudo palette */ oi->ivtvfb_info.pseudo_palette = - kmalloc(sizeof(u32) * 16, GFP_KERNEL|__GFP_NOWARN); + kmalloc_array(16, sizeof(u32), GFP_KERNEL|__GFP_NOWARN); if (!oi->ivtvfb_info.pseudo_palette) { IVTVFB_ERR("abort, unable to alloc pseudo palette\n"); diff --git a/drivers/media/pci/zoran/zoran_driver.c b/drivers/media/pci/zoran/zoran_driver.c index a11cb501c550..1b74fb7bee48 100644 --- a/drivers/media/pci/zoran/zoran_driver.c +++ b/drivers/media/pci/zoran/zoran_driver.c @@ -941,7 +941,7 @@ static int zoran_open(struct file *file) /* used to be BUZ_MAX_WIDTH/HEIGHT, but that gives overflows * on norm-change! */ fh->overlay_mask = - kmalloc(((768 + 31) / 32) * 576 * 4, GFP_KERNEL); + kmalloc(array3_size((768 + 31) / 32, 576, 4), GFP_KERNEL); if (!fh->overlay_mask) { dprintk(1, KERN_ERR diff --git a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c index fd10eb974b31..2698a08e94c5 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c +++ b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c @@ -626,9 +626,9 @@ static int32_t msm_actuator_move_focus( return -EFAULT; } /*Allocate memory for damping parameters of all regions*/ - ringing_params_kernel = kmalloc( - sizeof(struct damping_params_t)*(a_ctrl->region_size), - GFP_KERNEL); + ringing_params_kernel = kmalloc_array(a_ctrl->region_size, + sizeof(struct damping_params_t), + GFP_KERNEL); if (!ringing_params_kernel) { pr_err("kmalloc for damping parameters failed\n"); return -EFAULT; @@ -752,9 +752,9 @@ static int32_t msm_actuator_bivcm_move_focus( return -EFAULT; } /*Allocate memory for damping parameters of all regions*/ - ringing_params_kernel = kmalloc( - sizeof(struct damping_params_t)*(a_ctrl->region_size), - GFP_KERNEL); + ringing_params_kernel = kmalloc_array(a_ctrl->region_size, + sizeof(struct damping_params_t), + GFP_KERNEL); if (!ringing_params_kernel) { pr_err("kmalloc for damping parameters failed\n"); return -EFAULT; @@ -923,8 +923,9 @@ static int32_t msm_actuator_bivcm_init_step_table( } /* Fill step position table */ a_ctrl->step_position_table = - kmalloc(sizeof(uint16_t) * - (set_info->af_tuning_params.total_steps + 1), GFP_KERNEL); + kmalloc_array(set_info->af_tuning_params.total_steps + 1, + sizeof(uint16_t), + GFP_KERNEL); if (a_ctrl->step_position_table == NULL) return -ENOMEM; @@ -1011,8 +1012,9 @@ static int32_t msm_actuator_init_step_table(struct msm_actuator_ctrl_t *a_ctrl, } /* Fill step position table */ a_ctrl->step_position_table = - kmalloc(sizeof(uint16_t) * - (set_info->af_tuning_params.total_steps + 1), GFP_KERNEL); + kmalloc_array(set_info->af_tuning_params.total_steps + 1, + sizeof(uint16_t), + GFP_KERNEL); if (a_ctrl->step_position_table == NULL) return -ENOMEM; @@ -1349,8 +1351,9 @@ static int32_t msm_actuator_set_param(struct msm_actuator_ctrl_t *a_ctrl, } a_ctrl->i2c_reg_tbl = NULL; a_ctrl->i2c_reg_tbl = - kmalloc(sizeof(struct msm_camera_i2c_reg_array) * - (set_info->af_tuning_params.total_steps + 1), GFP_KERNEL); + kmalloc_array(set_info->af_tuning_params.total_steps + 1, + sizeof(struct msm_camera_i2c_reg_array), + GFP_KERNEL); if (!a_ctrl->i2c_reg_tbl) { pr_err("kmalloc fail\n"); return -ENOMEM; @@ -1370,9 +1373,9 @@ static int32_t msm_actuator_set_param(struct msm_actuator_ctrl_t *a_ctrl, set_info->actuator_params.init_setting_size <= MAX_ACTUATOR_INIT_SET) { if (a_ctrl->func_tbl->actuator_init_focus) { - init_settings = kmalloc(sizeof(struct reg_settings_t) * - (set_info->actuator_params.init_setting_size), - GFP_KERNEL); + init_settings = kmalloc_array(set_info->actuator_params.init_setting_size, + sizeof(struct reg_settings_t), + GFP_KERNEL); if (init_settings == NULL) { kfree(a_ctrl->i2c_reg_tbl); a_ctrl->i2c_reg_tbl = NULL; diff --git a/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c b/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c index 4371a88cc2a3..3d28660558f0 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c +++ b/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c @@ -438,10 +438,9 @@ static int32_t msm_ois_control(struct msm_ois_ctrl_t *o_ctrl, if (set_info->ois_params.setting_size > 0 && set_info->ois_params.setting_size < MAX_OIS_REG_SETTINGS) { - settings = kmalloc( - sizeof(struct reg_settings_ois_t) * - (set_info->ois_params.setting_size), - GFP_KERNEL); + settings = kmalloc_array(set_info->ois_params.setting_size, + sizeof(struct reg_settings_ois_t), + GFP_KERNEL); if (settings == NULL) { pr_err("Error allocating memory\n"); return -EFAULT; diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c index 80081ce41fd8..10da4bdaaf50 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_common.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c @@ -98,8 +98,9 @@ static struct v4l2_ctrl **get_super_cluster(struct msm_vidc_inst *inst, int num_ctrls) { int c = 0; - struct v4l2_ctrl **cluster = kmalloc(sizeof(struct v4l2_ctrl *) * - num_ctrls, GFP_KERNEL); + struct v4l2_ctrl **cluster = kmalloc_array(num_ctrls, + sizeof(struct v4l2_ctrl *), + GFP_KERNEL); if (!cluster || !inst) { kfree(cluster); diff --git a/drivers/media/platform/vivid/vivid-core.c b/drivers/media/platform/vivid/vivid-core.c index 5f316a5e38db..df93058e72eb 100644 --- a/drivers/media/platform/vivid/vivid-core.c +++ b/drivers/media/platform/vivid/vivid-core.c @@ -871,8 +871,9 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) /* create a string array containing the names of all the preset timings */ while (v4l2_dv_timings_presets[dev->query_dv_timings_size].bt.width) dev->query_dv_timings_size++; - dev->query_dv_timings_qmenu = kmalloc(dev->query_dv_timings_size * - (sizeof(void *) + 32), GFP_KERNEL); + dev->query_dv_timings_qmenu = kmalloc_array(dev->query_dv_timings_size, + (sizeof(void *) + 32), + GFP_KERNEL); if (dev->query_dv_timings_qmenu == NULL) goto free_dev; for (i = 0; i < dev->query_dv_timings_size; i++) { diff --git a/drivers/media/usb/cpia2/cpia2_usb.c b/drivers/media/usb/cpia2/cpia2_usb.c index 91b9eaa9b2ad..f23c2fa324ac 100644 --- a/drivers/media/usb/cpia2/cpia2_usb.c +++ b/drivers/media/usb/cpia2/cpia2_usb.c @@ -663,7 +663,8 @@ static int submit_urbs(struct camera_data *cam) if (cam->sbuf[i].data) continue; cam->sbuf[i].data = - kmalloc(FRAMES_PER_DESC * FRAME_SIZE_PER_DESC, GFP_KERNEL); + kmalloc_array(FRAME_SIZE_PER_DESC, FRAMES_PER_DESC, + GFP_KERNEL); if (!cam->sbuf[i].data) { while (--i >= 0) { kfree(cam->sbuf[i].data); diff --git a/drivers/media/usb/cx231xx/cx231xx-audio.c b/drivers/media/usb/cx231xx/cx231xx-audio.c index 06f10d7fc4b0..06d9a672faa6 100644 --- a/drivers/media/usb/cx231xx/cx231xx-audio.c +++ b/drivers/media/usb/cx231xx/cx231xx-audio.c @@ -710,7 +710,7 @@ static int cx231xx_audio_init(struct cx231xx *dev) dev_info(dev->dev, "audio EndPoint Addr 0x%x, Alternate settings: %i\n", adev->end_point_addr, adev->num_alt); - adev->alt_max_pkt_size = kmalloc(32 * adev->num_alt, GFP_KERNEL); + adev->alt_max_pkt_size = kmalloc_array(32, adev->num_alt, GFP_KERNEL); if (!adev->alt_max_pkt_size) { err = -ENOMEM; goto err_free_card; diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index 9747e23aad27..f00f95d035bd 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -3500,8 +3500,9 @@ static int em28xx_usb_probe(struct usb_interface *interface, /* compute alternate max packet sizes */ dev->alt_max_pkt_size_isoc = - kmalloc(sizeof(dev->alt_max_pkt_size_isoc[0]) * - interface->num_altsetting, GFP_KERNEL); + kmalloc_array(interface->num_altsetting, + sizeof(dev->alt_max_pkt_size_isoc[0]), + GFP_KERNEL); if (dev->alt_max_pkt_size_isoc == NULL) { kfree(dev); retval = -ENOMEM; diff --git a/drivers/media/usb/go7007/go7007-usb.c b/drivers/media/usb/go7007/go7007-usb.c index ed9bcaf08d5e..19c6a0354ce0 100644 --- a/drivers/media/usb/go7007/go7007-usb.c +++ b/drivers/media/usb/go7007/go7007-usb.c @@ -1143,7 +1143,8 @@ static int go7007_usb_probe(struct usb_interface *intf, usb->intr_urb = usb_alloc_urb(0, GFP_KERNEL); if (usb->intr_urb == NULL) goto allocfail; - usb->intr_urb->transfer_buffer = kmalloc(2*sizeof(u16), GFP_KERNEL); + usb->intr_urb->transfer_buffer = kmalloc_array(2, sizeof(u16), + GFP_KERNEL); if (usb->intr_urb->transfer_buffer == NULL) goto allocfail; diff --git a/drivers/media/usb/gspca/t613.c b/drivers/media/usb/gspca/t613.c index 46fb76349000..ce5c6464220f 100644 --- a/drivers/media/usb/gspca/t613.c +++ b/drivers/media/usb/gspca/t613.c @@ -363,7 +363,7 @@ static void reg_w_ixbuf(struct gspca_dev *gspca_dev, if (len * 2 <= USB_BUF_SZ) { p = tmpbuf = gspca_dev->usb_buf; } else { - p = tmpbuf = kmalloc(len * 2, GFP_KERNEL); + p = tmpbuf = kmalloc_array(len, 2, GFP_KERNEL); if (!tmpbuf) { pr_err("Out of memory\n"); return; diff --git a/drivers/media/usb/stk1160/stk1160-core.c b/drivers/media/usb/stk1160/stk1160-core.c index bea8bbbb84fb..e5acd2a4fc19 100644 --- a/drivers/media/usb/stk1160/stk1160-core.c +++ b/drivers/media/usb/stk1160/stk1160-core.c @@ -288,8 +288,9 @@ static int stk1160_probe(struct usb_interface *interface, return -ENODEV; /* Alloc an array for all possible max_pkt_size */ - alt_max_pkt_size = kmalloc(sizeof(alt_max_pkt_size[0]) * - interface->num_altsetting, GFP_KERNEL); + alt_max_pkt_size = kmalloc_array(interface->num_altsetting, + sizeof(alt_max_pkt_size[0]), + GFP_KERNEL); if (alt_max_pkt_size == NULL) return -ENOMEM; diff --git a/drivers/media/usb/tm6000/tm6000-video.c b/drivers/media/usb/tm6000/tm6000-video.c index ec8c4d2534dc..e3b2470ce61a 100644 --- a/drivers/media/usb/tm6000/tm6000-video.c +++ b/drivers/media/usb/tm6000/tm6000-video.c @@ -473,13 +473,14 @@ static int tm6000_alloc_urb_buffers(struct tm6000_core *dev) if (dev->urb_buffer != NULL) return 0; - dev->urb_buffer = kmalloc(sizeof(void *)*num_bufs, GFP_KERNEL); + dev->urb_buffer = kmalloc_array(num_bufs, sizeof(void *), GFP_KERNEL); if (!dev->urb_buffer) { tm6000_err("cannot allocate memory for urb buffers\n"); return -ENOMEM; } - dev->urb_dma = kmalloc(sizeof(dma_addr_t *)*num_bufs, GFP_KERNEL); + dev->urb_dma = kmalloc_array(num_bufs, sizeof(dma_addr_t *), + GFP_KERNEL); if (!dev->urb_dma) { tm6000_err("cannot allocate memory for urb dma pointers\n"); return -ENOMEM; @@ -597,14 +598,16 @@ static int tm6000_prepare_isoc(struct tm6000_core *dev) dev->isoc_ctl.num_bufs = num_bufs; - dev->isoc_ctl.urb = kmalloc(sizeof(void *)*num_bufs, GFP_KERNEL); + dev->isoc_ctl.urb = kmalloc_array(num_bufs, sizeof(void *), + GFP_KERNEL); if (!dev->isoc_ctl.urb) { tm6000_err("cannot alloc memory for usb buffers\n"); return -ENOMEM; } - dev->isoc_ctl.transfer_buffer = kmalloc(sizeof(void *)*num_bufs, - GFP_KERNEL); + dev->isoc_ctl.transfer_buffer = kmalloc_array(num_bufs, + sizeof(void *), + GFP_KERNEL); if (!dev->isoc_ctl.transfer_buffer) { tm6000_err("cannot allocate memory for usbtransfer\n"); kfree(dev->isoc_ctl.urb); diff --git a/drivers/media/usb/usbvision/usbvision-video.c b/drivers/media/usb/usbvision/usbvision-video.c index 4c39c502d616..dc4a2c7d153d 100644 --- a/drivers/media/usb/usbvision/usbvision-video.c +++ b/drivers/media/usb/usbvision/usbvision-video.c @@ -1506,7 +1506,8 @@ static int usbvision_probe(struct usb_interface *intf, usbvision->num_alt = uif->num_altsetting; PDEBUG(DBG_PROBE, "Alternate settings: %i", usbvision->num_alt); - usbvision->alt_max_pkt_size = kmalloc(32 * usbvision->num_alt, GFP_KERNEL); + usbvision->alt_max_pkt_size = kmalloc_array(32, usbvision->num_alt, + GFP_KERNEL); if (!usbvision->alt_max_pkt_size) { ret = -ENOMEM; goto err_pkt; diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index 591ca125bd96..25df6e76fa5f 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -268,7 +268,7 @@ void uvc_simplify_fraction(uint32_t *numerator, uint32_t *denominator, uint32_t x, y, r; unsigned int i, n; - an = kmalloc(n_terms * sizeof *an, GFP_KERNEL); + an = kmalloc_array(n_terms, sizeof(*an), GFP_KERNEL); if (an == NULL) return; diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c index 393371916381..929a445bdeab 100644 --- a/drivers/media/usb/uvc/uvc_video.c +++ b/drivers/media/usb/uvc/uvc_video.c @@ -513,8 +513,8 @@ static int uvc_video_clock_init(struct uvc_streaming *stream) spin_lock_init(&clock->lock); clock->size = 32; - clock->samples = kmalloc(clock->size * sizeof(*clock->samples), - GFP_KERNEL); + clock->samples = kmalloc_array(clock->size, sizeof(*clock->samples), + GFP_KERNEL); if (clock->samples == NULL) return -ENOMEM; diff --git a/drivers/media/v4l2-core/videobuf-dma-sg.c b/drivers/media/v4l2-core/videobuf-dma-sg.c index c55e607f5631..6244ac97f343 100644 --- a/drivers/media/v4l2-core/videobuf-dma-sg.c +++ b/drivers/media/v4l2-core/videobuf-dma-sg.c @@ -175,7 +175,8 @@ static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma, dma->offset = data & ~PAGE_MASK; dma->size = size; dma->nr_pages = last-first+1; - dma->pages = kmalloc(dma->nr_pages * sizeof(struct page *), GFP_KERNEL); + dma->pages = kmalloc_array(dma->nr_pages, sizeof(struct page *), + GFP_KERNEL); if (NULL == dma->pages) return -ENOMEM; diff --git a/drivers/memstick/core/ms_block.c b/drivers/memstick/core/ms_block.c index 22de7f5ed032..072fc73d8fe9 100644 --- a/drivers/memstick/core/ms_block.c +++ b/drivers/memstick/core/ms_block.c @@ -1201,7 +1201,8 @@ static int msb_read_boot_blocks(struct msb_data *msb) dbg_verbose("Start of a scan for the boot blocks"); if (!msb->boot_page) { - page = kmalloc(sizeof(struct ms_boot_page)*2, GFP_KERNEL); + page = kmalloc_array(2, sizeof(struct ms_boot_page), + GFP_KERNEL); if (!page) return -ENOMEM; @@ -1341,7 +1342,8 @@ static int msb_ftl_initialize(struct msb_data *msb) msb->used_blocks_bitmap = kzalloc(msb->block_count / 8, GFP_KERNEL); msb->erased_blocks_bitmap = kzalloc(msb->block_count / 8, GFP_KERNEL); msb->lba_to_pba_table = - kmalloc(msb->logical_block_count * sizeof(u16), GFP_KERNEL); + kmalloc_array(msb->logical_block_count, sizeof(u16), + GFP_KERNEL); if (!msb->used_blocks_bitmap || !msb->lba_to_pba_table || !msb->erased_blocks_bitmap) { diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c index 55dd71bbdc2a..e8b96383e253 100644 --- a/drivers/message/fusion/mptlan.c +++ b/drivers/message/fusion/mptlan.c @@ -394,7 +394,8 @@ mpt_lan_open(struct net_device *dev) "a moment.\n"); } - priv->mpt_txfidx = kmalloc(priv->tx_max_out * sizeof(int), GFP_KERNEL); + priv->mpt_txfidx = kmalloc_array(priv->tx_max_out, sizeof(int), + GFP_KERNEL); if (priv->mpt_txfidx == NULL) goto out; priv->mpt_txfidx_tail = -1; @@ -408,8 +409,8 @@ mpt_lan_open(struct net_device *dev) dlprintk((KERN_INFO MYNAM "@lo: Finished initializing SendCtl\n")); - priv->mpt_rxfidx = kmalloc(priv->max_buckets_out * sizeof(int), - GFP_KERNEL); + priv->mpt_rxfidx = kmalloc_array(priv->max_buckets_out, sizeof(int), + GFP_KERNEL); if (priv->mpt_rxfidx == NULL) goto out_SendCtl; priv->mpt_rxfidx_tail = -1; diff --git a/drivers/misc/eeprom/idt_89hpesx.c b/drivers/misc/eeprom/idt_89hpesx.c index 34a5a41578d7..59dc24bb70ec 100644 --- a/drivers/misc/eeprom/idt_89hpesx.c +++ b/drivers/misc/eeprom/idt_89hpesx.c @@ -964,7 +964,7 @@ static ssize_t idt_dbgfs_csr_write(struct file *filep, const char __user *ubuf, if (colon_ch != NULL) { csraddr_len = colon_ch - buf; csraddr_str = - kmalloc(sizeof(char)*(csraddr_len + 1), GFP_KERNEL); + kmalloc(csraddr_len + 1, GFP_KERNEL); if (csraddr_str == NULL) { ret = -ENOMEM; goto free_buf; diff --git a/drivers/misc/vmw_vmci/vmci_queue_pair.c b/drivers/misc/vmw_vmci/vmci_queue_pair.c index b4570d5c1fe7..c2e88ff022ef 100644 --- a/drivers/misc/vmw_vmci/vmci_queue_pair.c +++ b/drivers/misc/vmw_vmci/vmci_queue_pair.c @@ -490,12 +490,14 @@ static int qp_alloc_ppn_set(void *prod_q, return VMCI_ERROR_ALREADY_EXISTS; produce_ppns = - kmalloc(num_produce_pages * sizeof(*produce_ppns), GFP_KERNEL); + kmalloc_array(num_produce_pages, sizeof(*produce_ppns), + GFP_KERNEL); if (!produce_ppns) return VMCI_ERROR_NO_MEM; consume_ppns = - kmalloc(num_consume_pages * sizeof(*consume_ppns), GFP_KERNEL); + kmalloc_array(num_consume_pages, sizeof(*consume_ppns), + GFP_KERNEL); if (!consume_ppns) { kfree(produce_ppns); return VMCI_ERROR_NO_MEM; diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index e1b603ca0170..c311fa2d010e 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c @@ -758,7 +758,9 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd, newcfi = kmalloc(sizeof(struct cfi_private) + numvirtchips * sizeof(struct flchip), GFP_KERNEL); if (!newcfi) return -ENOMEM; - shared = kmalloc(sizeof(struct flchip_shared) * cfi->numchips, GFP_KERNEL); + shared = kmalloc_array(cfi->numchips, + sizeof(struct flchip_shared), + GFP_KERNEL); if (!shared) { kfree(newcfi); return -ENOMEM; diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index 1f0d83086cb0..e99de6beee7c 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -692,8 +692,9 @@ static struct mtd_info *cfi_amdstd_setup(struct mtd_info *mtd) mtd->size = devsize * cfi->numchips; mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips; - mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info) - * mtd->numeraseregions, GFP_KERNEL); + mtd->eraseregions = kmalloc_array(mtd->numeraseregions, + sizeof(struct mtd_erase_region_info), + GFP_KERNEL); if (!mtd->eraseregions) goto setup_err; diff --git a/drivers/mtd/chips/cfi_cmdset_0020.c b/drivers/mtd/chips/cfi_cmdset_0020.c index 7d342965f392..a0edda085f97 100644 --- a/drivers/mtd/chips/cfi_cmdset_0020.c +++ b/drivers/mtd/chips/cfi_cmdset_0020.c @@ -184,8 +184,9 @@ static struct mtd_info *cfi_staa_setup(struct map_info *map) mtd->size = devsize * cfi->numchips; mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips; - mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info) - * mtd->numeraseregions, GFP_KERNEL); + mtd->eraseregions = kmalloc_array(mtd->numeraseregions, + sizeof(struct mtd_erase_region_info), + GFP_KERNEL); if (!mtd->eraseregions) { kfree(cfi->cmdset_priv); kfree(mtd); diff --git a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c index 664d206a4cbe..132f36bf8e2a 100644 --- a/drivers/mtd/ftl.c +++ b/drivers/mtd/ftl.c @@ -207,15 +207,16 @@ static int build_maps(partition_t *part) /* Set up erase unit maps */ part->DataUnits = le16_to_cpu(part->header.NumEraseUnits) - part->header.NumTransferUnits; - part->EUNInfo = kmalloc(part->DataUnits * sizeof(struct eun_info_t), - GFP_KERNEL); + part->EUNInfo = kmalloc_array(part->DataUnits, sizeof(struct eun_info_t), + GFP_KERNEL); if (!part->EUNInfo) goto out; for (i = 0; i < part->DataUnits; i++) part->EUNInfo[i].Offset = 0xffffffff; part->XferInfo = - kmalloc(part->header.NumTransferUnits * sizeof(struct xfer_info_t), - GFP_KERNEL); + kmalloc_array(part->header.NumTransferUnits, + sizeof(struct xfer_info_t), + GFP_KERNEL); if (!part->XferInfo) goto out_EUNInfo; @@ -275,8 +276,8 @@ static int build_maps(partition_t *part) memset(part->VirtualBlockMap, 0xff, blocks * sizeof(uint32_t)); part->BlocksPerUnit = (1 << header.EraseUnitSize) >> header.BlockSize; - part->bam_cache = kmalloc(part->BlocksPerUnit * sizeof(uint32_t), - GFP_KERNEL); + part->bam_cache = kmalloc_array(part->BlocksPerUnit, sizeof(uint32_t), + GFP_KERNEL); if (!part->bam_cache) goto out_VirtualBlockMap; diff --git a/drivers/mtd/inftlmount.c b/drivers/mtd/inftlmount.c index 8d6bb189ea8e..99c2975a3c52 100644 --- a/drivers/mtd/inftlmount.c +++ b/drivers/mtd/inftlmount.c @@ -272,7 +272,8 @@ static int find_boot_record(struct INFTLrecord *inftl) inftl->nb_blocks = ip->lastUnit + 1; /* Memory alloc */ - inftl->PUtable = kmalloc(inftl->nb_blocks * sizeof(u16), GFP_KERNEL); + inftl->PUtable = kmalloc_array(inftl->nb_blocks, sizeof(u16), + GFP_KERNEL); if (!inftl->PUtable) { printk(KERN_WARNING "INFTL: allocation of PUtable " "failed (%zd bytes)\n", @@ -280,7 +281,8 @@ static int find_boot_record(struct INFTLrecord *inftl) return -ENOMEM; } - inftl->VUtable = kmalloc(inftl->nb_blocks * sizeof(u16), GFP_KERNEL); + inftl->VUtable = kmalloc_array(inftl->nb_blocks, sizeof(u16), + GFP_KERNEL); if (!inftl->VUtable) { kfree(inftl->PUtable); printk(KERN_WARNING "INFTL: allocation of VUtable " diff --git a/drivers/mtd/lpddr/lpddr_cmds.c b/drivers/mtd/lpddr/lpddr_cmds.c index e1c283ccbbde..889e40f7c463 100644 --- a/drivers/mtd/lpddr/lpddr_cmds.c +++ b/drivers/mtd/lpddr/lpddr_cmds.c @@ -78,7 +78,7 @@ struct mtd_info *lpddr_cmdset(struct map_info *map) mtd->erasesize = 1 << lpddr->qinfo->UniformBlockSizeShift; mtd->writesize = 1 << lpddr->qinfo->BufSizeShift; - shared = kmalloc(sizeof(struct flchip_shared) * lpddr->numchips, + shared = kmalloc_array(lpddr->numchips, sizeof(struct flchip_shared), GFP_KERNEL); if (!shared) { kfree(mtd); diff --git a/drivers/mtd/maps/vmu-flash.c b/drivers/mtd/maps/vmu-flash.c index 6b223cfe92b7..c5d4b6589488 100644 --- a/drivers/mtd/maps/vmu-flash.c +++ b/drivers/mtd/maps/vmu-flash.c @@ -629,15 +629,15 @@ static int vmu_connect(struct maple_device *mdev) * Not sure there are actually any multi-partition devices in the * real world, but the hardware supports them, so, so will we */ - card->parts = kmalloc(sizeof(struct vmupart) * card->partitions, - GFP_KERNEL); + card->parts = kmalloc_array(card->partitions, sizeof(struct vmupart), + GFP_KERNEL); if (!card->parts) { error = -ENOMEM; goto fail_partitions; } - card->mtd = kmalloc(sizeof(struct mtd_info) * card->partitions, - GFP_KERNEL); + card->mtd = kmalloc_array(card->partitions, sizeof(struct mtd_info), + GFP_KERNEL); if (!card->mtd) { error = -ENOMEM; goto fail_mtd_info; diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c index d573606b91c2..a3d1e0f51d38 100644 --- a/drivers/mtd/mtdconcat.c +++ b/drivers/mtd/mtdconcat.c @@ -849,8 +849,9 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c concat->mtd.erasesize = max_erasesize; concat->mtd.numeraseregions = num_erase_region; concat->mtd.eraseregions = erase_region_p = - kmalloc(num_erase_region * - sizeof (struct mtd_erase_region_info), GFP_KERNEL); + kmalloc_array(num_erase_region, + sizeof(struct mtd_erase_region_info), + GFP_KERNEL); if (!erase_region_p) { kfree(concat); printk diff --git a/drivers/mtd/mtdswap.c b/drivers/mtd/mtdswap.c index 7d9080e33865..d4282df0253e 100644 --- a/drivers/mtd/mtdswap.c +++ b/drivers/mtd/mtdswap.c @@ -1373,7 +1373,7 @@ static int mtdswap_init(struct mtdswap_dev *d, unsigned int eblocks, if (!d->page_buf) goto page_buf_fail; - d->oob_buf = kmalloc(2 * mtd->oobavail, GFP_KERNEL); + d->oob_buf = kmalloc_array(2, mtd->oobavail, GFP_KERNEL); if (!d->oob_buf) goto oob_buf_fail; diff --git a/drivers/mtd/nand/nand_bch.c b/drivers/mtd/nand/nand_bch.c index 505441c9373b..3ab49f103591 100644 --- a/drivers/mtd/nand/nand_bch.c +++ b/drivers/mtd/nand/nand_bch.c @@ -186,7 +186,7 @@ struct nand_bch_control *nand_bch_init(struct mtd_info *mtd) } nbc->eccmask = kmalloc(eccbytes, GFP_KERNEL); - nbc->errloc = kmalloc(t*sizeof(*nbc->errloc), GFP_KERNEL); + nbc->errloc = kmalloc_array(t, sizeof(*nbc->errloc), GFP_KERNEL); if (!nbc->eccmask || !nbc->errloc) goto fail; /* diff --git a/drivers/mtd/nftlmount.c b/drivers/mtd/nftlmount.c index 184c8fbfe465..6688f4e3a90b 100644 --- a/drivers/mtd/nftlmount.c +++ b/drivers/mtd/nftlmount.c @@ -200,13 +200,16 @@ device is already correct. nftl->lastEUN = nftl->nb_blocks - 1; /* memory alloc */ - nftl->EUNtable = kmalloc(nftl->nb_blocks * sizeof(u16), GFP_KERNEL); + nftl->EUNtable = kmalloc_array(nftl->nb_blocks, sizeof(u16), + GFP_KERNEL); if (!nftl->EUNtable) { printk(KERN_NOTICE "NFTL: allocation of EUNtable failed\n"); return -ENOMEM; } - nftl->ReplUnitTable = kmalloc(nftl->nb_blocks * sizeof(u16), GFP_KERNEL); + nftl->ReplUnitTable = kmalloc_array(nftl->nb_blocks, + sizeof(u16), + GFP_KERNEL); if (!nftl->ReplUnitTable) { kfree(nftl->EUNtable); printk(KERN_NOTICE "NFTL: allocation of ReplUnitTable failed\n"); diff --git a/drivers/mtd/sm_ftl.c b/drivers/mtd/sm_ftl.c index 3692dd547879..aed391b68ef6 100644 --- a/drivers/mtd/sm_ftl.c +++ b/drivers/mtd/sm_ftl.c @@ -768,7 +768,7 @@ static int sm_init_zone(struct sm_ftl *ftl, int zone_num) dbg("initializing zone %d", zone_num); /* Allocate memory for FTL table */ - zone->lba_to_phys_table = kmalloc(ftl->max_lba * 2, GFP_KERNEL); + zone->lba_to_phys_table = kmalloc_array(ftl->max_lba, 2, GFP_KERNEL); if (!zone->lba_to_phys_table) return -ENOMEM; diff --git a/drivers/mtd/ssfdc.c b/drivers/mtd/ssfdc.c index 95f0bf95f095..d746d983ad8e 100644 --- a/drivers/mtd/ssfdc.c +++ b/drivers/mtd/ssfdc.c @@ -332,8 +332,9 @@ static void ssfdcr_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) (long)ssfdc->sectors; /* Allocate logical block map */ - ssfdc->logic_block_map = kmalloc(sizeof(ssfdc->logic_block_map[0]) * - ssfdc->map_len, GFP_KERNEL); + ssfdc->logic_block_map = kmalloc_array(ssfdc->map_len, + sizeof(ssfdc->logic_block_map[0]), + GFP_KERNEL); if (!ssfdc->logic_block_map) goto out_err; memset(ssfdc->logic_block_map, 0xff, sizeof(ssfdc->logic_block_map[0]) * diff --git a/drivers/mtd/tests/stresstest.c b/drivers/mtd/tests/stresstest.c index e509f8aa9a7e..0fe1217f94b9 100644 --- a/drivers/mtd/tests/stresstest.c +++ b/drivers/mtd/tests/stresstest.c @@ -199,7 +199,7 @@ static int __init mtd_stresstest_init(void) err = -ENOMEM; readbuf = vmalloc(bufsize); writebuf = vmalloc(bufsize); - offsets = kmalloc(ebcnt * sizeof(int), GFP_KERNEL); + offsets = kmalloc_array(ebcnt, sizeof(int), GFP_KERNEL); if (!readbuf || !writebuf || !offsets) goto out; for (i = 0; i < ebcnt; i++) diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index c4d4b8f07630..f9cb8528e29f 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c @@ -1519,11 +1519,11 @@ int self_check_eba(struct ubi_device *ubi, struct ubi_attach_info *ai_fastmap, num_volumes = ubi->vtbl_slots + UBI_INT_VOL_COUNT; - scan_eba = kmalloc(sizeof(*scan_eba) * num_volumes, GFP_KERNEL); + scan_eba = kmalloc_array(num_volumes, sizeof(*scan_eba), GFP_KERNEL); if (!scan_eba) return -ENOMEM; - fm_eba = kmalloc(sizeof(*fm_eba) * num_volumes, GFP_KERNEL); + fm_eba = kmalloc_array(num_volumes, sizeof(*fm_eba), GFP_KERNEL); if (!fm_eba) { kfree(scan_eba); return -ENOMEM; @@ -1534,15 +1534,17 @@ int self_check_eba(struct ubi_device *ubi, struct ubi_attach_info *ai_fastmap, if (!vol) continue; - scan_eba[i] = kmalloc(vol->reserved_pebs * sizeof(**scan_eba), - GFP_KERNEL); + scan_eba[i] = kmalloc_array(vol->reserved_pebs, + sizeof(**scan_eba), + GFP_KERNEL); if (!scan_eba[i]) { ret = -ENOMEM; goto out_free; } - fm_eba[i] = kmalloc(vol->reserved_pebs * sizeof(**fm_eba), - GFP_KERNEL); + fm_eba[i] = kmalloc_array(vol->reserved_pebs, + sizeof(**fm_eba), + GFP_KERNEL); if (!fm_eba[i]) { ret = -ENOMEM; goto out_free; diff --git a/drivers/net/ethernet/amd/lance.c b/drivers/net/ethernet/amd/lance.c index 12a6a93d221b..e4326908456e 100644 --- a/drivers/net/ethernet/amd/lance.c +++ b/drivers/net/ethernet/amd/lance.c @@ -551,13 +551,13 @@ static int __init lance_probe1(struct net_device *dev, int ioaddr, int irq, int if (lance_debug > 6) printk(" (#0x%05lx)", (unsigned long)lp); dev->ml_priv = lp; lp->name = chipname; - lp->rx_buffs = (unsigned long)kmalloc(PKT_BUF_SZ*RX_RING_SIZE, - GFP_DMA | GFP_KERNEL); + lp->rx_buffs = (unsigned long) kmalloc_array(RX_RING_SIZE, PKT_BUF_SZ, + GFP_DMA | GFP_KERNEL); if (!lp->rx_buffs) goto out_lp; if (lance_need_isa_bounce_buffers) { - lp->tx_bounce_buffs = kmalloc(PKT_BUF_SZ*TX_RING_SIZE, - GFP_DMA | GFP_KERNEL); + lp->tx_bounce_buffs = kmalloc_array(TX_RING_SIZE, PKT_BUF_SZ, + GFP_DMA | GFP_KERNEL); if (!lp->tx_bounce_buffs) goto out_rx; } else diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c b/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c index cfe86a20c899..28e9ae1a193b 100644 --- a/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c @@ -209,8 +209,8 @@ static int atl1c_get_eeprom(struct net_device *netdev, first_dword = eeprom->offset >> 2; last_dword = (eeprom->offset + eeprom->len - 1) >> 2; - eeprom_buff = kmalloc(sizeof(u32) * - (last_dword - first_dword + 1), GFP_KERNEL); + eeprom_buff = kmalloc_array(last_dword - first_dword + 1, sizeof(u32), + GFP_KERNEL); if (eeprom_buff == NULL) return -ENOMEM; diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c b/drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c index cb489e7e8374..282ebdde4769 100644 --- a/drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c +++ b/drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c @@ -236,8 +236,8 @@ static int atl1e_get_eeprom(struct net_device *netdev, first_dword = eeprom->offset >> 2; last_dword = (eeprom->offset + eeprom->len - 1) >> 2; - eeprom_buff = kmalloc(sizeof(u32) * - (last_dword - first_dword + 1), GFP_KERNEL); + eeprom_buff = kmalloc_array(last_dword - first_dword + 1, sizeof(u32), + GFP_KERNEL); if (eeprom_buff == NULL) return -ENOMEM; diff --git a/drivers/net/ethernet/atheros/atlx/atl2.c b/drivers/net/ethernet/atheros/atlx/atl2.c index 225b4d452e0e..ee6983e6bb14 100644 --- a/drivers/net/ethernet/atheros/atlx/atl2.c +++ b/drivers/net/ethernet/atheros/atlx/atl2.c @@ -1940,8 +1940,8 @@ static int atl2_get_eeprom(struct net_device *netdev, first_dword = eeprom->offset >> 2; last_dword = (eeprom->offset + eeprom->len - 1) >> 2; - eeprom_buff = kmalloc(sizeof(u32) * (last_dword - first_dword + 1), - GFP_KERNEL); + eeprom_buff = kmalloc_array(last_dword - first_dword + 1, sizeof(u32), + GFP_KERNEL); if (!eeprom_buff) return -ENOMEM; diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c index e3af1f3cb61f..01666afa9aad 100644 --- a/drivers/net/ethernet/broadcom/bnx2.c +++ b/drivers/net/ethernet/broadcom/bnx2.c @@ -2666,7 +2666,7 @@ bnx2_alloc_bad_rbuf(struct bnx2 *bp) u32 good_mbuf_cnt; u32 val; - good_mbuf = kmalloc(512 * sizeof(u16), GFP_KERNEL); + good_mbuf = kmalloc_array(512, sizeof(u16), GFP_KERNEL); if (good_mbuf == NULL) return -ENOMEM; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c index e75db04c6cdc..3d85568ddc58 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c @@ -350,8 +350,8 @@ static int bnxt_vf_reps_create(struct bnxt *bp) return -ENOMEM; /* storage for cfa_code to vf-idx mapping */ - cfa_code_map = kmalloc(sizeof(*bp->cfa_code_map) * MAX_CFA_CODE, - GFP_KERNEL); + cfa_code_map = kmalloc_array(MAX_CFA_CODE, sizeof(*bp->cfa_code_map), + GFP_KERNEL); if (!cfa_code_map) { rc = -ENOMEM; goto err; diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c index 8bd90ad15607..2812ea7a1fb3 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c @@ -868,7 +868,7 @@ static int cctrl_tbl_show(struct seq_file *seq, void *v) u16 (*incr)[NCCTRL_WIN]; struct adapter *adap = seq->private; - incr = kmalloc(sizeof(*incr) * NMTUS, GFP_KERNEL); + incr = kmalloc_array(NMTUS, sizeof(*incr), GFP_KERNEL); if (!incr) return -ENOMEM; diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index 6eb65b870da7..946c763e5109 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -682,7 +682,7 @@ int cxgb4_write_rss(const struct port_info *pi, const u16 *queues) const struct sge_eth_rxq *rxq; rxq = &adapter->sge.ethrxq[pi->first_qset]; - rss = kmalloc(pi->rss_size * sizeof(u16), GFP_KERNEL); + rss = kmalloc_array(pi->rss_size, sizeof(u16), GFP_KERNEL); if (!rss) return -ENOMEM; @@ -4376,8 +4376,8 @@ static int enable_msix(struct adapter *adap) max_ingq += (MAX_OFLD_QSETS * adap->num_uld); if (is_offload(adap)) max_ingq += (MAX_OFLD_QSETS * adap->num_ofld_uld); - entries = kmalloc(sizeof(*entries) * (max_ingq + 1), - GFP_KERNEL); + entries = kmalloc_array(max_ingq + 1, sizeof(*entries), + GFP_KERNEL); if (!entries) return -ENOMEM; diff --git a/drivers/net/ethernet/freescale/ucc_geth.c b/drivers/net/ethernet/freescale/ucc_geth.c index 7c2a9fd4dc1a..0ea5ee1a44a7 100644 --- a/drivers/net/ethernet/freescale/ucc_geth.c +++ b/drivers/net/ethernet/freescale/ucc_geth.c @@ -2256,9 +2256,9 @@ static int ucc_geth_alloc_tx(struct ucc_geth_private *ugeth) /* Init Tx bds */ for (j = 0; j < ug_info->numQueuesTx; j++) { /* Setup the skbuff rings */ - ugeth->tx_skbuff[j] = kmalloc(sizeof(struct sk_buff *) * - ugeth->ug_info->bdRingLenTx[j], - GFP_KERNEL); + ugeth->tx_skbuff[j] = kmalloc_array(ugeth->ug_info->bdRingLenTx[j], + sizeof(struct sk_buff *), + GFP_KERNEL); if (ugeth->tx_skbuff[j] == NULL) { if (netif_msg_ifup(ugeth)) @@ -2329,9 +2329,9 @@ static int ucc_geth_alloc_rx(struct ucc_geth_private *ugeth) /* Init Rx bds */ for (j = 0; j < ug_info->numQueuesRx; j++) { /* Setup the skbuff rings */ - ugeth->rx_skbuff[j] = kmalloc(sizeof(struct sk_buff *) * - ugeth->ug_info->bdRingLenRx[j], - GFP_KERNEL); + ugeth->rx_skbuff[j] = kmalloc_array(ugeth->ug_info->bdRingLenRx[j], + sizeof(struct sk_buff *), + GFP_KERNEL); if (ugeth->rx_skbuff[j] == NULL) { if (netif_msg_ifup(ugeth)) diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c index b43aebfc7f5b..819c22b23eb3 100644 --- a/drivers/net/ethernet/ibm/ibmveth.c +++ b/drivers/net/ethernet/ibm/ibmveth.c @@ -171,7 +171,7 @@ static int ibmveth_alloc_buffer_pool(struct ibmveth_buff_pool *pool) { int i; - pool->free_map = kmalloc(sizeof(u16) * pool->size, GFP_KERNEL); + pool->free_map = kmalloc_array(pool->size, sizeof(u16), GFP_KERNEL); if (!pool->free_map) return -1; diff --git a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c index 88b34f722337..a562c443d9d4 100644 --- a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c +++ b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c @@ -455,8 +455,8 @@ static int e1000_get_eeprom(struct net_device *netdev, first_word = eeprom->offset >> 1; last_word = (eeprom->offset + eeprom->len - 1) >> 1; - eeprom_buff = kmalloc(sizeof(u16) * - (last_word - first_word + 1), GFP_KERNEL); + eeprom_buff = kmalloc_array(last_word - first_word + 1, sizeof(u16), + GFP_KERNEL); if (!eeprom_buff) return -ENOMEM; diff --git a/drivers/net/ethernet/intel/e1000e/ethtool.c b/drivers/net/ethernet/intel/e1000e/ethtool.c index 003cbd605799..6faf7bf3497e 100644 --- a/drivers/net/ethernet/intel/e1000e/ethtool.c +++ b/drivers/net/ethernet/intel/e1000e/ethtool.c @@ -527,8 +527,8 @@ static int e1000_get_eeprom(struct net_device *netdev, first_word = eeprom->offset >> 1; last_word = (eeprom->offset + eeprom->len - 1) >> 1; - eeprom_buff = kmalloc(sizeof(u16) * (last_word - first_word + 1), - GFP_KERNEL); + eeprom_buff = kmalloc_array(last_word - first_word + 1, sizeof(u16), + GFP_KERNEL); if (!eeprom_buff) return -ENOMEM; diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c index ff2be34bff39..bd8102ded442 100644 --- a/drivers/net/ethernet/intel/igb/igb_ethtool.c +++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c @@ -757,8 +757,8 @@ static int igb_get_eeprom(struct net_device *netdev, first_word = eeprom->offset >> 1; last_word = (eeprom->offset + eeprom->len - 1) >> 1; - eeprom_buff = kmalloc(sizeof(u16) * - (last_word - first_word + 1), GFP_KERNEL); + eeprom_buff = kmalloc_array(last_word - first_word + 1, sizeof(u16), + GFP_KERNEL); if (!eeprom_buff) return -ENOMEM; @@ -3203,8 +3203,8 @@ static int igb_get_module_eeprom(struct net_device *netdev, first_word = ee->offset >> 1; last_word = (ee->offset + ee->len - 1) >> 1; - dataword = kmalloc(sizeof(u16) * (last_word - first_word + 1), - GFP_KERNEL); + dataword = kmalloc_array(last_word - first_word + 1, sizeof(u16), + GFP_KERNEL); if (!dataword) return -ENOMEM; diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_ethtool.c b/drivers/net/ethernet/intel/ixgb/ixgb_ethtool.c index d10a0d242dda..488020475cec 100644 --- a/drivers/net/ethernet/intel/ixgb/ixgb_ethtool.c +++ b/drivers/net/ethernet/intel/ixgb/ixgb_ethtool.c @@ -400,8 +400,9 @@ ixgb_get_eeprom(struct net_device *netdev, first_word = eeprom->offset >> 1; last_word = (eeprom->offset + eeprom->len - 1) >> 1; - eeprom_buff = kmalloc(sizeof(__le16) * - (last_word - first_word + 1), GFP_KERNEL); + eeprom_buff = kmalloc_array(last_word - first_word + 1, + sizeof(__le16), + GFP_KERNEL); if (!eeprom_buff) return -ENOMEM; diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_main.c b/drivers/net/ethernet/intel/ixgb/ixgb_main.c index 5a713199653c..49c65ba4bdf3 100644 --- a/drivers/net/ethernet/intel/ixgb/ixgb_main.c +++ b/drivers/net/ethernet/intel/ixgb/ixgb_main.c @@ -1120,8 +1120,9 @@ ixgb_set_multi(struct net_device *netdev) rctl |= IXGB_RCTL_MPE; IXGB_WRITE_REG(hw, RCTL, rctl); } else { - u8 *mta = kmalloc(IXGB_MAX_NUM_MULTICAST_ADDRESSES * - ETH_ALEN, GFP_ATOMIC); + u8 *mta = kmalloc_array(ETH_ALEN, + IXGB_MAX_NUM_MULTICAST_ADDRESSES, + GFP_ATOMIC); u8 *addr; if (!mta) goto alloc_failed; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c index f7e68083200c..94d6f8bb9687 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c @@ -922,7 +922,7 @@ static int ixgbe_get_eeprom(struct net_device *netdev, last_word = (eeprom->offset + eeprom->len - 1) >> 1; eeprom_len = last_word - first_word + 1; - eeprom_buff = kmalloc(sizeof(u16) * eeprom_len, GFP_KERNEL); + eeprom_buff = kmalloc_array(eeprom_len, sizeof(u16), GFP_KERNEL); if (!eeprom_buff) return -ENOMEM; diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c index 4c2ee9fd9e57..fba2547eb689 100644 --- a/drivers/net/ethernet/mellanox/mlx4/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c @@ -2636,9 +2636,9 @@ int mlx4_cmd_use_events(struct mlx4_dev *dev) int i; int err = 0; - priv->cmd.context = kmalloc(priv->cmd.max_cmds * - sizeof(struct mlx4_cmd_context), - GFP_KERNEL); + priv->cmd.context = kmalloc_array(priv->cmd.max_cmds, + sizeof(struct mlx4_cmd_context), + GFP_KERNEL); if (!priv->cmd.context) return -ENOMEM; diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c index 050dc213e8db..2df92dbd38e1 100644 --- a/drivers/net/ethernet/mellanox/mlx4/eq.c +++ b/drivers/net/ethernet/mellanox/mlx4/eq.c @@ -1212,8 +1212,9 @@ int mlx4_init_eq_table(struct mlx4_dev *dev) } priv->eq_table.irq_names = - kmalloc(MLX4_IRQNAME_SIZE * (dev->caps.num_comp_vectors + 1), - GFP_KERNEL); + kmalloc_array(MLX4_IRQNAME_SIZE, + (dev->caps.num_comp_vectors + 1), + GFP_KERNEL); if (!priv->eq_table.irq_names) { err = -ENOMEM; goto err_out_clr_int; diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index 66e8054a8966..9a0076f36a81 100644 --- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c @@ -525,10 +525,12 @@ int mlx4_init_resource_tracker(struct mlx4_dev *dev) for (i = 0; i < MLX4_NUM_OF_RESOURCE_TYPE; i++) { struct resource_allocator *res_alloc = &priv->mfunc.master.res_tracker.res_alloc[i]; - res_alloc->quota = kmalloc((dev->persist->num_vfs + 1) * - sizeof(int), GFP_KERNEL); - res_alloc->guaranteed = kmalloc((dev->persist->num_vfs + 1) * - sizeof(int), GFP_KERNEL); + res_alloc->quota = kmalloc_array(dev->persist->num_vfs + 1, + sizeof(int), + GFP_KERNEL); + res_alloc->guaranteed = kmalloc_array(dev->persist->num_vfs + 1, + sizeof(int), + GFP_KERNEL); if (i == RES_MAC || i == RES_VLAN) res_alloc->allocated = kzalloc(MLX4_MAX_PORTS * (dev->persist->num_vfs diff --git a/drivers/net/ethernet/moxa/moxart_ether.c b/drivers/net/ethernet/moxa/moxart_ether.c index beb730ff5d42..4db3431b79ac 100644 --- a/drivers/net/ethernet/moxa/moxart_ether.c +++ b/drivers/net/ethernet/moxa/moxart_ether.c @@ -507,15 +507,15 @@ static int moxart_mac_probe(struct platform_device *pdev) goto init_fail; } - priv->tx_buf_base = kmalloc(priv->tx_buf_size * TX_DESC_NUM, - GFP_ATOMIC); + priv->tx_buf_base = kmalloc_array(priv->tx_buf_size, TX_DESC_NUM, + GFP_ATOMIC); if (!priv->tx_buf_base) { ret = -ENOMEM; goto init_fail; } - priv->rx_buf_base = kmalloc(priv->rx_buf_size * RX_DESC_NUM, - GFP_ATOMIC); + priv->rx_buf_base = kmalloc_array(priv->rx_buf_size, RX_DESC_NUM, + GFP_ATOMIC); if (!priv->rx_buf_base) { ret = -ENOMEM; goto init_fail; diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c index 994a83a1f0a5..1f869f1267ca 100644 --- a/drivers/net/ethernet/nvidia/forcedeth.c +++ b/drivers/net/ethernet/nvidia/forcedeth.c @@ -4599,8 +4599,10 @@ static int nv_set_ringparam(struct net_device *dev, struct ethtool_ringparam* ri sizeof(struct ring_desc_ex) * (ring->rx_pending + ring->tx_pending), &ring_addr); } - rx_skbuff = kmalloc(sizeof(struct nv_skb_map) * ring->rx_pending, GFP_KERNEL); - tx_skbuff = kmalloc(sizeof(struct nv_skb_map) * ring->tx_pending, GFP_KERNEL); + rx_skbuff = kmalloc_array(ring->rx_pending, sizeof(struct nv_skb_map), + GFP_KERNEL); + tx_skbuff = kmalloc_array(ring->tx_pending, sizeof(struct nv_skb_map), + GFP_KERNEL); if (!rxtx_ring || !rx_skbuff || !tx_skbuff) { /* fall back to old rings */ if (!nv_optimized(np)) { diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c index 5ae9681a2da7..069d78a44cbd 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c @@ -2187,7 +2187,7 @@ static void pch_gbe_set_multi(struct net_device *netdev) if (mc_count >= PCH_GBE_MAR_ENTRIES) return; - mta_list = kmalloc(mc_count * ETH_ALEN, GFP_ATOMIC); + mta_list = kmalloc_array(ETH_ALEN, mc_count, GFP_ATOMIC); if (!mta_list) return; diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/drivers/net/ethernet/qlogic/qlge/qlge_main.c index 0e3b2890b925..c693e5e8dada 100644 --- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c +++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c @@ -2805,7 +2805,8 @@ static int ql_alloc_tx_resources(struct ql_adapter *qdev, goto pci_alloc_err; tx_ring->q = - kmalloc(tx_ring->wq_len * sizeof(struct tx_ring_desc), GFP_KERNEL); + kmalloc_array(tx_ring->wq_len, sizeof(struct tx_ring_desc), + GFP_KERNEL); if (tx_ring->q == NULL) goto err; diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index 090607e725a2..848b69ca3e1f 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -771,13 +771,13 @@ static int gtp_hashtable_new(struct gtp_dev *gtp, int hsize) { int i; - gtp->addr_hash = kmalloc(sizeof(struct hlist_head) * hsize, - GFP_KERNEL | __GFP_NOWARN); + gtp->addr_hash = kmalloc_array(hsize, sizeof(struct hlist_head), + GFP_KERNEL | __GFP_NOWARN); if (gtp->addr_hash == NULL) return -ENOMEM; - gtp->tid_hash = kmalloc(sizeof(struct hlist_head) * hsize, - GFP_KERNEL | __GFP_NOWARN); + gtp->tid_hash = kmalloc_array(hsize, sizeof(struct hlist_head), + GFP_KERNEL | __GFP_NOWARN); if (gtp->tid_hash == NULL) goto err1; diff --git a/drivers/net/hippi/rrunner.c b/drivers/net/hippi/rrunner.c index 40ef4aeb0ef0..aa684660cc84 100644 --- a/drivers/net/hippi/rrunner.c +++ b/drivers/net/hippi/rrunner.c @@ -1585,7 +1585,7 @@ static int rr_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) return -EPERM; } - image = kmalloc(EEPROM_WORDS * sizeof(u32), GFP_KERNEL); + image = kmalloc_array(EEPROM_WORDS, sizeof(u32), GFP_KERNEL); if (!image) return -ENOMEM; diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index 396a8c6cb999..636411f46220 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -784,7 +784,8 @@ static int team_queue_override_init(struct team *team) if (!queue_cnt) return 0; - listarr = kmalloc(sizeof(struct list_head) * queue_cnt, GFP_KERNEL); + listarr = kmalloc_array(queue_cnt, sizeof(struct list_head), + GFP_KERNEL); if (!listarr) return -ENOMEM; team->qom_lists = listarr; diff --git a/drivers/net/usb/asix_common.c b/drivers/net/usb/asix_common.c index e9fcf6ef716a..347ef693c3b9 100644 --- a/drivers/net/usb/asix_common.c +++ b/drivers/net/usb/asix_common.c @@ -643,8 +643,8 @@ int asix_get_eeprom(struct net_device *net, struct ethtool_eeprom *eeprom, first_word = eeprom->offset >> 1; last_word = (eeprom->offset + eeprom->len - 1) >> 1; - eeprom_buff = kmalloc(sizeof(u16) * (last_word - first_word + 1), - GFP_KERNEL); + eeprom_buff = kmalloc_array(last_word - first_word + 1, sizeof(u16), + GFP_KERNEL); if (!eeprom_buff) return -ENOMEM; @@ -683,8 +683,8 @@ int asix_set_eeprom(struct net_device *net, struct ethtool_eeprom *eeprom, first_word = eeprom->offset >> 1; last_word = (eeprom->offset + eeprom->len - 1) >> 1; - eeprom_buff = kmalloc(sizeof(u16) * (last_word - first_word + 1), - GFP_KERNEL); + eeprom_buff = kmalloc_array(last_word - first_word + 1, sizeof(u16), + GFP_KERNEL); if (!eeprom_buff) return -ENOMEM; diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c index 5a2cdd2ccce6..75fbb8188c5c 100644 --- a/drivers/net/usb/ax88179_178a.c +++ b/drivers/net/usb/ax88179_178a.c @@ -602,8 +602,8 @@ ax88179_get_eeprom(struct net_device *net, struct ethtool_eeprom *eeprom, first_word = eeprom->offset >> 1; last_word = (eeprom->offset + eeprom->len - 1) >> 1; - eeprom_buff = kmalloc(sizeof(u16) * (last_word - first_word + 1), - GFP_KERNEL); + eeprom_buff = kmalloc_array(last_word - first_word + 1, sizeof(u16), + GFP_KERNEL); if (!eeprom_buff) return -ENOMEM; diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index c98a9738a025..29f4959a9ce8 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -1405,8 +1405,8 @@ static int build_dma_sg(const struct sk_buff *skb, struct urb *urb) return 0; /* reserve one for zero packet */ - urb->sg = kmalloc((num_sgs + 1) * sizeof(struct scatterlist), - GFP_ATOMIC); + urb->sg = kmalloc_array(num_sgs + 1, sizeof(struct scatterlist), + GFP_ATOMIC); if (!urb->sg) return -ENOMEM; diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 0b457c81c448..0c7a96334d82 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -2282,10 +2282,10 @@ static int virtnet_find_vqs(struct virtnet_info *vi) vqs = kzalloc(total_vqs * sizeof(*vqs), GFP_KERNEL); if (!vqs) goto err_vq; - callbacks = kmalloc(total_vqs * sizeof(*callbacks), GFP_KERNEL); + callbacks = kmalloc_array(total_vqs, sizeof(*callbacks), GFP_KERNEL); if (!callbacks) goto err_callback; - names = kmalloc(total_vqs * sizeof(*names), GFP_KERNEL); + names = kmalloc_array(total_vqs, sizeof(*names), GFP_KERNEL); if (!names) goto err_names; if (!vi->big_packets || vi->mergeable_rx_bufs) { diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 641b13a279e1..b1b8bc326830 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -890,7 +890,8 @@ ath5k_hw_rfregs_init(struct ath5k_hw *ah, * ah->ah_rf_banks based on ah->ah_rf_banks_size * we set above */ if (ah->ah_rf_banks == NULL) { - ah->ah_rf_banks = kmalloc(sizeof(u32) * ah->ah_rf_banks_size, + ah->ah_rf_banks = kmalloc_array(ah->ah_rf_banks_size, + sizeof(u32), GFP_KERNEL); if (ah->ah_rf_banks == NULL) { ATH5K_ERR(ah, "out of memory\n"); diff --git a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c index 6343cc91953e..34e100940284 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c @@ -925,7 +925,7 @@ int ar9003_paprd_create_curve(struct ath_hw *ah, memset(caldata->pa_table[chain], 0, sizeof(caldata->pa_table[chain])); - buf = kmalloc(2 * 48 * sizeof(u32), GFP_KERNEL); + buf = kmalloc_array(2 * 48, sizeof(u32), GFP_KERNEL); if (!buf) return -ENOMEM; diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 406b52f114f0..2a5039087116 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -127,13 +127,13 @@ void ath9k_hw_read_array(struct ath_hw *ah, u32 array[][2], int size) u32 *tmp_reg_list, *tmp_data; int i; - tmp_reg_list = kmalloc(size * sizeof(u32), GFP_KERNEL); + tmp_reg_list = kmalloc_array(size, sizeof(u32), GFP_KERNEL); if (!tmp_reg_list) { dev_err(ah->dev, "%s: tmp_reg_list: alloc filed\n", __func__); return; } - tmp_data = kmalloc(size * sizeof(u32), GFP_KERNEL); + tmp_data = kmalloc_array(size, sizeof(u32), GFP_KERNEL); if (!tmp_data) { dev_err(ah->dev, "%s tmp_data: alloc filed\n", __func__); goto error_tmp_data; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c index 93d4cde0eb31..a09f96b43a6b 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c @@ -1387,7 +1387,7 @@ wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi, s16 *ptr; struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; - ptr = kmalloc(sizeof(s16) * 131, GFP_ATOMIC); + ptr = kmalloc_array(131, sizeof(s16), GFP_ATOMIC); if (NULL == ptr) return false; if (module == 2) { @@ -2670,7 +2670,7 @@ wlc_lcnphy_tx_iqlo_cal(struct brcms_phy *pi, u16 *values_to_save; struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; - values_to_save = kmalloc(sizeof(u16) * 20, GFP_ATOMIC); + values_to_save = kmalloc_array(20, sizeof(u16), GFP_ATOMIC); if (NULL == values_to_save) return; @@ -3683,11 +3683,11 @@ wlc_lcnphy_a1(struct brcms_phy *pi, int cal_type, int num_levels, u16 *phy_c32; phy_c21 = 0; phy_c10 = phy_c13 = phy_c14 = phy_c8 = 0; - ptr = kmalloc(sizeof(s16) * 131, GFP_ATOMIC); + ptr = kmalloc_array(131, sizeof(s16), GFP_ATOMIC); if (NULL == ptr) return; - phy_c32 = kmalloc(sizeof(u16) * 20, GFP_ATOMIC); + phy_c32 = kmalloc_array(20, sizeof(u16), GFP_ATOMIC); if (NULL == phy_c32) { kfree(ptr); return; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c index ef685465f80a..1e67875cd07f 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c @@ -23116,7 +23116,7 @@ wlc_phy_loadsampletable_nphy(struct brcms_phy *pi, struct cordic_iq *tone_buf, u16 t; u32 *data_buf = NULL; - data_buf = kmalloc(sizeof(u32) * num_samps, GFP_ATOMIC); + data_buf = kmalloc_array(num_samps, sizeof(u32), GFP_ATOMIC); if (data_buf == NULL) return; @@ -23158,7 +23158,8 @@ wlc_phy_gen_load_samples_nphy(struct brcms_phy *pi, u32 f_kHz, u16 max_val, tbl_len = (phy_bw << 1); } - tone_buf = kmalloc(sizeof(struct cordic_iq) * tbl_len, GFP_ATOMIC); + tone_buf = kmalloc_array(tbl_len, sizeof(struct cordic_iq), + GFP_ATOMIC); if (tone_buf == NULL) return 0; diff --git a/drivers/net/wireless/cisco/airo.c b/drivers/net/wireless/cisco/airo.c index d06dc446a393..0a69649dd1e9 100644 --- a/drivers/net/wireless/cisco/airo.c +++ b/drivers/net/wireless/cisco/airo.c @@ -7139,7 +7139,7 @@ static int airo_get_aplist(struct net_device *dev, int i; int loseSync = capable(CAP_NET_ADMIN) ? 1: -1; - qual = kmalloc(IW_MAX_AP * sizeof(*qual), GFP_KERNEL); + qual = kmalloc_array(IW_MAX_AP, sizeof(*qual), GFP_KERNEL); if (!qual) return -ENOMEM; diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2100.c b/drivers/net/wireless/intel/ipw2x00/ipw2100.c index 8fbdd7d4fd0c..3f12ac09e75b 100644 --- a/drivers/net/wireless/intel/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/intel/ipw2x00/ipw2100.c @@ -3446,8 +3446,9 @@ static int ipw2100_msg_allocate(struct ipw2100_priv *priv) dma_addr_t p; priv->msg_buffers = - kmalloc(IPW_COMMAND_POOL_SIZE * sizeof(struct ipw2100_tx_packet), - GFP_KERNEL); + kmalloc_array(IPW_COMMAND_POOL_SIZE, + sizeof(struct ipw2100_tx_packet), + GFP_KERNEL); if (!priv->msg_buffers) return -ENOMEM; @@ -4589,9 +4590,9 @@ static int ipw2100_rx_allocate(struct ipw2100_priv *priv) /* * allocate packets */ - priv->rx_buffers = kmalloc(RX_QUEUE_LENGTH * - sizeof(struct ipw2100_rx_packet), - GFP_KERNEL); + priv->rx_buffers = kmalloc_array(RX_QUEUE_LENGTH, + sizeof(struct ipw2100_rx_packet), + GFP_KERNEL); if (!priv->rx_buffers) { IPW_DEBUG_INFO("can't allocate rx packet buffer table\n"); diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2200.c b/drivers/net/wireless/intel/ipw2x00/ipw2200.c index 2d0734ab3f74..54113802b2b9 100644 --- a/drivers/net/wireless/intel/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/intel/ipw2x00/ipw2200.c @@ -3216,13 +3216,13 @@ static int ipw_load_firmware(struct ipw_priv *priv, u8 * data, size_t len) IPW_DEBUG_TRACE("<< :\n"); - virts = kmalloc(sizeof(void *) * CB_NUMBER_OF_ELEMENTS_SMALL, - GFP_KERNEL); + virts = kmalloc_array(CB_NUMBER_OF_ELEMENTS_SMALL, sizeof(void *), + GFP_KERNEL); if (!virts) return -ENOMEM; - phys = kmalloc(sizeof(dma_addr_t) * CB_NUMBER_OF_ELEMENTS_SMALL, - GFP_KERNEL); + phys = kmalloc_array(CB_NUMBER_OF_ELEMENTS_SMALL, sizeof(dma_addr_t), + GFP_KERNEL); if (!phys) { kfree(virts); return -ENOMEM; @@ -3790,7 +3790,7 @@ static int ipw_queue_tx_init(struct ipw_priv *priv, { struct pci_dev *dev = priv->pci_dev; - q->txb = kmalloc(sizeof(q->txb[0]) * count, GFP_KERNEL); + q->txb = kmalloc_array(count, sizeof(q->txb[0]), GFP_KERNEL); if (!q->txb) { IPW_ERROR("vmalloc for auxiliary BD structures failed\n"); return -ENOMEM; diff --git a/drivers/net/wireless/intersil/hostap/hostap_info.c b/drivers/net/wireless/intersil/hostap/hostap_info.c index de8a099a9386..da8c30f10d92 100644 --- a/drivers/net/wireless/intersil/hostap/hostap_info.c +++ b/drivers/net/wireless/intersil/hostap/hostap_info.c @@ -271,8 +271,9 @@ static void prism2_info_scanresults(local_info_t *local, unsigned char *buf, left -= 4; new_count = left / sizeof(struct hfa384x_scan_result); - results = kmalloc(new_count * sizeof(struct hfa384x_hostscan_result), - GFP_ATOMIC); + results = kmalloc_array(new_count, + sizeof(struct hfa384x_hostscan_result), + GFP_ATOMIC); if (results == NULL) return; diff --git a/drivers/net/wireless/intersil/hostap/hostap_ioctl.c b/drivers/net/wireless/intersil/hostap/hostap_ioctl.c index c1bc0a6ef300..1ca9731d9b14 100644 --- a/drivers/net/wireless/intersil/hostap/hostap_ioctl.c +++ b/drivers/net/wireless/intersil/hostap/hostap_ioctl.c @@ -513,8 +513,8 @@ static int prism2_ioctl_giwaplist(struct net_device *dev, return -EOPNOTSUPP; } - addr = kmalloc(sizeof(struct sockaddr) * IW_MAX_AP, GFP_KERNEL); - qual = kmalloc(sizeof(struct iw_quality) * IW_MAX_AP, GFP_KERNEL); + addr = kmalloc_array(IW_MAX_AP, sizeof(struct sockaddr), GFP_KERNEL); + qual = kmalloc_array(IW_MAX_AP, sizeof(struct iw_quality), GFP_KERNEL); if (addr == NULL || qual == NULL) { kfree(addr); kfree(qual); diff --git a/drivers/net/wireless/zydas/zd1211rw/zd_mac.c b/drivers/net/wireless/zydas/zd1211rw/zd_mac.c index b785742bfd9e..59f48119f2cf 100644 --- a/drivers/net/wireless/zydas/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zydas/zd1211rw/zd_mac.c @@ -733,7 +733,8 @@ static int zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon, /* Alloc memory for full beacon write at once. */ num_cmds = 1 + zd_chip_is_zd1211b(&mac->chip) + full_len; - ioreqs = kmalloc(num_cmds * sizeof(struct zd_ioreq32), GFP_KERNEL); + ioreqs = kmalloc_array(num_cmds, sizeof(struct zd_ioreq32), + GFP_KERNEL); if (!ioreqs) { r = -ENOMEM; goto out_nofree; diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c index 55ef7d1fd8da..90be9b0a7b76 100644 --- a/drivers/pcmcia/cistpl.c +++ b/drivers/pcmcia/cistpl.c @@ -1481,11 +1481,11 @@ static ssize_t pccard_extract_cis(struct pcmcia_socket *s, char *buf, u_char *tuplebuffer; u_char *tempbuffer; - tuplebuffer = kmalloc(sizeof(u_char) * 256, GFP_KERNEL); + tuplebuffer = kmalloc_array(256, sizeof(u_char), GFP_KERNEL); if (!tuplebuffer) return -ENOMEM; - tempbuffer = kmalloc(sizeof(u_char) * 258, GFP_KERNEL); + tempbuffer = kmalloc_array(258, sizeof(u_char), GFP_KERNEL); if (!tempbuffer) { ret = -ENOMEM; goto free_tuple; diff --git a/drivers/pinctrl/freescale/pinctrl-imx.c b/drivers/pinctrl/freescale/pinctrl-imx.c index ec0119e1e781..071980dba20e 100644 --- a/drivers/pinctrl/freescale/pinctrl-imx.c +++ b/drivers/pinctrl/freescale/pinctrl-imx.c @@ -87,7 +87,8 @@ static int imx_dt_node_to_map(struct pinctrl_dev *pctldev, map_num++; } - new_map = kmalloc(sizeof(struct pinctrl_map) * map_num, GFP_KERNEL); + new_map = kmalloc_array(map_num, sizeof(struct pinctrl_map), + GFP_KERNEL); if (!new_map) return -ENOMEM; diff --git a/drivers/pinctrl/freescale/pinctrl-imx1-core.c b/drivers/pinctrl/freescale/pinctrl-imx1-core.c index 68108c4c3969..e994f8916f01 100644 --- a/drivers/pinctrl/freescale/pinctrl-imx1-core.c +++ b/drivers/pinctrl/freescale/pinctrl-imx1-core.c @@ -246,7 +246,8 @@ static int imx1_dt_node_to_map(struct pinctrl_dev *pctldev, for (i = 0; i < grp->npins; i++) map_num++; - new_map = kmalloc(sizeof(struct pinctrl_map) * map_num, GFP_KERNEL); + new_map = kmalloc_array(map_num, sizeof(struct pinctrl_map), + GFP_KERNEL); if (!new_map) return -ENOMEM; diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index cc8b86a16da0..6d351827facb 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c @@ -349,7 +349,7 @@ static int sunxi_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev, * any configuration. */ nmaps = npins * 2; - *map = kmalloc(nmaps * sizeof(struct pinctrl_map), GFP_KERNEL); + *map = kmalloc_array(nmaps, sizeof(struct pinctrl_map), GFP_KERNEL); if (!*map) return -ENOMEM; diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c index 4630782b5456..c2a1769ea08d 100644 --- a/drivers/s390/block/dasd_eer.c +++ b/drivers/s390/block/dasd_eer.c @@ -561,8 +561,8 @@ static int dasd_eer_open(struct inode *inp, struct file *filp) return -EINVAL; } eerb->buffersize = eerb->buffer_page_count * PAGE_SIZE; - eerb->buffer = kmalloc(eerb->buffer_page_count * sizeof(char *), - GFP_KERNEL); + eerb->buffer = kmalloc_array(eerb->buffer_page_count, sizeof(char *), + GFP_KERNEL); if (!eerb->buffer) { kfree(eerb); return -ENOMEM; diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c index 401688bf8fd3..046a9ce8f53b 100644 --- a/drivers/s390/char/tty3270.c +++ b/drivers/s390/char/tty3270.c @@ -717,7 +717,8 @@ tty3270_alloc_view(void) if (!tp) goto out_err; tp->freemem_pages = - kmalloc(sizeof(void *) * TTY3270_STRING_PAGES, GFP_KERNEL); + kmalloc_array(TTY3270_STRING_PAGES, sizeof(void *), + GFP_KERNEL); if (!tp->freemem_pages) goto out_tp; INIT_LIST_HEAD(&tp->freemem); diff --git a/drivers/s390/crypto/pkey_api.c b/drivers/s390/crypto/pkey_api.c index bd0376dc7e1e..93d695c3058e 100644 --- a/drivers/s390/crypto/pkey_api.c +++ b/drivers/s390/crypto/pkey_api.c @@ -126,7 +126,7 @@ static int alloc_and_prep_cprbmem(size_t paramblen, * allocate consecutive memory for request CPRB, request param * block, reply CPRB and reply param block */ - cprbmem = kmalloc(2 * cprbplusparamblen, GFP_KERNEL); + cprbmem = kmalloc_array(2, cprbplusparamblen, GFP_KERNEL); if (!cprbmem) return -ENOMEM; memset(cprbmem, 0, 2 * cprbplusparamblen); diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 7173ae53c526..1c7b551d6f3c 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -3978,7 +3978,7 @@ static int aac_convert_sgraw2(struct aac_raw_io2 *rio2, int pages, int nseg, int if (aac_convert_sgl == 0) return 0; - sge = kmalloc(nseg_new * sizeof(struct sge_ieee1212), GFP_ATOMIC); + sge = kmalloc_array(nseg_new, sizeof(struct sge_ieee1212), GFP_ATOMIC); if (sge == NULL) return -ENOMEM; diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c index 124217927c4a..41add33e3f1f 100644 --- a/drivers/scsi/aha1542.c +++ b/drivers/scsi/aha1542.c @@ -400,7 +400,8 @@ static int aha1542_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *cmd) #endif if (bufflen) { /* allocate memory before taking host_lock */ sg_count = scsi_sg_count(cmd); - cptr = kmalloc(sizeof(*cptr) * sg_count, GFP_KERNEL | GFP_DMA); + cptr = kmalloc_array(sg_count, sizeof(*cptr), + GFP_KERNEL | GFP_DMA); if (!cptr) return SCSI_MLQUEUE_HOST_BUSY; } else { diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c index 95d8f25cbcca..cfa39e0b9953 100644 --- a/drivers/scsi/aic7xxx/aic79xx_core.c +++ b/drivers/scsi/aic7xxx/aic79xx_core.c @@ -7074,7 +7074,8 @@ ahd_init(struct ahd_softc *ahd) AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK); ahd->stack_size = ahd_probe_stack_size(ahd); - ahd->saved_stack = kmalloc(ahd->stack_size * sizeof(uint16_t), GFP_ATOMIC); + ahd->saved_stack = kmalloc_array(ahd->stack_size, sizeof(uint16_t), + GFP_ATOMIC); if (ahd->saved_stack == NULL) return (ENOMEM); diff --git a/drivers/scsi/aic94xx/aic94xx_hwi.c b/drivers/scsi/aic94xx/aic94xx_hwi.c index f2671a8fa7e3..dfe8fc16b41b 100644 --- a/drivers/scsi/aic94xx/aic94xx_hwi.c +++ b/drivers/scsi/aic94xx/aic94xx_hwi.c @@ -291,7 +291,8 @@ static int asd_alloc_edbs(struct asd_ha_struct *asd_ha, gfp_t gfp_flags) struct asd_seq_data *seq = &asd_ha->seq; int i; - seq->edb_arr = kmalloc(seq->num_edbs*sizeof(*seq->edb_arr), gfp_flags); + seq->edb_arr = kmalloc_array(seq->num_edbs, sizeof(*seq->edb_arr), + gfp_flags); if (!seq->edb_arr) return -ENOMEM; @@ -323,8 +324,8 @@ static int asd_alloc_escbs(struct asd_ha_struct *asd_ha, struct asd_ascb *escb; int i, escbs; - seq->escb_arr = kmalloc(seq->num_escbs*sizeof(*seq->escb_arr), - gfp_flags); + seq->escb_arr = kmalloc_array(seq->num_escbs, sizeof(*seq->escb_arr), + gfp_flags); if (!seq->escb_arr) return -ENOMEM; diff --git a/drivers/scsi/arm/queue.c b/drivers/scsi/arm/queue.c index 3441ce3ebabf..996dfe903928 100644 --- a/drivers/scsi/arm/queue.c +++ b/drivers/scsi/arm/queue.c @@ -70,7 +70,7 @@ int queue_initialise (Queue_t *queue) * need to keep free lists or allocate this * memory. */ - queue->alloc = q = kmalloc(sizeof(QE_t) * nqueues, GFP_KERNEL); + queue->alloc = q = kmalloc_array(nqueues, sizeof(QE_t), GFP_KERNEL); if (q) { for (; nqueues; q++, nqueues--) { SET_MAGIC(q, QUEUE_MAGIC_FREE); diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index b4542e7e2ad5..d6ce7545f35a 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -2471,8 +2471,9 @@ static int beiscsi_alloc_mem(struct beiscsi_hba *phba) return -ENOMEM; } - mem_arr_orig = kmalloc(sizeof(*mem_arr_orig) * BEISCSI_MAX_FRAGS_INIT, - GFP_KERNEL); + mem_arr_orig = kmalloc_array(BEISCSI_MAX_FRAGS_INIT, + sizeof(*mem_arr_orig), + GFP_KERNEL); if (!mem_arr_orig) { kfree(phba->init_mem); kfree(phwi_ctrlr->wrb_context); @@ -2521,8 +2522,8 @@ static int beiscsi_alloc_mem(struct beiscsi_hba *phba) } while (alloc_size); mem_descr->num_elements = j; mem_descr->size_in_bytes = phba->mem_req[i]; - mem_descr->mem_array = kmalloc(sizeof(*mem_arr) * j, - GFP_KERNEL); + mem_descr->mem_array = kmalloc_array(j, sizeof(*mem_arr), + GFP_KERNEL); if (!mem_descr->mem_array) goto free_mem; @@ -3341,8 +3342,9 @@ beiscsi_create_wrb_rings(struct beiscsi_hba *phba, idx = 0; mem_descr = phba->init_mem; mem_descr += HWI_MEM_WRB; - pwrb_arr = kmalloc(sizeof(*pwrb_arr) * phba->params.cxns_per_ctrl, - GFP_KERNEL); + pwrb_arr = kmalloc_array(phba->params.cxns_per_ctrl, + sizeof(*pwrb_arr), + GFP_KERNEL); if (!pwrb_arr) { beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, "BM_%d : Memory alloc failed in create wrb ring.\n"); diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c index d95ba1a07ba3..bda52c11f489 100644 --- a/drivers/scsi/fcoe/fcoe_ctlr.c +++ b/drivers/scsi/fcoe/fcoe_ctlr.c @@ -1393,8 +1393,8 @@ static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip, */ num_vlink_desc = rlen / sizeof(*vp); if (num_vlink_desc) - vlink_desc_arr = kmalloc(sizeof(vp) * num_vlink_desc, - GFP_ATOMIC); + vlink_desc_arr = kmalloc_array(num_vlink_desc, sizeof(vp), + GFP_ATOMIC); if (!vlink_desc_arr) return; num_vlink_desc = 0; diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 3b892918d821..d3fc4922251b 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -2125,8 +2125,9 @@ static int hpsa_allocate_ioaccel2_sg_chain_blocks(struct ctlr_info *h) return -ENOMEM; for (i = 0; i < h->nr_cmds; i++) { h->ioaccel2_cmd_sg_list[i] = - kmalloc(sizeof(*h->ioaccel2_cmd_sg_list[i]) * - h->maxsgentries, GFP_KERNEL); + kmalloc_array(h->maxsgentries, + sizeof(*h->ioaccel2_cmd_sg_list[i]), + GFP_KERNEL); if (!h->ioaccel2_cmd_sg_list[i]) goto clean; } @@ -2164,8 +2165,9 @@ static int hpsa_alloc_sg_chain_blocks(struct ctlr_info *h) return -ENOMEM; for (i = 0; i < h->nr_cmds; i++) { - h->cmd_sg_list[i] = kmalloc(sizeof(*h->cmd_sg_list[i]) * - h->chainsize, GFP_KERNEL); + h->cmd_sg_list[i] = kmalloc_array(h->chainsize, + sizeof(*h->cmd_sg_list[i]), + GFP_KERNEL); if (!h->cmd_sg_list[i]) goto clean; @@ -6301,7 +6303,7 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp) status = -ENOMEM; goto cleanup1; } - buff_size = kmalloc(SG_ENTRIES_IN_CMD * sizeof(int), GFP_KERNEL); + buff_size = kmalloc_array(SG_ENTRIES_IN_CMD, sizeof(int), GFP_KERNEL); if (!buff_size) { status = -ENOMEM; goto cleanup1; @@ -7034,7 +7036,7 @@ static int controller_reset_failed(struct CfgTable __iomem *cfgtable) char *driver_ver, *old_driver_ver; int rc, size = sizeof(cfgtable->driver_version); - old_driver_ver = kmalloc(2 * size, GFP_KERNEL); + old_driver_ver = kmalloc_array(2, size, GFP_KERNEL); if (!old_driver_ver) return -ENOMEM; driver_ver = old_driver_ver + size; diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c index 87c08ff37ddd..9addd9ee48ea 100644 --- a/drivers/scsi/lpfc/lpfc_mem.c +++ b/drivers/scsi/lpfc/lpfc_mem.c @@ -120,8 +120,9 @@ lpfc_mem_alloc(struct lpfc_hba *phba, int align) if (!phba->lpfc_mbuf_pool) goto fail_free_dma_buf_pool; - pool->elements = kmalloc(sizeof(struct lpfc_dmabuf) * - LPFC_MBUF_POOL_SIZE, GFP_KERNEL); + pool->elements = kmalloc_array(LPFC_MBUF_POOL_SIZE, + sizeof(struct lpfc_dmabuf), + GFP_KERNEL); if (!pool->elements) goto fail_free_lpfc_mbuf_pool; diff --git a/drivers/scsi/mac53c94.c b/drivers/scsi/mac53c94.c index 8c4d3003b68b..177701dfdfcb 100644 --- a/drivers/scsi/mac53c94.c +++ b/drivers/scsi/mac53c94.c @@ -464,8 +464,9 @@ static int mac53c94_probe(struct macio_dev *mdev, const struct of_device_id *mat * +1 to allow for aligning. * XXX FIXME: Use DMA consistent routines */ - dma_cmd_space = kmalloc((host->sg_tablesize + 2) * - sizeof(struct dbdma_cmd), GFP_KERNEL); + dma_cmd_space = kmalloc_array(host->sg_tablesize + 2, + sizeof(struct dbdma_cmd), + GFP_KERNEL); if (dma_cmd_space == 0) { printk(KERN_ERR "mac53c94: couldn't allocate dma " "command space for %pOF\n", node); diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c index f5c09bbf9374..270cfcdaed5f 100644 --- a/drivers/scsi/megaraid.c +++ b/drivers/scsi/megaraid.c @@ -4325,7 +4325,8 @@ megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) goto out_host_put; } - adapter->scb_list = kmalloc(sizeof(scb_t) * MAX_COMMANDS, GFP_KERNEL); + adapter->scb_list = kmalloc_array(MAX_COMMANDS, sizeof(scb_t), + GFP_KERNEL); if (!adapter->scb_list) { dev_warn(&pdev->dev, "out of RAM\n"); goto out_free_cmd_buffer; diff --git a/drivers/scsi/megaraid/megaraid_mm.c b/drivers/scsi/megaraid/megaraid_mm.c index 65b6f6ace3a5..12aa285a6513 100644 --- a/drivers/scsi/megaraid/megaraid_mm.c +++ b/drivers/scsi/megaraid/megaraid_mm.c @@ -936,10 +936,12 @@ mraid_mm_register_adp(mraid_mmadp_t *lld_adp) * Allocate single blocks of memory for all required kiocs, * mailboxes and passthru structures. */ - adapter->kioc_list = kmalloc(sizeof(uioc_t) * lld_adp->max_kioc, - GFP_KERNEL); - adapter->mbox_list = kmalloc(sizeof(mbox64_t) * lld_adp->max_kioc, - GFP_KERNEL); + adapter->kioc_list = kmalloc_array(lld_adp->max_kioc, + sizeof(uioc_t), + GFP_KERNEL); + adapter->mbox_list = kmalloc_array(lld_adp->max_kioc, + sizeof(mbox64_t), + GFP_KERNEL); adapter->pthru_dma_pool = dma_pool_create("megaraid mm pthru pool", &adapter->pdev->dev, sizeof(mraid_passthru_t), diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index 20ec1c01dbd5..d04e4d433c9f 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c @@ -5856,7 +5856,9 @@ static int osst_probe(struct device *dev) /* if this is the first attach, build the infrastructure */ write_lock(&os_scsi_tapes_lock); if (os_scsi_tapes == NULL) { - os_scsi_tapes = kmalloc(osst_max_dev * sizeof(struct osst_tape *), GFP_ATOMIC); + os_scsi_tapes = kmalloc_array(osst_max_dev, + sizeof(struct osst_tape *), + GFP_ATOMIC); if (os_scsi_tapes == NULL) { write_unlock(&os_scsi_tapes_lock); printk(KERN_ERR "osst :E: Unable to allocate array for OnStream SCSI tapes.\n"); diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index a5b8313cf491..5becb875ae28 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -1230,7 +1230,7 @@ qla82xx_pinit_from_rom(scsi_qla_host_t *vha) ql_log(ql_log_info, vha, 0x0072, "%d CRB init values found in ROM.\n", n); - buf = kmalloc(n * sizeof(struct crb_addr_pair), GFP_KERNEL); + buf = kmalloc_array(n, sizeof(struct crb_addr_pair), GFP_KERNEL); if (buf == NULL) { ql_log(ql_log_fatal, vha, 0x010c, "Unable to allocate memory.\n"); diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c index e91abb327745..9815674d937b 100644 --- a/drivers/scsi/qla4xxx/ql4_nx.c +++ b/drivers/scsi/qla4xxx/ql4_nx.c @@ -1075,7 +1075,7 @@ qla4_82xx_pinit_from_rom(struct scsi_qla_host *ha, int verbose) ql4_printk(KERN_INFO, ha, "%s: %d CRB init values found in ROM.\n", DRIVER_NAME, n); - buf = kmalloc(n * sizeof(struct crb_addr_pair), GFP_KERNEL); + buf = kmalloc_array(n, sizeof(struct crb_addr_pair), GFP_KERNEL); if (buf == NULL) { ql4_printk(KERN_WARNING, ha, "%s: [ERROR] Unable to malloc memory.\n", DRIVER_NAME); diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c index 4055753b495a..01e74d499735 100644 --- a/drivers/scsi/smartpqi/smartpqi_init.c +++ b/drivers/scsi/smartpqi/smartpqi_init.c @@ -1826,8 +1826,9 @@ static int pqi_update_scsi_devices(struct pqi_ctrl_info *ctrl_info) num_new_devices = num_physicals + num_logicals; - new_device_list = kmalloc(sizeof(*new_device_list) * - num_new_devices, GFP_KERNEL); + new_device_list = kmalloc_array(num_new_devices, + sizeof(*new_device_list), + GFP_KERNEL); if (!new_device_list) { dev_warn(&ctrl_info->pci_dev->dev, "%s\n", out_of_memory_msg); rc = -ENOMEM; diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 94e402ed30f6..56c0eefa1cfc 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -4915,7 +4915,7 @@ static int sgl_map_user_pages(struct st_buffer *STbp, if (count == 0) return 0; - if ((pages = kmalloc(max_pages * sizeof(*pages), GFP_KERNEL)) == NULL) + if ((pages = kmalloc_array(max_pages, sizeof(*pages), GFP_KERNEL)) == NULL) return -ENOMEM; /* Try to fault in all of the necessary pages */ diff --git a/drivers/scsi/ufs/ufs_test.c b/drivers/scsi/ufs/ufs_test.c index 92b348590650..ad38eef26528 100644 --- a/drivers/scsi/ufs/ufs_test.c +++ b/drivers/scsi/ufs/ufs_test.c @@ -1309,8 +1309,8 @@ static int ufs_test_debugfs_init(void) utils_root = test_iosched_get_debugfs_utils_root(); tests_root = test_iosched_get_debugfs_tests_root(); - utd->test_list = kmalloc(sizeof(struct dentry *) * NUM_TESTS, - GFP_KERNEL); + utd->test_list = kmalloc_array(NUM_TESTS, sizeof(struct dentry *), + GFP_KERNEL); if (!utd->test_list) { pr_err("%s: failed to allocate tests dentrys", __func__); return -ENODEV; diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c index 1f4bd7d0154d..90540ccc14c5 100644 --- a/drivers/scsi/virtio_scsi.c +++ b/drivers/scsi/virtio_scsi.c @@ -830,9 +830,10 @@ static int virtscsi_init(struct virtio_device *vdev, struct irq_affinity desc = { .pre_vectors = 2 }; num_vqs = vscsi->num_queues + VIRTIO_SCSI_VQ_BASE; - vqs = kmalloc(num_vqs * sizeof(struct virtqueue *), GFP_KERNEL); - callbacks = kmalloc(num_vqs * sizeof(vq_callback_t *), GFP_KERNEL); - names = kmalloc(num_vqs * sizeof(char *), GFP_KERNEL); + vqs = kmalloc_array(num_vqs, sizeof(struct virtqueue *), GFP_KERNEL); + callbacks = kmalloc_array(num_vqs, sizeof(vq_callback_t *), + GFP_KERNEL); + names = kmalloc_array(num_vqs, sizeof(char *), GFP_KERNEL); if (!callbacks || !vqs || !names) { err = -ENOMEM; diff --git a/drivers/soc/fsl/qbman/qman.c b/drivers/soc/fsl/qbman/qman.c index 90892a360c61..5a0a640323fd 100644 --- a/drivers/soc/fsl/qbman/qman.c +++ b/drivers/soc/fsl/qbman/qman.c @@ -1153,7 +1153,7 @@ static int qman_create_portal(struct qman_portal *portal, qm_dqrr_set_ithresh(p, QMAN_PIRQ_DQRR_ITHRESH); qm_mr_set_ithresh(p, QMAN_PIRQ_MR_ITHRESH); qm_out(p, QM_REG_ITPR, QMAN_PIRQ_IPERIOD); - portal->cgrs = kmalloc(2 * sizeof(*cgrs), GFP_KERNEL); + portal->cgrs = kmalloc_array(2, sizeof(*cgrs), GFP_KERNEL); if (!portal->cgrs) goto fail_cgrs; /* initial snapshot is no-depletion */ diff --git a/drivers/soc/qcom/service-locator.c b/drivers/soc/qcom/service-locator.c index b35cd3b27d74..619cd44b0d26 100644 --- a/drivers/soc/qcom/service-locator.c +++ b/drivers/soc/qcom/service-locator.c @@ -210,9 +210,9 @@ static int service_locator_send_msg(struct pd_qmi_client_data *pd) goto out; } - pd->domain_list = kmalloc( - sizeof(struct servreg_loc_entry_v01) * - resp->total_domains, GFP_KERNEL); + pd->domain_list = kmalloc_array(resp->total_domains, + sizeof(struct servreg_loc_entry_v01), + GFP_KERNEL); if (!pd->domain_list) { pr_err("Cannot allocate domain list\n"); rc = -ENOMEM; diff --git a/drivers/staging/irda/net/discovery.c b/drivers/staging/irda/net/discovery.c index 364d70aed068..d48e9a839831 100644 --- a/drivers/staging/irda/net/discovery.c +++ b/drivers/staging/irda/net/discovery.c @@ -178,7 +178,9 @@ void irlmp_expire_discoveries(hashbin_t *log, __u32 saddr, int force) if(buffer == NULL) { /* Create the client specific buffer */ n = HASHBIN_GET_SIZE(log); - buffer = kmalloc(n * sizeof(struct irda_device_info), GFP_ATOMIC); + buffer = kmalloc_array(n, + sizeof(struct irda_device_info), + GFP_ATOMIC); if (buffer == NULL) { spin_unlock_irqrestore(&log->hb_spinlock, flags); return; @@ -290,7 +292,9 @@ struct irda_device_info *irlmp_copy_discoveries(hashbin_t *log, int *pn, if(buffer == NULL) { /* Create the client specific buffer */ n = HASHBIN_GET_SIZE(log); - buffer = kmalloc(n * sizeof(struct irda_device_info), GFP_ATOMIC); + buffer = kmalloc_array(n, + sizeof(struct irda_device_info), + GFP_ATOMIC); if (buffer == NULL) { spin_unlock_irqrestore(&log->hb_spinlock, flags); return NULL; diff --git a/drivers/staging/media/atomisp/pci/atomisp2/atomisp_fops.c b/drivers/staging/media/atomisp/pci/atomisp2/atomisp_fops.c index f1d8cc5a2730..f28ea9a2604b 100644 --- a/drivers/staging/media/atomisp/pci/atomisp2/atomisp_fops.c +++ b/drivers/staging/media/atomisp/pci/atomisp2/atomisp_fops.c @@ -1136,7 +1136,7 @@ static int remove_pad_from_frame(struct atomisp_device *isp, ia_css_ptr load = in_frame->data; ia_css_ptr store = load; - buffer = kmalloc(width*sizeof(load), GFP_KERNEL); + buffer = kmalloc_array(width, sizeof(load), GFP_KERNEL); if (!buffer) { dev_err(isp->dev, "out of memory.\n"); return -ENOMEM; diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css_firmware.c b/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css_firmware.c index 63582161050a..06f13e55e9d1 100644 --- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css_firmware.c +++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css_firmware.c @@ -226,9 +226,9 @@ sh_css_load_firmware(const char *fw_data, sh_css_num_binaries = file_header->binary_nr; /* Only allocate memory for ISP blob info */ if (sh_css_num_binaries > NUM_OF_SPS) { - sh_css_blob_info = kmalloc( - (sh_css_num_binaries - NUM_OF_SPS) * - sizeof(*sh_css_blob_info), GFP_KERNEL); + sh_css_blob_info = kmalloc_array(sh_css_num_binaries - NUM_OF_SPS, + sizeof(*sh_css_blob_info), + GFP_KERNEL); if (sh_css_blob_info == NULL) return IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; } else { diff --git a/drivers/staging/media/atomisp/pci/atomisp2/hmm/hmm_bo.c b/drivers/staging/media/atomisp/pci/atomisp2/hmm/hmm_bo.c index 11162f595fc7..929597713261 100644 --- a/drivers/staging/media/atomisp/pci/atomisp2/hmm/hmm_bo.c +++ b/drivers/staging/media/atomisp/pci/atomisp2/hmm/hmm_bo.c @@ -725,8 +725,8 @@ static int alloc_private_pages(struct hmm_buffer_object *bo, pgnr = bo->pgnr; - bo->page_obj = kmalloc(sizeof(struct hmm_page_object) * pgnr, - GFP_KERNEL); + bo->page_obj = kmalloc_array(pgnr, sizeof(struct hmm_page_object), + GFP_KERNEL); if (unlikely(!bo->page_obj)) { dev_err(atomisp_dev, "out of memory for bo->page_obj\n"); return -ENOMEM; @@ -990,14 +990,14 @@ static int alloc_user_pages(struct hmm_buffer_object *bo, struct vm_area_struct *vma; struct page **pages; - pages = kmalloc(sizeof(struct page *) * bo->pgnr, GFP_KERNEL); + pages = kmalloc_array(bo->pgnr, sizeof(struct page *), GFP_KERNEL); if (unlikely(!pages)) { dev_err(atomisp_dev, "out of memory for pages...\n"); return -ENOMEM; } - bo->page_obj = kmalloc(sizeof(struct hmm_page_object) * bo->pgnr, - GFP_KERNEL); + bo->page_obj = kmalloc_array(bo->pgnr, sizeof(struct hmm_page_object), + GFP_KERNEL); if (unlikely(!bo->page_obj)) { dev_err(atomisp_dev, "out of memory for bo->page_obj...\n"); kfree(pages); @@ -1363,7 +1363,7 @@ void *hmm_bo_vmap(struct hmm_buffer_object *bo, bool cached) bo->status &= ~(HMM_BO_VMAPED | HMM_BO_VMAPED_CACHED); } - pages = kmalloc(sizeof(*pages) * bo->pgnr, GFP_KERNEL); + pages = kmalloc_array(bo->pgnr, sizeof(*pages), GFP_KERNEL); if (unlikely(!pages)) { mutex_unlock(&bo->mutex); dev_err(atomisp_dev, "out of memory for pages...\n"); diff --git a/drivers/staging/media/atomisp/pci/atomisp2/hmm/hmm_reserved_pool.c b/drivers/staging/media/atomisp/pci/atomisp2/hmm/hmm_reserved_pool.c index bf6586805f7f..8bcef2445b48 100644 --- a/drivers/staging/media/atomisp/pci/atomisp2/hmm/hmm_reserved_pool.c +++ b/drivers/staging/media/atomisp/pci/atomisp2/hmm/hmm_reserved_pool.c @@ -97,8 +97,8 @@ static int hmm_reserved_pool_setup(struct hmm_reserved_pool_info **repool_info, return -ENOMEM; } - pool_info->pages = kmalloc(sizeof(struct page *) * pool_size, - GFP_KERNEL); + pool_info->pages = kmalloc_array(pool_size, sizeof(struct page *), + GFP_KERNEL); if (unlikely(!pool_info->pages)) { dev_err(atomisp_dev, "out of memory for repool_info->pages.\n"); kfree(pool_info); diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c index cbf8eb4a049d..afdd79d9dd93 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c @@ -597,8 +597,9 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee, bool bMatchWinStart = false, bPktInBuf = false; IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): Seq is %d,pTS->RxIndicateSeq is %d, WinSize is %d\n",__func__,SeqNum,pTS->RxIndicateSeq,WinSize); - prxbIndicateArray = kmalloc(sizeof(struct ieee80211_rxb *) * - REORDER_WIN_SIZE, GFP_KERNEL); + prxbIndicateArray = kmalloc_array(REORDER_WIN_SIZE, + sizeof(struct ieee80211_rxb *), + GFP_KERNEL); if (!prxbIndicateArray) return; diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c index fbbd1b59dc11..bbc2fadf65f5 100644 --- a/drivers/staging/rtl8192u/r8192U_core.c +++ b/drivers/staging/rtl8192u/r8192U_core.c @@ -1686,8 +1686,8 @@ static short rtl8192_usb_initendpoints(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); - priv->rx_urb = kmalloc(sizeof(struct urb *) * (MAX_RX_URB + 1), - GFP_KERNEL); + priv->rx_urb = kmalloc_array(MAX_RX_URB + 1, sizeof(struct urb *), + GFP_KERNEL); if (!priv->rx_urb) return -ENOMEM; diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c index f05e9af4fe81..77f1f4c91acc 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c @@ -2086,7 +2086,7 @@ dump_phys_mem(void *virt_addr, u32 num_bytes) num_pages = DIV_ROUND_UP(offset + num_bytes, PAGE_SIZE); - pages = kmalloc(sizeof(struct page *) * num_pages, GFP_KERNEL); + pages = kmalloc_array(num_pages, sizeof(struct page *), GFP_KERNEL); if (!pages) { vchiq_log_error(vchiq_arm_log_level, "Unable to allocation memory for %d pages\n", diff --git a/drivers/tty/hvc/hvcs.c b/drivers/tty/hvc/hvcs.c index 63c29fe9d21f..b55616b26fdc 100644 --- a/drivers/tty/hvc/hvcs.c +++ b/drivers/tty/hvc/hvcs.c @@ -1454,7 +1454,8 @@ static int hvcs_alloc_index_list(int n) { int i; - hvcs_index_list = kmalloc(n * sizeof(hvcs_index_count),GFP_KERNEL); + hvcs_index_list = kmalloc_array(n, sizeof(hvcs_index_count), + GFP_KERNEL); if (!hvcs_index_list) return -ENOMEM; hvcs_index_count = n; diff --git a/drivers/tty/isicom.c b/drivers/tty/isicom.c index 61ecdd6b2fc2..f7d8204ce09b 100644 --- a/drivers/tty/isicom.c +++ b/drivers/tty/isicom.c @@ -1485,7 +1485,7 @@ static int load_firmware(struct pci_dev *pdev, goto errrelfw; } - data = kmalloc(word_count * 2, GFP_KERNEL); + data = kmalloc_array(word_count, 2, GFP_KERNEL); if (data == NULL) { dev_err(&pdev->dev, "Card%d, firmware upload " "failed, not enough memory\n", index + 1); diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index a00227d312d3..690ecf9fa990 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -2789,8 +2789,9 @@ static int atmel_serial_probe(struct platform_device *pdev) if (!atmel_use_pdc_rx(&atmel_port->uart)) { ret = -ENOMEM; - data = kmalloc(sizeof(struct atmel_uart_char) - * ATMEL_SERIAL_RINGSIZE, GFP_KERNEL); + data = kmalloc_array(ATMEL_SERIAL_RINGSIZE, + sizeof(struct atmel_uart_char), + GFP_KERNEL); if (!data) goto err_alloc_ring; atmel_port->rx_ring.buf = data; diff --git a/drivers/tty/vt/consolemap.c b/drivers/tty/vt/consolemap.c index a5f88cf0f61d..749543d8e33e 100644 --- a/drivers/tty/vt/consolemap.c +++ b/drivers/tty/vt/consolemap.c @@ -230,7 +230,7 @@ static void set_inverse_trans_unicode(struct vc_data *conp, q = p->inverse_trans_unicode; if (!q) { q = p->inverse_trans_unicode = - kmalloc(MAX_GLYPH * sizeof(u16), GFP_KERNEL); + kmalloc_array(MAX_GLYPH, sizeof(u16), GFP_KERNEL); if (!q) return; } @@ -478,7 +478,8 @@ con_insert_unipair(struct uni_pagedir *p, u_short unicode, u_short fontpos) p1 = p->uni_pgdir[n = unicode >> 11]; if (!p1) { - p1 = p->uni_pgdir[n] = kmalloc(32*sizeof(u16 *), GFP_KERNEL); + p1 = p->uni_pgdir[n] = kmalloc_array(32, sizeof(u16 *), + GFP_KERNEL); if (!p1) return -ENOMEM; for (i = 0; i < 32; i++) p1[i] = NULL; @@ -486,7 +487,7 @@ con_insert_unipair(struct uni_pagedir *p, u_short unicode, u_short fontpos) p2 = p1[n = (unicode >> 6) & 0x1f]; if (!p2) { - p2 = p1[n] = kmalloc(64*sizeof(u16), GFP_KERNEL); + p2 = p1[n] = kmalloc_array(64, sizeof(u16), GFP_KERNEL); if (!p2) return -ENOMEM; memset(p2, 0xff, 64*sizeof(u16)); /* No glyphs for the characters (yet) */ } diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c index 610cb8338d53..dce5523d0736 100644 --- a/drivers/tty/vt/keyboard.c +++ b/drivers/tty/vt/keyboard.c @@ -1630,7 +1630,7 @@ int vt_do_diacrit(unsigned int cmd, void __user *udp, int perm) struct kbdiacr *dia; int i; - dia = kmalloc(MAX_DIACR * sizeof(struct kbdiacr), + dia = kmalloc_array(MAX_DIACR, sizeof(struct kbdiacr), GFP_KERNEL); if (!dia) return -ENOMEM; @@ -1663,7 +1663,7 @@ int vt_do_diacrit(unsigned int cmd, void __user *udp, int perm) struct kbdiacrsuc __user *a = udp; void *buf; - buf = kmalloc(MAX_DIACR * sizeof(struct kbdiacruc), + buf = kmalloc_array(MAX_DIACR, sizeof(struct kbdiacruc), GFP_KERNEL); if (buf == NULL) return -ENOMEM; diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c index 8687b17f6cf0..0a997c801b4d 100644 --- a/drivers/tty/vt/selection.c +++ b/drivers/tty/vt/selection.c @@ -301,7 +301,8 @@ static int __set_selection(const struct tiocl_selection __user *sel, struct tty_ /* Allocate a new buffer before freeing the old one ... */ multiplier = use_unicode ? 3 : 1; /* chars can take up to 3 bytes */ - bp = kmalloc(((sel_end-sel_start)/2+1)*multiplier, GFP_KERNEL); + bp = kmalloc_array((sel_end - sel_start) / 2 + 1, multiplier, + GFP_KERNEL); if (!bp) { printk(KERN_WARNING "selection: kmalloc() failed\n"); clear_selection(); diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 4fb4cf8c2f14..50f9da4ec99b 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -927,7 +927,7 @@ static int parse_usbdevfs_streams(struct usb_dev_state *ps, if (num_streams_ret && (num_streams < 2 || num_streams > 65536)) return -EINVAL; - eps = kmalloc(num_eps * sizeof(*eps), GFP_KERNEL); + eps = kmalloc_array(num_eps, sizeof(*eps), GFP_KERNEL); if (!eps) return -ENOMEM; @@ -1646,8 +1646,9 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb as->mem_usage = u; if (num_sgs) { - as->urb->sg = kmalloc(num_sgs * sizeof(struct scatterlist), - GFP_KERNEL); + as->urb->sg = kmalloc_array(num_sgs, + sizeof(struct scatterlist), + GFP_KERNEL); if (!as->urb->sg) { ret = -ENOMEM; goto error; diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 298c91f83aee..230acf0d44aa 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -389,7 +389,7 @@ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev, } /* initialize all the urbs we'll use */ - io->urbs = kmalloc(io->entries * sizeof(*io->urbs), mem_flags); + io->urbs = kmalloc_array(io->entries, sizeof(*io->urbs), mem_flags); if (!io->urbs) goto nomem; @@ -1782,8 +1782,8 @@ int usb_set_configuration(struct usb_device *dev, int configuration) n = nintf = 0; if (cp) { nintf = cp->desc.bNumInterfaces; - new_interfaces = kmalloc(nintf * sizeof(*new_interfaces), - GFP_NOIO); + new_interfaces = kmalloc_array(nintf, sizeof(*new_interfaces), + GFP_NOIO); if (!new_interfaces) return -ENOMEM; diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c index 3a61ee06e201..fa549c576911 100644 --- a/drivers/usb/gadget/ci13xxx_udc.c +++ b/drivers/usb/gadget/ci13xxx_udc.c @@ -1429,7 +1429,7 @@ static ssize_t show_registers(struct device *dev, return 0; } - dump = kmalloc(sizeof(u32) * DUMP_ENTRIES, GFP_KERNEL); + dump = kmalloc_array(DUMP_ENTRIES, sizeof(u32), GFP_KERNEL); if (!dump) return 0; diff --git a/drivers/usb/host/fhci-tds.c b/drivers/usb/host/fhci-tds.c index f82ad5df1b0d..9d39458dbab2 100644 --- a/drivers/usb/host/fhci-tds.c +++ b/drivers/usb/host/fhci-tds.c @@ -193,7 +193,7 @@ u32 fhci_create_ep(struct fhci_usb *usb, enum fhci_mem_alloc data_mem, goto err; } - buff = kmalloc(1028 * sizeof(*buff), GFP_KERNEL); + buff = kmalloc_array(1028, sizeof(*buff), GFP_KERNEL); if (!buff) { kfree(pkt); err_for = "buffer"; diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c index 56176222b0b6..86239e58aed5 100644 --- a/drivers/usb/host/ohci-dbg.c +++ b/drivers/usb/host/ohci-dbg.c @@ -491,7 +491,7 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf) char *next; unsigned i; - seen = kmalloc(DBG_SCHED_LIMIT * sizeof *seen, GFP_ATOMIC); + seen = kmalloc_array(DBG_SCHED_LIMIT, sizeof(*seen), GFP_ATOMIC); if (!seen) return 0; seen_count = 0; diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index e6ba86defeaf..7cbf6275055b 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -2387,8 +2387,9 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags) * Not sure how the USB core will handle a hub with no ports... */ if (xhci->num_usb2_ports) { - xhci->usb2_ports = kmalloc(sizeof(*xhci->usb2_ports)* - xhci->num_usb2_ports, flags); + xhci->usb2_ports = kmalloc_array(xhci->num_usb2_ports, + sizeof(*xhci->usb2_ports), + flags); if (!xhci->usb2_ports) return -ENOMEM; @@ -2412,8 +2413,9 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags) } } if (xhci->num_usb3_ports) { - xhci->usb3_ports = kmalloc(sizeof(*xhci->usb3_ports)* - xhci->num_usb3_ports, flags); + xhci->usb3_ports = kmalloc_array(xhci->num_usb3_ports, + sizeof(*xhci->usb3_ports), + flags); if (!xhci->usb3_ports) return -ENOMEM; diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c index e16af177d467..a1cab05f6b44 100644 --- a/drivers/usb/misc/ldusb.c +++ b/drivers/usb/misc/ldusb.c @@ -712,7 +712,9 @@ static int ld_usb_probe(struct usb_interface *intf, const struct usb_device_id * goto error; dev->interrupt_out_endpoint_size = dev->interrupt_out_endpoint ? usb_endpoint_maxp(dev->interrupt_out_endpoint) : udev->descriptor.bMaxPacketSize0; - dev->interrupt_out_buffer = kmalloc(write_buffer_size*dev->interrupt_out_endpoint_size, GFP_KERNEL); + dev->interrupt_out_buffer = kmalloc_array(write_buffer_size, + dev->interrupt_out_endpoint_size, + GFP_KERNEL); if (!dev->interrupt_out_buffer) goto error; dev->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL); diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index a1a11f8bb2a3..f7bdc2578fb7 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c @@ -744,7 +744,7 @@ static int iuu_uart_on(struct usb_serial_port *port) int status; u8 *buf; - buf = kmalloc(sizeof(u8) * 4, GFP_KERNEL); + buf = kmalloc(4, GFP_KERNEL); if (!buf) return -ENOMEM; @@ -798,7 +798,7 @@ static int iuu_uart_baud(struct usb_serial_port *port, u32 baud_base, unsigned int T1FrekvensHZ = 0; dev_dbg(&port->dev, "%s - enter baud_base=%d\n", __func__, baud_base); - dataout = kmalloc(sizeof(u8) * 5, GFP_KERNEL); + dataout = kmalloc(5, GFP_KERNEL); if (!dataout) return -ENOMEM; diff --git a/drivers/usb/storage/alauda.c b/drivers/usb/storage/alauda.c index 878b4b8761f5..049b0c3a44d5 100644 --- a/drivers/usb/storage/alauda.c +++ b/drivers/usb/storage/alauda.c @@ -1038,7 +1038,7 @@ static int alauda_write_data(struct us_data *us, unsigned long address, * We also need a temporary block buffer, where we read in the old data, * overwrite parts with the new data, and manipulate the redundancy data */ - blockbuffer = kmalloc((pagesize + 64) * blocksize, GFP_NOIO); + blockbuffer = kmalloc_array(pagesize + 64, blocksize, GFP_NOIO); if (!blockbuffer) { kfree(buffer); return USB_STOR_TRANSPORT_ERROR; diff --git a/drivers/usb/storage/ene_ub6250.c b/drivers/usb/storage/ene_ub6250.c index 28100374f7bd..397ecfdd8871 100644 --- a/drivers/usb/storage/ene_ub6250.c +++ b/drivers/usb/storage/ene_ub6250.c @@ -822,8 +822,12 @@ static int ms_lib_alloc_logicalmap(struct us_data *us) u32 i; struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; - info->MS_Lib.Phy2LogMap = kmalloc(info->MS_Lib.NumberOfPhyBlock * sizeof(u16), GFP_KERNEL); - info->MS_Lib.Log2PhyMap = kmalloc(info->MS_Lib.NumberOfLogBlock * sizeof(u16), GFP_KERNEL); + info->MS_Lib.Phy2LogMap = kmalloc_array(info->MS_Lib.NumberOfPhyBlock, + sizeof(u16), + GFP_KERNEL); + info->MS_Lib.Log2PhyMap = kmalloc_array(info->MS_Lib.NumberOfLogBlock, + sizeof(u16), + GFP_KERNEL); if ((info->MS_Lib.Phy2LogMap == NULL) || (info->MS_Lib.Log2PhyMap == NULL)) { ms_lib_free_logicalmap(us); @@ -1128,8 +1132,12 @@ static int ms_lib_alloc_writebuf(struct us_data *us) info->MS_Lib.wrtblk = (u16)-1; - info->MS_Lib.blkpag = kmalloc(info->MS_Lib.PagesPerBlock * info->MS_Lib.BytesPerSector, GFP_KERNEL); - info->MS_Lib.blkext = kmalloc(info->MS_Lib.PagesPerBlock * sizeof(struct ms_lib_type_extdat), GFP_KERNEL); + info->MS_Lib.blkpag = kmalloc_array(info->MS_Lib.PagesPerBlock, + info->MS_Lib.BytesPerSector, + GFP_KERNEL); + info->MS_Lib.blkext = kmalloc_array(info->MS_Lib.PagesPerBlock, + sizeof(struct ms_lib_type_extdat), + GFP_KERNEL); if ((info->MS_Lib.blkpag == NULL) || (info->MS_Lib.blkext == NULL)) { ms_lib_free_writebuf(us); diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c index 44f8ffccd031..271014f03254 100644 --- a/drivers/usb/storage/sddr09.c +++ b/drivers/usb/storage/sddr09.c @@ -1244,8 +1244,8 @@ sddr09_read_map(struct us_data *us) { kfree(info->lba_to_pba); kfree(info->pba_to_lba); - info->lba_to_pba = kmalloc(numblocks*sizeof(int), GFP_NOIO); - info->pba_to_lba = kmalloc(numblocks*sizeof(int), GFP_NOIO); + info->lba_to_pba = kmalloc_array(numblocks, sizeof(int), GFP_NOIO); + info->pba_to_lba = kmalloc_array(numblocks, sizeof(int), GFP_NOIO); if (info->lba_to_pba == NULL || info->pba_to_lba == NULL) { printk(KERN_WARNING "sddr09_read_map: out of memory\n"); diff --git a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c index 147c50b3e00f..73186d66b618 100644 --- a/drivers/usb/storage/sddr55.c +++ b/drivers/usb/storage/sddr55.c @@ -663,7 +663,7 @@ static int sddr55_read_map(struct us_data *us) { numblocks = info->capacity >> (info->blockshift + info->pageshift); - buffer = kmalloc( numblocks * 2, GFP_NOIO ); + buffer = kmalloc_array(numblocks, 2, GFP_NOIO ); if (!buffer) return -1; @@ -696,8 +696,8 @@ static int sddr55_read_map(struct us_data *us) { kfree(info->lba_to_pba); kfree(info->pba_to_lba); - info->lba_to_pba = kmalloc(numblocks*sizeof(int), GFP_NOIO); - info->pba_to_lba = kmalloc(numblocks*sizeof(int), GFP_NOIO); + info->lba_to_pba = kmalloc_array(numblocks, sizeof(int), GFP_NOIO); + info->pba_to_lba = kmalloc_array(numblocks, sizeof(int), GFP_NOIO); if (info->lba_to_pba == NULL || info->pba_to_lba == NULL) { kfree(info->lba_to_pba); diff --git a/drivers/uwb/est.c b/drivers/uwb/est.c index f3e232584284..ad30ddfe30b3 100644 --- a/drivers/uwb/est.c +++ b/drivers/uwb/est.c @@ -217,7 +217,7 @@ static int uwb_est_grow(void) { size_t actual_size = uwb_est_size * sizeof(uwb_est[0]); - void *new = kmalloc(2 * actual_size, GFP_ATOMIC); + void *new = kmalloc_array(2, actual_size, GFP_ATOMIC); if (new == NULL) return -ENOMEM; memcpy(new, uwb_est, actual_size); diff --git a/drivers/uwb/i1480/dfu/usb.c b/drivers/uwb/i1480/dfu/usb.c index a50cf45e530f..c0430a41e24b 100644 --- a/drivers/uwb/i1480/dfu/usb.c +++ b/drivers/uwb/i1480/dfu/usb.c @@ -376,7 +376,7 @@ int i1480_usb_probe(struct usb_interface *iface, const struct usb_device_id *id) i1480 = &i1480_usb->i1480; i1480->buf_size = 512; - i1480->cmd_buf = kmalloc(2 * i1480->buf_size, GFP_KERNEL); + i1480->cmd_buf = kmalloc_array(2, i1480->buf_size, GFP_KERNEL); if (i1480->cmd_buf == NULL) { dev_err(dev, "Cannot allocate transfer buffers\n"); result = -ENOMEM; diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index 8fe07622ae59..3e5245ad6c91 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -259,8 +259,9 @@ static int vhost_net_set_ubuf_info(struct vhost_net *n) zcopy = vhost_net_zcopy_mask & (0x1 << i); if (!zcopy) continue; - n->vqs[i].ubuf_info = kmalloc(sizeof(*n->vqs[i].ubuf_info) * - UIO_MAXIOV, GFP_KERNEL); + n->vqs[i].ubuf_info = kmalloc_array(UIO_MAXIOV, + sizeof(*n->vqs[i].ubuf_info), + GFP_KERNEL); if (!n->vqs[i].ubuf_info) goto err; } @@ -911,7 +912,7 @@ static int vhost_net_open(struct inode *inode, struct file *f) n = kvmalloc(sizeof *n, GFP_KERNEL | __GFP_RETRY_MAYFAIL); if (!n) return -ENOMEM; - vqs = kmalloc(VHOST_NET_VQ_MAX * sizeof(*vqs), GFP_KERNEL); + vqs = kmalloc_array(VHOST_NET_VQ_MAX, sizeof(*vqs), GFP_KERNEL); if (!vqs) { kvfree(n); return -ENOMEM; diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c index cb4ab5b955ad..d3e90a2f7ebc 100644 --- a/drivers/vhost/scsi.c +++ b/drivers/vhost/scsi.c @@ -1415,7 +1415,7 @@ static int vhost_scsi_open(struct inode *inode, struct file *f) goto err_vs; } - vqs = kmalloc(VHOST_SCSI_MAX_VQ * sizeof(*vqs), GFP_KERNEL); + vqs = kmalloc_array(VHOST_SCSI_MAX_VQ, sizeof(*vqs), GFP_KERNEL); if (!vqs) goto err_vqs; diff --git a/drivers/vhost/test.c b/drivers/vhost/test.c index 682fc58e1f75..bf24ecc46ed6 100644 --- a/drivers/vhost/test.c +++ b/drivers/vhost/test.c @@ -111,7 +111,7 @@ static int vhost_test_open(struct inode *inode, struct file *f) if (!n) return -ENOMEM; - vqs = kmalloc(VHOST_TEST_VQ_MAX * sizeof(*vqs), GFP_KERNEL); + vqs = kmalloc_array(VHOST_TEST_VQ_MAX, sizeof(*vqs), GFP_KERNEL); if (!vqs) { kfree(n); return -ENOMEM; diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 85edacc0be47..8ef554c28aee 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -392,10 +392,13 @@ static long vhost_dev_alloc_iovecs(struct vhost_dev *dev) for (i = 0; i < dev->nvqs; ++i) { vq = dev->vqs[i]; - vq->indirect = kmalloc(sizeof *vq->indirect * UIO_MAXIOV, - GFP_KERNEL); - vq->log = kmalloc(sizeof *vq->log * UIO_MAXIOV, GFP_KERNEL); - vq->heads = kmalloc(sizeof *vq->heads * UIO_MAXIOV, GFP_KERNEL); + vq->indirect = kmalloc_array(UIO_MAXIOV, + sizeof(*vq->indirect), + GFP_KERNEL); + vq->log = kmalloc_array(UIO_MAXIOV, sizeof(*vq->log), + GFP_KERNEL); + vq->heads = kmalloc_array(UIO_MAXIOV, sizeof(*vq->heads), + GFP_KERNEL); if (!vq->indirect || !vq->log || !vq->heads) goto err_nomem; } diff --git a/drivers/vhost/vringh.c b/drivers/vhost/vringh.c index bb8971f2a634..a94d700a4503 100644 --- a/drivers/vhost/vringh.c +++ b/drivers/vhost/vringh.c @@ -191,7 +191,7 @@ static int resize_iovec(struct vringh_kiov *iov, gfp_t gfp) if (flag) new = krealloc(iov->iov, new_num * sizeof(struct iovec), gfp); else { - new = kmalloc(new_num * sizeof(struct iovec), gfp); + new = kmalloc_array(new_num, sizeof(struct iovec), gfp); if (new) { memcpy(new, iov->iov, iov->max_num * sizeof(struct iovec)); diff --git a/drivers/video/fbdev/core/bitblit.c b/drivers/video/fbdev/core/bitblit.c index 5dce2b10c09a..35ebeeccde4d 100644 --- a/drivers/video/fbdev/core/bitblit.c +++ b/drivers/video/fbdev/core/bitblit.c @@ -269,7 +269,7 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode, if (attribute) { u8 *dst; - dst = kmalloc(w * vc->vc_font.height, GFP_ATOMIC); + dst = kmalloc_array(w, vc->vc_font.height, GFP_ATOMIC); if (!dst) return; kfree(ops->cursor_data); @@ -312,7 +312,7 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode, vc->vc_cursor_type != ops->p->cursor_shape || ops->cursor_state.mask == NULL || ops->cursor_reset) { - char *mask = kmalloc(w*vc->vc_font.height, GFP_ATOMIC); + char *mask = kmalloc_array(w, vc->vc_font.height, GFP_ATOMIC); int cur_height, size, i = 0; u8 msk = 0xff; diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c index 2f946cdd9945..3d0f7747d9d6 100644 --- a/drivers/video/fbdev/core/fbcon.c +++ b/drivers/video/fbdev/core/fbcon.c @@ -592,7 +592,8 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info, if (scr_readw(r) != vc->vc_video_erase_char) break; if (r != q && new_rows >= rows + logo_lines) { - save = kmalloc(logo_lines * new_cols * 2, GFP_KERNEL); + save = kmalloc(array3_size(logo_lines, new_cols, 2), + GFP_KERNEL); if (save) { int i = cols < new_cols ? cols : new_cols; scr_memsetw(save, erase, logo_lines * new_cols * 2); diff --git a/drivers/video/fbdev/core/fbcon_ccw.c b/drivers/video/fbdev/core/fbcon_ccw.c index e0b9fbe7ca9e..78f3a5621478 100644 --- a/drivers/video/fbdev/core/fbcon_ccw.c +++ b/drivers/video/fbdev/core/fbcon_ccw.c @@ -258,7 +258,7 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode, if (attribute) { u8 *dst; - dst = kmalloc(w * vc->vc_font.width, GFP_ATOMIC); + dst = kmalloc_array(w, vc->vc_font.width, GFP_ATOMIC); if (!dst) return; kfree(ops->cursor_data); @@ -304,14 +304,15 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode, vc->vc_cursor_type != ops->p->cursor_shape || ops->cursor_state.mask == NULL || ops->cursor_reset) { - char *tmp, *mask = kmalloc(w*vc->vc_font.width, GFP_ATOMIC); + char *tmp, *mask = kmalloc_array(w, vc->vc_font.width, + GFP_ATOMIC); int cur_height, size, i = 0; int width = (vc->vc_font.width + 7)/8; if (!mask) return; - tmp = kmalloc(width * vc->vc_font.height, GFP_ATOMIC); + tmp = kmalloc_array(width, vc->vc_font.height, GFP_ATOMIC); if (!tmp) { kfree(mask); diff --git a/drivers/video/fbdev/core/fbcon_cw.c b/drivers/video/fbdev/core/fbcon_cw.c index 158e6ea1c0f6..fd098ff17574 100644 --- a/drivers/video/fbdev/core/fbcon_cw.c +++ b/drivers/video/fbdev/core/fbcon_cw.c @@ -241,7 +241,7 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode, if (attribute) { u8 *dst; - dst = kmalloc(w * vc->vc_font.width, GFP_ATOMIC); + dst = kmalloc_array(w, vc->vc_font.width, GFP_ATOMIC); if (!dst) return; kfree(ops->cursor_data); @@ -287,14 +287,15 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode, vc->vc_cursor_type != ops->p->cursor_shape || ops->cursor_state.mask == NULL || ops->cursor_reset) { - char *tmp, *mask = kmalloc(w*vc->vc_font.width, GFP_ATOMIC); + char *tmp, *mask = kmalloc_array(w, vc->vc_font.width, + GFP_ATOMIC); int cur_height, size, i = 0; int width = (vc->vc_font.width + 7)/8; if (!mask) return; - tmp = kmalloc(width * vc->vc_font.height, GFP_ATOMIC); + tmp = kmalloc_array(width, vc->vc_font.height, GFP_ATOMIC); if (!tmp) { kfree(mask); diff --git a/drivers/video/fbdev/core/fbcon_rotate.c b/drivers/video/fbdev/core/fbcon_rotate.c index 8a51e4d95cc5..c0d445294aa7 100644 --- a/drivers/video/fbdev/core/fbcon_rotate.c +++ b/drivers/video/fbdev/core/fbcon_rotate.c @@ -46,7 +46,7 @@ static int fbcon_rotate_font(struct fb_info *info, struct vc_data *vc) info->fbops->fb_sync(info); if (ops->fd_size < d_cellsize * len) { - dst = kmalloc(d_cellsize * len, GFP_KERNEL); + dst = kmalloc_array(len, d_cellsize, GFP_KERNEL); if (dst == NULL) { err = -ENOMEM; diff --git a/drivers/video/fbdev/core/fbcon_ud.c b/drivers/video/fbdev/core/fbcon_ud.c index 3df269638166..e165a3fad29a 100644 --- a/drivers/video/fbdev/core/fbcon_ud.c +++ b/drivers/video/fbdev/core/fbcon_ud.c @@ -289,7 +289,7 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode, if (attribute) { u8 *dst; - dst = kmalloc(w * vc->vc_font.height, GFP_ATOMIC); + dst = kmalloc_array(w, vc->vc_font.height, GFP_ATOMIC); if (!dst) return; kfree(ops->cursor_data); @@ -335,7 +335,7 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode, vc->vc_cursor_type != ops->p->cursor_shape || ops->cursor_state.mask == NULL || ops->cursor_reset) { - char *mask = kmalloc(w*vc->vc_font.height, GFP_ATOMIC); + char *mask = kmalloc_array(w, vc->vc_font.height, GFP_ATOMIC); int cur_height, size, i = 0; u8 msk = 0xff; diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index 4e2c6c8e549a..3ac97c8d7166 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -496,7 +496,8 @@ static int fb_show_logo_line(struct fb_info *info, int rotate, } if (fb_logo.depth <= 4) { - logo_new = kmalloc(logo->width * logo->height, GFP_KERNEL); + logo_new = kmalloc_array(logo->width, logo->height, + GFP_KERNEL); if (logo_new == NULL) { kfree(palette); if (saved_pseudo_palette) @@ -513,8 +514,8 @@ static int fb_show_logo_line(struct fb_info *info, int rotate, image.height = logo->height; if (rotate) { - logo_rotate = kmalloc(logo->width * - logo->height, GFP_KERNEL); + logo_rotate = kmalloc_array(logo->width, logo->height, + GFP_KERNEL); if (logo_rotate) fb_rotate_logo(info, logo_rotate, &image, rotate); } diff --git a/drivers/video/fbdev/core/fbmon.c b/drivers/video/fbdev/core/fbmon.c index ed202f1e13b8..b73839c19660 100644 --- a/drivers/video/fbdev/core/fbmon.c +++ b/drivers/video/fbdev/core/fbmon.c @@ -671,7 +671,7 @@ static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize, } *dbsize = num; - m = kmalloc(num * sizeof(struct fb_videomode), GFP_KERNEL); + m = kmalloc_array(num, sizeof(struct fb_videomode), GFP_KERNEL); if (!m) return mode; memmove(m, mode, num * sizeof(struct fb_videomode)); diff --git a/drivers/video/fbdev/imxfb.c b/drivers/video/fbdev/imxfb.c index ba82f97fb42b..c4eb8661f751 100644 --- a/drivers/video/fbdev/imxfb.c +++ b/drivers/video/fbdev/imxfb.c @@ -662,7 +662,7 @@ static int imxfb_init_fbinfo(struct platform_device *pdev) pr_debug("%s\n",__func__); - info->pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL); + info->pseudo_palette = kmalloc_array(16, sizeof(u32), GFP_KERNEL); if (!info->pseudo_palette) return -ENOMEM; diff --git a/drivers/video/fbdev/mb862xx/mb862xxfb_accel.c b/drivers/video/fbdev/mb862xx/mb862xxfb_accel.c index fe92eed6da70..8dd296d257dd 100644 --- a/drivers/video/fbdev/mb862xx/mb862xxfb_accel.c +++ b/drivers/video/fbdev/mb862xx/mb862xxfb_accel.c @@ -245,7 +245,7 @@ static void mb86290fb_imageblit(struct fb_info *info, return; } - cmd = kmalloc(cmdlen * 4, GFP_DMA); + cmd = kmalloc_array(cmdlen, 4, GFP_DMA); if (!cmd) return cfb_imageblit(info, image); cmdfn(cmd, step, dx, dy, width, height, fgcolor, bgcolor, image, info); diff --git a/drivers/video/fbdev/nvidia/nvidia.c b/drivers/video/fbdev/nvidia/nvidia.c index 418a2d0d06a9..2e50120bcfae 100644 --- a/drivers/video/fbdev/nvidia/nvidia.c +++ b/drivers/video/fbdev/nvidia/nvidia.c @@ -566,7 +566,7 @@ static int nvidiafb_cursor(struct fb_info *info, struct fb_cursor *cursor) u8 *msk = (u8 *) cursor->mask; u8 *src; - src = kmalloc(s_pitch * cursor->image.height, GFP_ATOMIC); + src = kmalloc_array(s_pitch, cursor->image.height, GFP_ATOMIC); if (src) { switch (cursor->rop) { diff --git a/drivers/video/fbdev/pvr2fb.c b/drivers/video/fbdev/pvr2fb.c index 867c5218968f..22e3850d970c 100644 --- a/drivers/video/fbdev/pvr2fb.c +++ b/drivers/video/fbdev/pvr2fb.c @@ -682,7 +682,7 @@ static ssize_t pvr2fb_write(struct fb_info *info, const char *buf, nr_pages = (count + PAGE_SIZE - 1) >> PAGE_SHIFT; - pages = kmalloc(nr_pages * sizeof(struct page *), GFP_KERNEL); + pages = kmalloc_array(nr_pages, sizeof(struct page *), GFP_KERNEL); if (!pages) return -ENOMEM; diff --git a/drivers/video/fbdev/riva/fbdev.c b/drivers/video/fbdev/riva/fbdev.c index 1ea78bb911fb..3ab9ff169cff 100644 --- a/drivers/video/fbdev/riva/fbdev.c +++ b/drivers/video/fbdev/riva/fbdev.c @@ -1615,7 +1615,7 @@ static int rivafb_cursor(struct fb_info *info, struct fb_cursor *cursor) u8 *msk = (u8 *) cursor->mask; u8 *src; - src = kmalloc(s_pitch * cursor->image.height, GFP_ATOMIC); + src = kmalloc_array(s_pitch, cursor->image.height, GFP_ATOMIC); if (src) { switch (cursor->rop) { diff --git a/drivers/video/fbdev/via/viafbdev.c b/drivers/video/fbdev/via/viafbdev.c index 71b5dca95bdb..a5857f917cb3 100644 --- a/drivers/video/fbdev/via/viafbdev.c +++ b/drivers/video/fbdev/via/viafbdev.c @@ -597,7 +597,8 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg) break; case VIAFB_GET_GAMMA_LUT: - viafb_gamma_table = kmalloc(256 * sizeof(u32), GFP_KERNEL); + viafb_gamma_table = kmalloc_array(256, sizeof(u32), + GFP_KERNEL); if (!viafb_gamma_table) return -ENOMEM; viafb_get_gamma_table(viafb_gamma_table); diff --git a/drivers/video/fbdev/w100fb.c b/drivers/video/fbdev/w100fb.c index ffda1d68fb05..9e8496331ad3 100644 --- a/drivers/video/fbdev/w100fb.c +++ b/drivers/video/fbdev/w100fb.c @@ -695,7 +695,8 @@ int w100fb_probe(struct platform_device *pdev) goto out; } - info->pseudo_palette = kmalloc(sizeof (u32) * MAX_PALETTES, GFP_KERNEL); + info->pseudo_palette = kmalloc_array(MAX_PALETTES, sizeof(u32), + GFP_KERNEL); if (!info->pseudo_palette) { err = -ENOMEM; goto out; diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c index 80a3704939cd..916c4ad22eee 100644 --- a/drivers/virtio/virtio_pci_common.c +++ b/drivers/virtio/virtio_pci_common.c @@ -113,8 +113,9 @@ static int vp_request_msix_vectors(struct virtio_device *vdev, int nvectors, vp_dev->msix_vectors = nvectors; - vp_dev->msix_names = kmalloc(nvectors * sizeof *vp_dev->msix_names, - GFP_KERNEL); + vp_dev->msix_names = kmalloc_array(nvectors, + sizeof(*vp_dev->msix_names), + GFP_KERNEL); if (!vp_dev->msix_names) goto error; vp_dev->msix_affinity_masks diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index b82bb0b08161..03f85b80df88 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c @@ -248,7 +248,7 @@ static struct vring_desc *alloc_indirect(struct virtqueue *_vq, */ gfp &= ~__GFP_HIGHMEM; - desc = kmalloc(total_sg * sizeof(struct vring_desc), gfp); + desc = kmalloc_array(total_sg, sizeof(struct vring_desc), gfp); if (!desc) return NULL; diff --git a/drivers/vservices/devio.c b/drivers/vservices/devio.c index 8155c8c88dae..fa716d59e042 100644 --- a/drivers/vservices/devio.c +++ b/drivers/vservices/devio.c @@ -415,7 +415,7 @@ vs_devio_check_iov(struct vs_ioctl_iovec *io, bool is_send, ssize_t *total) if (io->iovcnt > UIO_MAXIOV) return ERR_PTR(-EINVAL); - iov = kmalloc(sizeof(*iov) * io->iovcnt, GFP_KERNEL); + iov = kmalloc_array(io->iovcnt, sizeof(*iov), GFP_KERNEL); if (!iov) return ERR_PTR(-ENOMEM); diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index 1fb374466e84..9047187dd9b7 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c @@ -990,7 +990,7 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx) /* No need for kzalloc as it is initialized in following hypercall * GNTTABOP_setup_table. */ - frames = kmalloc(nr_gframes * sizeof(unsigned long), GFP_ATOMIC); + frames = kmalloc_array(nr_gframes, sizeof(unsigned long), GFP_ATOMIC); if (!frames) return -ENOMEM; @@ -1108,8 +1108,9 @@ int gnttab_init(void) max_nr_glist_frames = (max_nr_grant_frames * grefs_per_grant_frame / RPP); - gnttab_list = kmalloc(max_nr_glist_frames * sizeof(grant_ref_t *), - GFP_KERNEL); + gnttab_list = kmalloc_array(max_nr_glist_frames, + sizeof(grant_ref_t *), + GFP_KERNEL); if (gnttab_list == NULL) return -ENOMEM; diff --git a/drivers/xen/xen-pciback/pciback_ops.c b/drivers/xen/xen-pciback/pciback_ops.c index 7af047008ea2..787966f44589 100644 --- a/drivers/xen/xen-pciback/pciback_ops.c +++ b/drivers/xen/xen-pciback/pciback_ops.c @@ -232,7 +232,7 @@ int xen_pcibk_enable_msix(struct xen_pcibk_device *pdev, if (dev->msi_enabled || !(cmd & PCI_COMMAND_MEMORY)) return -ENXIO; - entries = kmalloc(op->value * sizeof(*entries), GFP_KERNEL); + entries = kmalloc_array(op->value, sizeof(*entries), GFP_KERNEL); if (entries == NULL) return -ENOMEM; diff --git a/fs/9p/fid.c b/fs/9p/fid.c index ed4f8519b627..a9ef46f02354 100644 --- a/fs/9p/fid.c +++ b/fs/9p/fid.c @@ -100,7 +100,7 @@ static int build_path_from_dentry(struct v9fs_session_info *v9ses, for (ds = dentry; !IS_ROOT(ds); ds = ds->d_parent) n++; - wnames = kmalloc(sizeof(char *) * n, GFP_KERNEL); + wnames = kmalloc_array(n, sizeof(char *), GFP_KERNEL); if (!wnames) goto err_out; diff --git a/fs/adfs/super.c b/fs/adfs/super.c index e42c30001509..6d04905e9774 100644 --- a/fs/adfs/super.c +++ b/fs/adfs/super.c @@ -313,7 +313,7 @@ static struct adfs_discmap *adfs_read_map(struct super_block *sb, struct adfs_di asb->s_ids_per_zone = zone_size / (asb->s_idlen + 1); - dm = kmalloc(nzones * sizeof(*dm), GFP_KERNEL); + dm = kmalloc_array(nzones, sizeof(*dm), GFP_KERNEL); if (dm == NULL) { adfs_error(sb, "not enough memory"); return ERR_PTR(-ENOMEM); diff --git a/fs/afs/cmservice.c b/fs/afs/cmservice.c index c7475867a52b..63100f8b00f9 100644 --- a/fs/afs/cmservice.c +++ b/fs/afs/cmservice.c @@ -212,7 +212,8 @@ static int afs_deliver_cb_callback(struct afs_call *call) if (call->count > AFSCBMAX) return -EBADMSG; - call->buffer = kmalloc(call->count * 3 * 4, GFP_KERNEL); + call->buffer = kmalloc(array3_size(call->count, 3, 4), + GFP_KERNEL); if (!call->buffer) return -ENOMEM; call->offset = 0; @@ -367,7 +368,7 @@ static int afs_deliver_cb_init_call_back_state3(struct afs_call *call) switch (call->unmarshall) { case 0: call->offset = 0; - call->buffer = kmalloc(11 * sizeof(__be32), GFP_KERNEL); + call->buffer = kmalloc_array(11, sizeof(__be32), GFP_KERNEL); if (!call->buffer) return -ENOMEM; call->unmarshall++; @@ -489,7 +490,7 @@ static int afs_deliver_cb_probe_uuid(struct afs_call *call) switch (call->unmarshall) { case 0: call->offset = 0; - call->buffer = kmalloc(11 * sizeof(__be32), GFP_KERNEL); + call->buffer = kmalloc_array(11, sizeof(__be32), GFP_KERNEL); if (!call->buffer) return -ENOMEM; call->unmarshall++; diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index fe31f911a648..19c42bd69aa6 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -1999,7 +1999,7 @@ static int elf_note_info_init(struct elf_note_info *info) INIT_LIST_HEAD(&info->thread_list); /* Allocate space for ELF notes */ - info->notes = kmalloc(8 * sizeof(struct memelfnote), GFP_KERNEL); + info->notes = kmalloc_array(8, sizeof(struct memelfnote), GFP_KERNEL); if (!info->notes) return 0; info->psinfo = kmalloc(sizeof(*info->psinfo), GFP_KERNEL); diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index e70c039ac190..9fa4bfafcc51 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c @@ -1588,7 +1588,8 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm) psinfo = kmalloc(sizeof(*psinfo), GFP_KERNEL); if (!psinfo) goto cleanup; - notes = kmalloc(NUM_NOTES * sizeof(struct memelfnote), GFP_KERNEL); + notes = kmalloc_array(NUM_NOTES, sizeof(struct memelfnote), + GFP_KERNEL); if (!notes) goto cleanup; fpu = kmalloc(sizeof(*fpu), GFP_KERNEL); diff --git a/fs/block_dev.c b/fs/block_dev.c index 9584df0e29b1..b8605000216e 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -231,7 +231,8 @@ __blkdev_direct_IO_simple(struct kiocb *iocb, struct iov_iter *iter, if (nr_pages <= DIO_INLINE_BIO_VECS) vecs = inline_vecs; else { - vecs = kmalloc(nr_pages * sizeof(struct bio_vec), GFP_KERNEL); + vecs = kmalloc_array(nr_pages, sizeof(struct bio_vec), + GFP_KERNEL); if (!vecs) return -ENOMEM; } diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 26c682db94ee..7052639a7ebd 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -368,7 +368,7 @@ static int start_read(struct inode *inode, struct list_head *page_list, int max) /* build page vector */ nr_pages = calc_pages_for(0, len); - pages = kmalloc(sizeof(*pages) * nr_pages, GFP_KERNEL); + pages = kmalloc_array(nr_pages, sizeof(*pages), GFP_KERNEL); if (!pages) { ret = -ENOMEM; goto out_put; @@ -958,8 +958,9 @@ get_more_pages: BUG_ON(pages); max_pages = calc_pages_for(0, (u64)len); - pages = kmalloc(max_pages * sizeof (*pages), - GFP_NOFS); + pages = kmalloc_array(max_pages, + sizeof(*pages), + GFP_NOFS); if (!pages) { pool = fsc->wb_pagevec_pool; pages = mempool_alloc(pool, GFP_NOFS); @@ -1105,8 +1106,8 @@ new_request: /* allocate new pages array for next request */ data_pages = pages; - pages = kmalloc(locked_pages * sizeof (*pages), - GFP_NOFS); + pages = kmalloc_array(locked_pages, sizeof(*pages), + GFP_NOFS); if (!pages) { pool = fsc->wb_pagevec_pool; pages = mempool_alloc(pool, GFP_NOFS); diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index f36ddfea4997..5178874baf55 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -2981,8 +2981,9 @@ static int encode_caps_cb(struct inode *inode, struct ceph_cap *cap, encode_again: ceph_count_locks(inode, &num_fcntl_locks, &num_flock_locks); - flocks = kmalloc((num_fcntl_locks+num_flock_locks) * - sizeof(struct ceph_filelock), GFP_NOFS); + flocks = kmalloc_array(num_fcntl_locks + num_flock_locks, + sizeof(struct ceph_filelock), + GFP_NOFS); if (!flocks) { err = -ENOMEM; goto out_free; diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c index a3b56544c21b..3d19595eb352 100644 --- a/fs/cifs/asn1.c +++ b/fs/cifs/asn1.c @@ -428,7 +428,7 @@ asn1_oid_decode(struct asn1_ctx *ctx, if (size < 2 || size > UINT_MAX/sizeof(unsigned long)) return 0; - *oid = kmalloc(size * sizeof(unsigned long), GFP_ATOMIC); + *oid = kmalloc_array(size, sizeof(unsigned long), GFP_ATOMIC); if (*oid == NULL) return 0; diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index 73d428af97a9..207be1fae2f8 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c @@ -747,8 +747,8 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, if (num_aces > ULONG_MAX / sizeof(struct cifs_ace *)) return; - ppace = kmalloc(num_aces * sizeof(struct cifs_ace *), - GFP_KERNEL); + ppace = kmalloc_array(num_aces, sizeof(struct cifs_ace *), + GFP_KERNEL); if (!ppace) return; diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index b76e73395299..15a586e78e33 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -1821,7 +1821,7 @@ cifs_rename2(struct inode *source_dir, struct dentry *source_dentry, * with unix extensions enabled. */ info_buf_source = - kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO), + kmalloc_array(2, sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL); if (info_buf_source == NULL) { rc = -ENOMEM; diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 1c87a429ce72..58dc8496a145 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -3150,7 +3150,7 @@ send_set_info(const unsigned int xid, struct cifs_tcon *tcon, if (!num) return -EINVAL; - iov = kmalloc(sizeof(struct kvec) * num, GFP_KERNEL); + iov = kmalloc_array(num, sizeof(struct kvec), GFP_KERNEL); if (!iov) return -ENOMEM; @@ -3213,7 +3213,7 @@ SMB2_rename(const unsigned int xid, struct cifs_tcon *tcon, int rc; int len = (2 * UniStrnlen((wchar_t *)target_file, PATH_MAX)); - data = kmalloc(sizeof(void *) * 2, GFP_KERNEL); + data = kmalloc_array(2, sizeof(void *), GFP_KERNEL); if (!data) return -ENOMEM; @@ -3261,7 +3261,7 @@ SMB2_set_hardlink(const unsigned int xid, struct cifs_tcon *tcon, int rc; int len = (2 * UniStrnlen((wchar_t *)target_file, PATH_MAX)); - data = kmalloc(sizeof(void *) * 2, GFP_KERNEL); + data = kmalloc_array(2, sizeof(void *), GFP_KERNEL); if (!data) return -ENOMEM; diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index ffc8757e5a3c..f1d2ac7ce1fa 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c @@ -822,7 +822,7 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses, struct kvec *new_iov; int rc; - new_iov = kmalloc(sizeof(struct kvec) * (n_vec + 1), GFP_KERNEL); + new_iov = kmalloc_array(n_vec + 1, sizeof(struct kvec), GFP_KERNEL); if (!new_iov) return -ENOMEM; diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c index f17715d140b5..aef3f4206540 100644 --- a/fs/exofs/inode.c +++ b/fs/exofs/inode.c @@ -110,8 +110,8 @@ static int pcol_try_alloc(struct page_collect *pcol) pages = exofs_max_io_pages(&pcol->sbi->layout, pcol->expected_pages); for (; pages; pages >>= 1) { - pcol->pages = kmalloc(pages * sizeof(struct page *), - GFP_KERNEL); + pcol->pages = kmalloc_array(pages, sizeof(struct page *), + GFP_KERNEL); if (likely(pcol->pages)) { pcol->alloc_pages = pages; return 0; diff --git a/fs/ext2/super.c b/fs/ext2/super.c index e3679cc9c0b9..f8fddba7e04b 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c @@ -1083,7 +1083,9 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) / EXT2_BLOCKS_PER_GROUP(sb)) + 1; db_count = (sbi->s_groups_count + EXT2_DESC_PER_BLOCK(sb) - 1) / EXT2_DESC_PER_BLOCK(sb); - sbi->s_group_desc = kmalloc (db_count * sizeof (struct buffer_head *), GFP_KERNEL); + sbi->s_group_desc = kmalloc_array (db_count, + sizeof(struct buffer_head *), + GFP_KERNEL); if (sbi->s_group_desc == NULL) { ext2_msg(sb, KERN_ERR, "error: not enough memory"); goto failed_mount; diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index 19af346a6651..2b7534a5a4d2 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c @@ -234,12 +234,14 @@ static struct ext4_new_flex_group_data *alloc_flex_gd(unsigned long flexbg_size) goto out2; flex_gd->count = flexbg_size; - flex_gd->groups = kmalloc(sizeof(struct ext4_new_group_data) * - flexbg_size, GFP_NOFS); + flex_gd->groups = kmalloc_array(flexbg_size, + sizeof(struct ext4_new_group_data), + GFP_NOFS); if (flex_gd->groups == NULL) goto out2; - flex_gd->bg_flags = kmalloc(flexbg_size * sizeof(__u16), GFP_NOFS); + flex_gd->bg_flags = kmalloc_array(flexbg_size, sizeof(__u16), + GFP_NOFS); if (flex_gd->bg_flags == NULL) goto out1; @@ -981,7 +983,7 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode, int res, i; int err; - primary = kmalloc(reserved_gdb * sizeof(*primary), GFP_NOFS); + primary = kmalloc_array(reserved_gdb, sizeof(*primary), GFP_NOFS); if (!primary) return -ENOMEM; diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c index 2649759c478a..a49eef1363d6 100644 --- a/fs/fat/namei_vfat.c +++ b/fs/fat/namei_vfat.c @@ -664,7 +664,7 @@ static int vfat_add_entry(struct inode *dir, const struct qstr *qname, if (len == 0) return -ENOENT; - slots = kmalloc(sizeof(*slots) * MSDOS_SLOTS, GFP_NOFS); + slots = kmalloc_array(MSDOS_SLOTS, sizeof(*slots), GFP_NOFS); if (slots == NULL) return -ENOMEM; diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index bfd6353ef7fa..18a1b9b33f7d 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -66,9 +66,11 @@ static struct fuse_req *__fuse_request_alloc(unsigned npages, gfp_t flags) pages = req->inline_pages; page_descs = req->inline_page_descs; } else { - pages = kmalloc(sizeof(struct page *) * npages, flags); - page_descs = kmalloc(sizeof(struct fuse_page_desc) * - npages, flags); + pages = kmalloc_array(npages, sizeof(struct page *), + flags); + page_descs = kmalloc_array(npages, + sizeof(struct fuse_page_desc), + flags); } if (!pages || !page_descs) { @@ -1388,7 +1390,8 @@ static ssize_t fuse_dev_splice_read(struct file *in, loff_t *ppos, if (!fud) return -EPERM; - bufs = kmalloc(pipe->buffers * sizeof(struct pipe_buffer), GFP_KERNEL); + bufs = kmalloc_array(pipe->buffers, sizeof(struct pipe_buffer), + GFP_KERNEL); if (!bufs) return -ENOMEM; @@ -1983,7 +1986,8 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe, pipe_lock(pipe); - bufs = kmalloc(pipe->buffers * sizeof(struct pipe_buffer), GFP_KERNEL); + bufs = kmalloc_array(pipe->buffers, sizeof(struct pipe_buffer), + GFP_KERNEL); if (!bufs) { pipe_unlock(pipe); return -ENOMEM; diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index 06a0d1947c77..f1e7fb36cf8d 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c @@ -1056,7 +1056,7 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name) /* Change the pointers. Don't bother distinguishing stuffed from non-stuffed. This code is complicated enough already. */ - lp = kmalloc(half_len * sizeof(__be64), GFP_NOFS); + lp = kmalloc_array(half_len, sizeof(__be64), GFP_NOFS); if (!lp) { error = -ENOMEM; goto fail_brelse; @@ -1170,7 +1170,7 @@ static int dir_double_exhash(struct gfs2_inode *dip) if (IS_ERR(hc)) return PTR_ERR(hc); - hc2 = kmalloc(hsize_bytes * 2, GFP_NOFS | __GFP_NOWARN); + hc2 = kmalloc_array(hsize_bytes, 2, GFP_NOFS | __GFP_NOWARN); if (hc2 == NULL) hc2 = __vmalloc(hsize_bytes * 2, GFP_NOFS, PAGE_KERNEL); @@ -1597,7 +1597,7 @@ int gfs2_dir_read(struct inode *inode, struct dir_context *ctx, error = -ENOMEM; /* 96 is max number of dirents which can be stuffed into an inode */ - darr = kmalloc(96 * sizeof(struct gfs2_dirent *), GFP_NOFS); + darr = kmalloc_array(96, sizeof(struct gfs2_dirent *), GFP_NOFS); if (darr) { g.pdent = (const struct gfs2_dirent **)darr; g.offset = 0; diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index aea1ed0aebd0..25932a09aef5 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c @@ -1307,7 +1307,8 @@ int gfs2_glock_nq_m(unsigned int num_gh, struct gfs2_holder *ghs) default: if (num_gh <= 4) break; - pph = kmalloc(num_gh * sizeof(struct gfs2_holder *), GFP_NOFS); + pph = kmalloc_array(num_gh, sizeof(struct gfs2_holder *), + GFP_NOFS); if (!pph) return -ENOMEM; } diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index a833e2e07167..e0c5bae00d8f 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c @@ -883,7 +883,7 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda) gfs2_write_calc_reserv(ip, sizeof(struct gfs2_quota), &data_blocks, &ind_blocks); - ghs = kmalloc(num_qd * sizeof(struct gfs2_holder), GFP_NOFS); + ghs = kmalloc_array(num_qd, sizeof(struct gfs2_holder), GFP_NOFS); if (!ghs) return -ENOMEM; diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index 7cb0672294df..9c5325c1696d 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c @@ -2600,8 +2600,9 @@ void gfs2_rlist_alloc(struct gfs2_rgrp_list *rlist, unsigned int state) { unsigned int x; - rlist->rl_ghs = kmalloc(rlist->rl_rgrps * sizeof(struct gfs2_holder), - GFP_NOFS | __GFP_NOFAIL); + rlist->rl_ghs = kmalloc_array(rlist->rl_rgrps, + sizeof(struct gfs2_holder), + GFP_NOFS | __GFP_NOFAIL); for (x = 0; x < rlist->rl_rgrps; x++) gfs2_holder_init(rlist->rl_rgd[x]->rd_gl, state, 0, diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index c3f3f1ae4e1b..329b93f1e6a8 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c @@ -1086,7 +1086,7 @@ static int gfs2_statfs_slow(struct gfs2_sbd *sdp, struct gfs2_statfs_change_host int error = 0, err; memset(sc, 0, sizeof(struct gfs2_statfs_change_host)); - gha = kmalloc(slots * sizeof(struct gfs2_holder), GFP_KERNEL); + gha = kmalloc_array(slots, sizeof(struct gfs2_holder), GFP_KERNEL); if (!gha) return -ENOMEM; for (x = 0; x < slots; x++) diff --git a/fs/hpfs/dnode.c b/fs/hpfs/dnode.c index 3b834563b1f1..10cd5582844b 100644 --- a/fs/hpfs/dnode.c +++ b/fs/hpfs/dnode.c @@ -33,7 +33,7 @@ int hpfs_add_pos(struct inode *inode, loff_t *pos) if (hpfs_inode->i_rddir_off[i] == pos) return 0; if (!(i&0x0f)) { - if (!(ppos = kmalloc((i+0x11) * sizeof(loff_t*), GFP_NOFS))) { + if (!(ppos = kmalloc_array(i + 0x11, sizeof(loff_t *), GFP_NOFS))) { pr_err("out of memory for position list\n"); return -ENOMEM; } diff --git a/fs/hpfs/map.c b/fs/hpfs/map.c index e0e60b148400..f8834d932db2 100644 --- a/fs/hpfs/map.c +++ b/fs/hpfs/map.c @@ -115,7 +115,7 @@ __le32 *hpfs_load_bitmap_directory(struct super_block *s, secno bmp) int n = (hpfs_sb(s)->sb_fs_size + 0x200000 - 1) >> 21; int i; __le32 *b; - if (!(b = kmalloc(n * 512, GFP_KERNEL))) { + if (!(b = kmalloc_array(n, 512, GFP_KERNEL))) { pr_err("can't allocate memory for bitmap directory\n"); return NULL; } diff --git a/fs/jbd2/revoke.c b/fs/jbd2/revoke.c index f9aefcda5854..939b4f629b4b 100644 --- a/fs/jbd2/revoke.c +++ b/fs/jbd2/revoke.c @@ -230,7 +230,7 @@ static struct jbd2_revoke_table_s *jbd2_journal_init_revoke_table(int hash_size) table->hash_size = hash_size; table->hash_shift = shift; table->hash_table = - kmalloc(hash_size * sizeof(struct list_head), GFP_KERNEL); + kmalloc_array(hash_size, sizeof(struct list_head), GFP_KERNEL); if (!table->hash_table) { kmem_cache_free(jbd2_revoke_table_cache, table); table = NULL; diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index 2cfe487708e0..c6821a509481 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -1208,7 +1208,7 @@ int jffs2_nand_flash_setup(struct jffs2_sb_info *c) if (!c->wbuf) return -ENOMEM; - c->oobbuf = kmalloc(NR_OOB_SCAN_PAGES * c->oobavail, GFP_KERNEL); + c->oobbuf = kmalloc_array(NR_OOB_SCAN_PAGES, c->oobavail, GFP_KERNEL); if (!c->oobbuf) { kfree(c->wbuf); return -ENOMEM; diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c index 2d514c7affc2..49263e220dbc 100644 --- a/fs/jfs/jfs_dmap.c +++ b/fs/jfs/jfs_dmap.c @@ -1641,7 +1641,7 @@ s64 dbDiscardAG(struct inode *ip, int agno, s64 minlen) max_ranges = nblocks; do_div(max_ranges, minlen); range_cnt = min_t(u64, max_ranges + 1, 32 * 1024); - totrim = kmalloc(sizeof(struct range2trim) * range_cnt, GFP_NOFS); + totrim = kmalloc_array(range_cnt, sizeof(struct range2trim), GFP_NOFS); if (totrim == NULL) { jfs_error(bmp->db_ipbmap->i_sb, "no memory for trim array\n"); IWRITE_UNLOCK(ipbmap); diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c index de2bcb36e079..52bae3f5c914 100644 --- a/fs/jfs/jfs_dtree.c +++ b/fs/jfs/jfs_dtree.c @@ -594,7 +594,8 @@ int dtSearch(struct inode *ip, struct component_name * key, ino_t * data, struct component_name ciKey; struct super_block *sb = ip->i_sb; - ciKey.name = kmalloc((JFS_NAME_MAX + 1) * sizeof(wchar_t), GFP_NOFS); + ciKey.name = kmalloc_array(JFS_NAME_MAX + 1, sizeof(wchar_t), + GFP_NOFS); if (!ciKey.name) { rc = -ENOMEM; goto dtSearch_Exit2; @@ -957,7 +958,7 @@ static int dtSplitUp(tid_t tid, smp = split->mp; sp = DT_PAGE(ip, smp); - key.name = kmalloc((JFS_NAME_MAX + 2) * sizeof(wchar_t), GFP_NOFS); + key.name = kmalloc_array(JFS_NAME_MAX + 2, sizeof(wchar_t), GFP_NOFS); if (!key.name) { DT_PUTPAGE(smp); rc = -ENOMEM; @@ -3779,12 +3780,12 @@ static int ciGetLeafPrefixKey(dtpage_t * lp, int li, dtpage_t * rp, struct component_name lkey; struct component_name rkey; - lkey.name = kmalloc((JFS_NAME_MAX + 1) * sizeof(wchar_t), + lkey.name = kmalloc_array(JFS_NAME_MAX + 1, sizeof(wchar_t), GFP_KERNEL); if (lkey.name == NULL) return -ENOMEM; - rkey.name = kmalloc((JFS_NAME_MAX + 1) * sizeof(wchar_t), + rkey.name = kmalloc_array(JFS_NAME_MAX + 1, sizeof(wchar_t), GFP_KERNEL); if (rkey.name == NULL) { kfree(lkey.name); diff --git a/fs/jfs/jfs_unicode.c b/fs/jfs/jfs_unicode.c index c7de6f5bbefc..0148e2e4d97a 100644 --- a/fs/jfs/jfs_unicode.c +++ b/fs/jfs/jfs_unicode.c @@ -121,7 +121,7 @@ int get_UCSname(struct component_name * uniName, struct dentry *dentry) return -ENAMETOOLONG; uniName->name = - kmalloc((length + 1) * sizeof(wchar_t), GFP_NOFS); + kmalloc_array(length + 1, sizeof(wchar_t), GFP_NOFS); if (uniName->name == NULL) return -ENOMEM; diff --git a/fs/mbcache.c b/fs/mbcache.c index bf41e2e72c18..91dfe1abfccd 100644 --- a/fs/mbcache.c +++ b/fs/mbcache.c @@ -353,8 +353,9 @@ struct mb_cache *mb_cache_create(int bucket_bits) cache->c_max_entries = bucket_count << 4; INIT_LIST_HEAD(&cache->c_list); spin_lock_init(&cache->c_list_lock); - cache->c_hash = kmalloc(bucket_count * sizeof(struct hlist_bl_head), - GFP_KERNEL); + cache->c_hash = kmalloc_array(bucket_count, + sizeof(struct hlist_bl_head), + GFP_KERNEL); if (!cache->c_hash) { kfree(cache); goto err_out; diff --git a/fs/namei.c b/fs/namei.c index 6c933d1cc941..43a3b93e1781 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -572,12 +572,12 @@ static int __nd_alloc_stack(struct nameidata *nd) struct saved *p; if (nd->flags & LOOKUP_RCU) { - p= kmalloc(MAXSYMLINKS * sizeof(struct saved), + p= kmalloc_array(MAXSYMLINKS, sizeof(struct saved), GFP_ATOMIC); if (unlikely(!p)) return -ECHILD; } else { - p= kmalloc(MAXSYMLINKS * sizeof(struct saved), + p= kmalloc_array(MAXSYMLINKS, sizeof(struct saved), GFP_KERNEL); if (unlikely(!p)) return -ENOMEM; diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c index dc9586feab31..5188f9f70c78 100644 --- a/fs/nfsd/nfs4recover.c +++ b/fs/nfsd/nfs4recover.c @@ -510,8 +510,9 @@ nfs4_legacy_state_init(struct net *net) struct nfsd_net *nn = net_generic(net, nfsd_net_id); int i; - nn->reclaim_str_hashtbl = kmalloc(sizeof(struct list_head) * - CLIENT_HASH_SIZE, GFP_KERNEL); + nn->reclaim_str_hashtbl = kmalloc_array(CLIENT_HASH_SIZE, + sizeof(struct list_head), + GFP_KERNEL); if (!nn->reclaim_str_hashtbl) return -ENOMEM; diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index d5d1c70bb927..1d6b9feeb8a6 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -1797,8 +1797,9 @@ static struct nfs4_client *alloc_client(struct xdr_netobj name) clp->cl_name.data = kmemdup(name.data, name.len, GFP_KERNEL); if (clp->cl_name.data == NULL) goto err_no_name; - clp->cl_ownerstr_hashtbl = kmalloc(sizeof(struct list_head) * - OWNER_HASH_SIZE, GFP_KERNEL); + clp->cl_ownerstr_hashtbl = kmalloc_array(OWNER_HASH_SIZE, + sizeof(struct list_head), + GFP_KERNEL); if (!clp->cl_ownerstr_hashtbl) goto err_no_hashtbl; for (i = 0; i < OWNER_HASH_SIZE; i++) @@ -7098,16 +7099,19 @@ static int nfs4_state_create_net(struct net *net) struct nfsd_net *nn = net_generic(net, nfsd_net_id); int i; - nn->conf_id_hashtbl = kmalloc(sizeof(struct list_head) * - CLIENT_HASH_SIZE, GFP_KERNEL); + nn->conf_id_hashtbl = kmalloc_array(CLIENT_HASH_SIZE, + sizeof(struct list_head), + GFP_KERNEL); if (!nn->conf_id_hashtbl) goto err; - nn->unconf_id_hashtbl = kmalloc(sizeof(struct list_head) * - CLIENT_HASH_SIZE, GFP_KERNEL); + nn->unconf_id_hashtbl = kmalloc_array(CLIENT_HASH_SIZE, + sizeof(struct list_head), + GFP_KERNEL); if (!nn->unconf_id_hashtbl) goto err_unconf_id; - nn->sessionid_hashtbl = kmalloc(sizeof(struct list_head) * - SESSION_HASH_SIZE, GFP_KERNEL); + nn->sessionid_hashtbl = kmalloc_array(SESSION_HASH_SIZE, + sizeof(struct list_head), + GFP_KERNEL); if (!nn->sessionid_hashtbl) goto err_sessionid; diff --git a/fs/ntfs/compress.c b/fs/ntfs/compress.c index f8eb04387ca4..fbd0090d7d0c 100644 --- a/fs/ntfs/compress.c +++ b/fs/ntfs/compress.c @@ -527,7 +527,7 @@ int ntfs_read_compressed_block(struct page *page) BUG_ON(ni->type != AT_DATA); BUG_ON(ni->name_len); - pages = kmalloc(nr_pages * sizeof(struct page *), GFP_NOFS); + pages = kmalloc_array(nr_pages, sizeof(struct page *), GFP_NOFS); /* Allocate memory to store the buffer heads we need. */ bhs_size = cb_size / block_size * sizeof(struct buffer_head *); diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c index 8d779227370a..23758118c532 100644 --- a/fs/ocfs2/cluster/tcp.c +++ b/fs/ocfs2/cluster/tcp.c @@ -1078,7 +1078,7 @@ int o2net_send_message_vec(u32 msg_type, u32 key, struct kvec *caller_vec, o2net_set_nst_sock_container(&nst, sc); veclen = caller_veclen + 1; - vec = kmalloc(sizeof(struct kvec) * veclen, GFP_ATOMIC); + vec = kmalloc_array(veclen, sizeof(struct kvec), GFP_ATOMIC); if (vec == NULL) { mlog(0, "failed to %zu element kvec!\n", veclen); ret = -ENOMEM; diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c index 6099a8034b17..32968549712b 100644 --- a/fs/ocfs2/dlm/dlmdomain.c +++ b/fs/ocfs2/dlm/dlmdomain.c @@ -86,7 +86,7 @@ static void dlm_free_pagevec(void **vec, int pages) static void **dlm_alloc_pagevec(int pages) { - void **vec = kmalloc(pages * sizeof(void *), GFP_KERNEL); + void **vec = kmalloc_array(pages, sizeof(void *), GFP_KERNEL); int i; if (!vec) diff --git a/fs/ocfs2/filecheck.c b/fs/ocfs2/filecheck.c index 2cabbcf2f28e..7a56c13f2fc6 100644 --- a/fs/ocfs2/filecheck.c +++ b/fs/ocfs2/filecheck.c @@ -222,7 +222,7 @@ int ocfs2_filecheck_create_sysfs(struct super_block *sb) if (!ocfs2_kset) return -ENOMEM; - attrs = kmalloc(sizeof(struct attribute *) * 4, GFP_NOFS); + attrs = kmalloc_array(4, sizeof(struct attribute *), GFP_NOFS); if (!attrs) { ret = -ENOMEM; goto error; diff --git a/fs/proc/base.c b/fs/proc/base.c index a54bb37af414..9f2d19fbaa7e 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -376,7 +376,8 @@ static int proc_pid_stack(struct seq_file *m, struct pid_namespace *ns, if (!file_ns_capable(m->file, &init_user_ns, CAP_SYS_ADMIN)) return -EACCES; - entries = kmalloc(MAX_STACK_TRACE_DEPTH * sizeof(*entries), GFP_KERNEL); + entries = kmalloc_array(MAX_STACK_TRACE_DEPTH, sizeof(*entries), + GFP_KERNEL); if (!entries) return -ENOMEM; diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index b3c5f6383dc3..b73693c522f4 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -1572,7 +1572,7 @@ static ssize_t pagemap_read(struct file *file, char __user *buf, pm.show_pfn = file_ns_capable(file, &init_user_ns, CAP_SYS_ADMIN); pm.len = (PAGEMAP_WALK_SIZE >> PAGE_SHIFT); - pm.buffer = kmalloc(pm.len * PM_ENTRY_BYTES, GFP_KERNEL); + pm.buffer = kmalloc_array(pm.len, PM_ENTRY_BYTES, GFP_KERNEL); ret = -ENOMEM; if (!pm.buffer) goto out_mm; diff --git a/fs/read_write.c b/fs/read_write.c index 0da6e4f19d7f..635f0d7ced85 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -777,7 +777,7 @@ ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector, goto out; } if (nr_segs > fast_segs) { - iov = kmalloc(nr_segs*sizeof(struct iovec), GFP_KERNEL); + iov = kmalloc_array(nr_segs, sizeof(struct iovec), GFP_KERNEL); if (iov == NULL) { ret = -ENOMEM; goto out; @@ -848,7 +848,7 @@ ssize_t compat_rw_copy_check_uvector(int type, goto out; if (nr_segs > fast_segs) { ret = -ENOMEM; - iov = kmalloc(nr_segs*sizeof(struct iovec), GFP_KERNEL); + iov = kmalloc_array(nr_segs, sizeof(struct iovec), GFP_KERNEL); if (iov == NULL) goto out; } diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index 2be907231375..272ca73094c8 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c @@ -2192,10 +2192,12 @@ static int journal_read_transaction(struct super_block *sb, * now we know we've got a good transaction, and it was * inside the valid time ranges */ - log_blocks = kmalloc(get_desc_trans_len(desc) * - sizeof(struct buffer_head *), GFP_NOFS); - real_blocks = kmalloc(get_desc_trans_len(desc) * - sizeof(struct buffer_head *), GFP_NOFS); + log_blocks = kmalloc_array(get_desc_trans_len(desc), + sizeof(struct buffer_head *), + GFP_NOFS); + real_blocks = kmalloc_array(get_desc_trans_len(desc), + sizeof(struct buffer_head *), + GFP_NOFS); if (!log_blocks || !real_blocks) { brelse(c_bh); brelse(d_bh); diff --git a/fs/select.c b/fs/select.c index d027addc9b31..664c3fd499ca 100644 --- a/fs/select.c +++ b/fs/select.c @@ -1224,7 +1224,7 @@ static int compat_core_sys_select(int n, compat_ulong_t __user *inp, size = FDS_BYTES(n); bits = stack_fds; if (size > sizeof(stack_fds) / 6) { - bits = kmalloc(6 * size, GFP_KERNEL); + bits = kmalloc_array(6, size, GFP_KERNEL); ret = -ENOMEM; if (!bits) goto out_nofds; diff --git a/fs/splice.c b/fs/splice.c index c84ac7e97e21..6e9ef6fecba8 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -259,8 +259,9 @@ int splice_grow_spd(const struct pipe_inode_info *pipe, struct splice_pipe_desc if (buffers <= PIPE_DEF_BUFFERS) return 0; - spd->pages = kmalloc(buffers * sizeof(struct page *), GFP_KERNEL); - spd->partial = kmalloc(buffers * sizeof(struct partial_page), GFP_KERNEL); + spd->pages = kmalloc_array(buffers, sizeof(struct page *), GFP_KERNEL); + spd->partial = kmalloc_array(buffers, sizeof(struct partial_page), + GFP_KERNEL); if (spd->pages && spd->partial) return 0; @@ -395,7 +396,7 @@ static ssize_t default_file_splice_read(struct file *in, loff_t *ppos, vec = __vec; if (nr_pages > PIPE_DEF_BUFFERS) { - vec = kmalloc(nr_pages * sizeof(struct kvec), GFP_KERNEL); + vec = kmalloc_array(nr_pages, sizeof(struct kvec), GFP_KERNEL); if (unlikely(!vec)) { res = -ENOMEM; goto out; diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c index 69051f7a9606..027363eb6870 100644 --- a/fs/ubifs/journal.c +++ b/fs/ubifs/journal.c @@ -1291,7 +1291,7 @@ static int truncate_data_node(const struct ubifs_info *c, const struct inode *in int err, dlen, compr_type, out_len, old_dlen; out_len = le32_to_cpu(dn->size); - buf = kmalloc(out_len * WORST_COMPR_FACTOR, GFP_NOFS); + buf = kmalloc_array(WORST_COMPR_FACTOR, out_len, GFP_NOFS); if (!buf) return -ENOMEM; diff --git a/fs/ubifs/lpt.c b/fs/ubifs/lpt.c index 9a517109da0f..d4e45adddf1e 100644 --- a/fs/ubifs/lpt.c +++ b/fs/ubifs/lpt.c @@ -628,7 +628,7 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first, /* Needed by 'ubifs_pack_lsave()' */ c->main_first = c->leb_cnt - *main_lebs; - lsave = kmalloc(sizeof(int) * c->lsave_cnt, GFP_KERNEL); + lsave = kmalloc_array(c->lsave_cnt, sizeof(int), GFP_KERNEL); pnode = kzalloc(sizeof(struct ubifs_pnode), GFP_KERNEL); nnode = kzalloc(sizeof(struct ubifs_nnode), GFP_KERNEL); buf = vmalloc(c->leb_size); @@ -1636,15 +1636,17 @@ static int lpt_init_rd(struct ubifs_info *c) return -ENOMEM; for (i = 0; i < LPROPS_HEAP_CNT; i++) { - c->lpt_heap[i].arr = kmalloc(sizeof(void *) * LPT_HEAP_SZ, - GFP_KERNEL); + c->lpt_heap[i].arr = kmalloc_array(LPT_HEAP_SZ, + sizeof(void *), + GFP_KERNEL); if (!c->lpt_heap[i].arr) return -ENOMEM; c->lpt_heap[i].cnt = 0; c->lpt_heap[i].max_cnt = LPT_HEAP_SZ; } - c->dirty_idx.arr = kmalloc(sizeof(void *) * LPT_HEAP_SZ, GFP_KERNEL); + c->dirty_idx.arr = kmalloc_array(LPT_HEAP_SZ, sizeof(void *), + GFP_KERNEL); if (!c->dirty_idx.arr) return -ENOMEM; c->dirty_idx.cnt = 0; @@ -1697,7 +1699,7 @@ static int lpt_init_wr(struct ubifs_info *c) return -ENOMEM; if (c->big_lpt) { - c->lsave = kmalloc(sizeof(int) * c->lsave_cnt, GFP_NOFS); + c->lsave = kmalloc_array(c->lsave_cnt, sizeof(int), GFP_NOFS); if (!c->lsave) return -ENOMEM; err = read_lsave(c); @@ -1939,8 +1941,8 @@ int ubifs_lpt_scan_nolock(struct ubifs_info *c, int start_lnum, int end_lnum, return err; } - path = kmalloc(sizeof(struct lpt_scan_node) * (c->lpt_hght + 1), - GFP_NOFS); + path = kmalloc_array(c->lpt_hght + 1, sizeof(struct lpt_scan_node), + GFP_NOFS); if (!path) return -ENOMEM; diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 224ca552edb9..0bc04215eacf 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -1198,7 +1198,8 @@ static int mount_ubifs(struct ubifs_info *c) * never exceed 64. */ err = -ENOMEM; - c->bottom_up_buf = kmalloc(BOTTOM_UP_HEIGHT * sizeof(int), GFP_KERNEL); + c->bottom_up_buf = kmalloc_array(BOTTOM_UP_HEIGHT, sizeof(int), + GFP_KERNEL); if (!c->bottom_up_buf) goto out_free; diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c index c7828db206bc..7be4d1eb37f2 100644 --- a/fs/ubifs/tnc.c +++ b/fs/ubifs/tnc.c @@ -1104,8 +1104,9 @@ static struct ubifs_znode *dirty_cow_bottom_up(struct ubifs_info *c, ubifs_assert(znode); if (c->zroot.znode->level > BOTTOM_UP_HEIGHT) { kfree(c->bottom_up_buf); - c->bottom_up_buf = kmalloc(c->zroot.znode->level * sizeof(int), - GFP_NOFS); + c->bottom_up_buf = kmalloc_array(c->zroot.znode->level, + sizeof(int), + GFP_NOFS); if (!c->bottom_up_buf) return ERR_PTR(-ENOMEM); path = c->bottom_up_buf; diff --git a/fs/ubifs/tnc_commit.c b/fs/ubifs/tnc_commit.c index aa31f60220ef..a9df94ad46a3 100644 --- a/fs/ubifs/tnc_commit.c +++ b/fs/ubifs/tnc_commit.c @@ -366,7 +366,8 @@ static int layout_in_gaps(struct ubifs_info *c, int cnt) dbg_gc("%d znodes to write", cnt); - c->gap_lebs = kmalloc(sizeof(int) * (c->lst.idx_lebs + 1), GFP_NOFS); + c->gap_lebs = kmalloc_array(c->lst.idx_lebs + 1, sizeof(int), + GFP_NOFS); if (!c->gap_lebs) return -ENOMEM; @@ -674,7 +675,7 @@ static int alloc_idx_lebs(struct ubifs_info *c, int cnt) dbg_cmt("need about %d empty LEBS for TNC commit", leb_cnt); if (!leb_cnt) return 0; - c->ilebs = kmalloc(leb_cnt * sizeof(int), GFP_NOFS); + c->ilebs = kmalloc_array(leb_cnt, sizeof(int), GFP_NOFS); if (!c->ilebs) return -ENOMEM; for (i = 0; i < leb_cnt; i++) { diff --git a/fs/ufs/super.c b/fs/ufs/super.c index 6440003f8ddc..9837c67dd032 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -540,7 +540,7 @@ static int ufs_read_cylinder_structures(struct super_block *sb) * Read cylinder group (we read only first fragment from block * at this time) and prepare internal data structures for cg caching. */ - if (!(sbi->s_ucg = kmalloc (sizeof(struct buffer_head *) * uspi->s_ncg, GFP_NOFS))) + if (!(sbi->s_ucg = kmalloc_array (uspi->s_ncg, sizeof(struct buffer_head *), GFP_NOFS))) goto failed; for (i = 0; i < uspi->s_ncg; i++) sbi->s_ucg[i] = NULL; diff --git a/kernel/cgroup/cgroup-v1.c b/kernel/cgroup/cgroup-v1.c index 1d166be184f7..ae2da7b9b3e8 100644 --- a/kernel/cgroup/cgroup-v1.c +++ b/kernel/cgroup/cgroup-v1.c @@ -197,7 +197,7 @@ static void *pidlist_allocate(int count) if (PIDLIST_TOO_LARGE(count)) return vmalloc(count * sizeof(pid_t)); else - return kmalloc(count * sizeof(pid_t), GFP_KERNEL); + return kmalloc_array(count, sizeof(pid_t), GFP_KERNEL); } static void pidlist_free(void *p) diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c index 8ef030828e9d..84e3543548cc 100644 --- a/kernel/cgroup/cpuset.c +++ b/kernel/cgroup/cpuset.c @@ -703,7 +703,7 @@ static int generate_sched_domains(cpumask_var_t **domains, goto done; } - csa = kmalloc(nr_cpusets() * sizeof(cp), GFP_KERNEL); + csa = kmalloc_array(nr_cpusets(), sizeof(cp), GFP_KERNEL); if (!csa) goto done; csn = 0; @@ -772,7 +772,8 @@ restart: * The rest of the code, including the scheduler, can deal with * dattr==NULL case. No need to abort if alloc fails. */ - dattr = kmalloc(ndoms * sizeof(struct sched_domain_attr), GFP_KERNEL); + dattr = kmalloc_array(ndoms, sizeof(struct sched_domain_attr), + GFP_KERNEL); for (nslot = 0, i = 0; i < csn; i++) { struct cpuset *a = csa[i]; diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c index 90bd7895dc85..dac2cc0c17b5 100644 --- a/kernel/debug/kdb/kdb_main.c +++ b/kernel/debug/kdb/kdb_main.c @@ -729,8 +729,8 @@ static int kdb_defcmd(int argc, const char **argv) kdb_printf("Command only available during kdb_init()\n"); return KDB_NOTIMP; } - defcmd_set = kmalloc((defcmd_set_count + 1) * sizeof(*defcmd_set), - GFP_KDB); + defcmd_set = kmalloc_array(defcmd_set_count + 1, sizeof(*defcmd_set), + GFP_KDB); if (!defcmd_set) goto fail_defcmd; memcpy(defcmd_set, save_defcmd_set, @@ -2731,8 +2731,9 @@ int kdb_register_flags(char *cmd, } if (i >= kdb_max_commands) { - kdbtab_t *new = kmalloc((kdb_max_commands - KDB_BASE_CMD_MAX + - kdb_command_extend) * sizeof(*new), GFP_KDB); + kdbtab_t *new = kmalloc_array(kdb_max_commands - KDB_BASE_CMD_MAX + kdb_command_extend, + sizeof(*new), + GFP_KDB); if (!new) { kdb_printf("Could not allocate new kdb_command " "table\n"); diff --git a/kernel/locking/locktorture.c b/kernel/locking/locktorture.c index 838e25a6f3d2..fe8109492901 100644 --- a/kernel/locking/locktorture.c +++ b/kernel/locking/locktorture.c @@ -929,7 +929,9 @@ static int __init lock_torture_init(void) /* Initialize the statistics so that each run gets its own numbers. */ if (nwriters_stress) { lock_is_write_held = 0; - cxt.lwsa = kmalloc(sizeof(*cxt.lwsa) * cxt.nrealwriters_stress, GFP_KERNEL); + cxt.lwsa = kmalloc_array(cxt.nrealwriters_stress, + sizeof(*cxt.lwsa), + GFP_KERNEL); if (cxt.lwsa == NULL) { VERBOSE_TOROUT_STRING("cxt.lwsa: Out of memory"); firsterr = -ENOMEM; @@ -958,7 +960,9 @@ static int __init lock_torture_init(void) if (nreaders_stress) { lock_is_read_held = 0; - cxt.lrsa = kmalloc(sizeof(*cxt.lrsa) * cxt.nrealreaders_stress, GFP_KERNEL); + cxt.lrsa = kmalloc_array(cxt.nrealreaders_stress, + sizeof(*cxt.lrsa), + GFP_KERNEL); if (cxt.lrsa == NULL) { VERBOSE_TOROUT_STRING("cxt.lrsa: Out of memory"); firsterr = -ENOMEM; diff --git a/kernel/relay.c b/kernel/relay.c index b141ce697679..813823080a08 100644 --- a/kernel/relay.c +++ b/kernel/relay.c @@ -169,7 +169,8 @@ static struct rchan_buf *relay_create_buf(struct rchan *chan) buf = kzalloc(sizeof(struct rchan_buf), GFP_KERNEL); if (!buf) return NULL; - buf->padding = kmalloc(chan->n_subbufs * sizeof(size_t *), GFP_KERNEL); + buf->padding = kmalloc_array(chan->n_subbufs, sizeof(size_t *), + GFP_KERNEL); if (!buf->padding) goto free_buf; diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 3753db83747d..d84b0f4bdc9f 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -8010,7 +8010,8 @@ static inline void alloc_eenv(void) for_each_possible_cpu(cpu) { struct energy_env *eenv = &per_cpu(eenv_cache, cpu); - eenv->cpu = kmalloc(sizeof(struct eenv_cpu) * cpu_count, GFP_KERNEL); + eenv->cpu = kmalloc_array(cpu_count, sizeof(struct eenv_cpu), + GFP_KERNEL); eenv->eenv_cpu_count = cpu_count; #ifdef DEBUG_EENV_DECISIONS eenv->debug = (struct _eenv_debug *)kmalloc(eenv_debug_size(), GFP_KERNEL); diff --git a/kernel/sched/topology.c b/kernel/sched/topology.c index b034b186f255..79919ba439ce 100644 --- a/kernel/sched/topology.c +++ b/kernel/sched/topology.c @@ -1958,7 +1958,7 @@ cpumask_var_t *alloc_sched_domains(unsigned int ndoms) int i; cpumask_var_t *doms; - doms = kmalloc(sizeof(*doms) * ndoms, GFP_KERNEL); + doms = kmalloc_array(ndoms, sizeof(*doms), GFP_KERNEL); if (!doms) return NULL; for (i = 0; i < ndoms; i++) { diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 5cc253f8fbf7..24d7fd60ff1c 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -6631,9 +6631,9 @@ static int alloc_retstack_tasklist(struct ftrace_ret_stack **ret_stack_list) struct task_struct *g, *t; for (i = 0; i < FTRACE_RETSTACK_ALLOC_SIZE; i++) { - ret_stack_list[i] = kmalloc(FTRACE_RETFUNC_DEPTH - * sizeof(struct ftrace_ret_stack), - GFP_KERNEL); + ret_stack_list[i] = kmalloc_array(FTRACE_RETFUNC_DEPTH, + sizeof(struct ftrace_ret_stack), + GFP_KERNEL); if (!ret_stack_list[i]) { start = 0; end = i; @@ -6705,9 +6705,9 @@ static int start_graph_tracing(void) struct ftrace_ret_stack **ret_stack_list; int ret, cpu; - ret_stack_list = kmalloc(FTRACE_RETSTACK_ALLOC_SIZE * - sizeof(struct ftrace_ret_stack *), - GFP_KERNEL); + ret_stack_list = kmalloc_array(FTRACE_RETSTACK_ALLOC_SIZE, + sizeof(struct ftrace_ret_stack *), + GFP_KERNEL); if (!ret_stack_list) return -ENOMEM; @@ -6889,9 +6889,9 @@ void ftrace_graph_init_idle_task(struct task_struct *t, int cpu) ret_stack = per_cpu(idle_ret_stack, cpu); if (!ret_stack) { - ret_stack = kmalloc(FTRACE_RETFUNC_DEPTH - * sizeof(struct ftrace_ret_stack), - GFP_KERNEL); + ret_stack = kmalloc_array(FTRACE_RETFUNC_DEPTH, + sizeof(struct ftrace_ret_stack), + GFP_KERNEL); if (!ret_stack) return; per_cpu(idle_ret_stack, cpu) = ret_stack; @@ -6910,9 +6910,9 @@ void ftrace_graph_init_task(struct task_struct *t) if (ftrace_graph_active) { struct ftrace_ret_stack *ret_stack; - ret_stack = kmalloc(FTRACE_RETFUNC_DEPTH - * sizeof(struct ftrace_ret_stack), - GFP_KERNEL); + ret_stack = kmalloc_array(FTRACE_RETFUNC_DEPTH, + sizeof(struct ftrace_ret_stack), + GFP_KERNEL); if (!ret_stack) return; graph_init_task(t, ret_stack); diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 9e93ef4969e7..d0a2ca3023fb 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -1754,12 +1754,13 @@ static inline void set_cmdline(int idx, const char *cmdline) static int allocate_cmdlines_buffer(unsigned int val, struct saved_cmdlines_buffer *s) { - s->map_cmdline_to_pid = kmalloc(val * sizeof(*s->map_cmdline_to_pid), - GFP_KERNEL); + s->map_cmdline_to_pid = kmalloc_array(val, + sizeof(*s->map_cmdline_to_pid), + GFP_KERNEL); if (!s->map_cmdline_to_pid) return -ENOMEM; - s->saved_cmdlines = kmalloc(val * TASK_COMM_LEN, GFP_KERNEL); + s->saved_cmdlines = kmalloc_array(TASK_COMM_LEN, val, GFP_KERNEL); if (!s->saved_cmdlines) { kfree(s->map_cmdline_to_pid); return -ENOMEM; @@ -5105,7 +5106,7 @@ trace_insert_eval_map_file(struct module *mod, struct trace_eval_map **start, * where the head holds the module and length of array, and the * tail holds a pointer to the next list. */ - map_array = kmalloc(sizeof(*map_array) * (len + 2), GFP_KERNEL); + map_array = kmalloc_array(len + 2, sizeof(*map_array), GFP_KERNEL); if (!map_array) { pr_warn("Unable to allocate trace eval mapping\n"); return; diff --git a/lib/argv_split.c b/lib/argv_split.c index 5c35752a9414..1a19a0a93dc1 100644 --- a/lib/argv_split.c +++ b/lib/argv_split.c @@ -69,7 +69,7 @@ char **argv_split(gfp_t gfp, const char *str, int *argcp) return NULL; argc = count_argc(argv_str); - argv = kmalloc(sizeof(*argv) * (argc + 2), gfp); + argv = kmalloc_array(argc + 2, sizeof(*argv), gfp); if (!argv) { kfree(argv_str); return NULL; diff --git a/lib/interval_tree_test.c b/lib/interval_tree_test.c index 835242e74aaa..75509a1511a3 100644 --- a/lib/interval_tree_test.c +++ b/lib/interval_tree_test.c @@ -64,11 +64,12 @@ static int interval_tree_test_init(void) unsigned long results; cycles_t time1, time2, time; - nodes = kmalloc(nnodes * sizeof(struct interval_tree_node), GFP_KERNEL); + nodes = kmalloc_array(nnodes, sizeof(struct interval_tree_node), + GFP_KERNEL); if (!nodes) return -ENOMEM; - queries = kmalloc(nsearches * sizeof(int), GFP_KERNEL); + queries = kmalloc_array(nsearches, sizeof(int), GFP_KERNEL); if (!queries) { kfree(nodes); return -ENOMEM; diff --git a/lib/kfifo.c b/lib/kfifo.c index a94227c55551..6cfca1be8e6f 100644 --- a/lib/kfifo.c +++ b/lib/kfifo.c @@ -54,7 +54,7 @@ int __kfifo_alloc(struct __kfifo *fifo, unsigned int size, return -EINVAL; } - fifo->data = kmalloc(size * esize, gfp_mask); + fifo->data = kmalloc_array(esize, size, gfp_mask); if (!fifo->data) { fifo->mask = 0; diff --git a/lib/mpi/mpiutil.c b/lib/mpi/mpiutil.c index 314f4dfa603e..2dbfc4c8a237 100644 --- a/lib/mpi/mpiutil.c +++ b/lib/mpi/mpiutil.c @@ -91,7 +91,7 @@ int mpi_resize(MPI a, unsigned nlimbs) return 0; /* no need to do it */ if (a->d) { - p = kmalloc(nlimbs * sizeof(mpi_limb_t), GFP_KERNEL); + p = kmalloc_array(nlimbs, sizeof(mpi_limb_t), GFP_KERNEL); if (!p) return -ENOMEM; memcpy(p, a->d, a->alloced * sizeof(mpi_limb_t)); diff --git a/lib/rbtree_test.c b/lib/rbtree_test.c index 7d36c1e27ff6..b7055b2a07d3 100644 --- a/lib/rbtree_test.c +++ b/lib/rbtree_test.c @@ -247,7 +247,7 @@ static int __init rbtree_test_init(void) cycles_t time1, time2, time; struct rb_node *node; - nodes = kmalloc(nnodes * sizeof(*nodes), GFP_KERNEL); + nodes = kmalloc_array(nnodes, sizeof(*nodes), GFP_KERNEL); if (!nodes) return -ENOMEM; diff --git a/lib/reed_solomon/reed_solomon.c b/lib/reed_solomon/reed_solomon.c index 3a1022a80a7b..e99b43f74645 100644 --- a/lib/reed_solomon/reed_solomon.c +++ b/lib/reed_solomon/reed_solomon.c @@ -85,15 +85,15 @@ static struct rs_control *rs_init(int symsize, int gfpoly, int (*gffunc)(int), rs->gffunc = gffunc; /* Allocate the arrays */ - rs->alpha_to = kmalloc(sizeof(uint16_t) * (rs->nn + 1), GFP_KERNEL); + rs->alpha_to = kmalloc_array(rs->nn + 1, sizeof(uint16_t), GFP_KERNEL); if (rs->alpha_to == NULL) goto errrs; - rs->index_of = kmalloc(sizeof(uint16_t) * (rs->nn + 1), GFP_KERNEL); + rs->index_of = kmalloc_array(rs->nn + 1, sizeof(uint16_t), GFP_KERNEL); if (rs->index_of == NULL) goto erralp; - rs->genpoly = kmalloc(sizeof(uint16_t) * (rs->nroots + 1), GFP_KERNEL); + rs->genpoly = kmalloc_array(rs->nroots + 1, sizeof(uint16_t), GFP_KERNEL); if(rs->genpoly == NULL) goto erridx; diff --git a/lib/scatterlist.c b/lib/scatterlist.c index a11127d47b33..59c02cca45da 100644 --- a/lib/scatterlist.c +++ b/lib/scatterlist.c @@ -163,7 +163,7 @@ EXPORT_SYMBOL(sg_init_one); */ static struct scatterlist *sg_kmalloc(unsigned int nents, gfp_t gfp_mask) { - return kmalloc(nents * sizeof(struct scatterlist), gfp_mask); + return kmalloc_array(nents, sizeof(struct scatterlist), gfp_mask); } static void sg_kfree(struct scatterlist *sg, unsigned int nents) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 7ad06ed9048e..86e8675494bb 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -1138,8 +1138,8 @@ static int do_huge_pmd_wp_page_fallback(struct vm_fault *vmf, pmd_t orig_pmd, unsigned long mmun_start; /* For mmu_notifiers */ unsigned long mmun_end; /* For mmu_notifiers */ - pages = kmalloc(sizeof(struct page *) * HPAGE_PMD_NR, - GFP_KERNEL); + pages = kmalloc_array(HPAGE_PMD_NR, sizeof(struct page *), + GFP_KERNEL); if (unlikely(!pages)) { ret |= VM_FAULT_OOM; goto out; diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 9ac4f76310cf..c99bdbed5af4 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -2808,7 +2808,8 @@ static int __init hugetlb_init(void) num_fault_mutexes = 1; #endif hugetlb_fault_mutex_table = - kmalloc(sizeof(struct mutex) * num_fault_mutexes, GFP_KERNEL); + kmalloc_array(num_fault_mutexes, sizeof(struct mutex), + GFP_KERNEL); BUG_ON(!hugetlb_fault_mutex_table); for (i = 0; i < num_fault_mutexes; i++) diff --git a/mm/slub.c b/mm/slub.c index 8ee2e6be7778..7a7ed043fc09 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -4561,8 +4561,9 @@ static long validate_slab_cache(struct kmem_cache *s) { int node; unsigned long count = 0; - unsigned long *map = kmalloc(BITS_TO_LONGS(oo_objects(s->max)) * - sizeof(unsigned long), GFP_KERNEL); + unsigned long *map = kmalloc_array(BITS_TO_LONGS(oo_objects(s->max)), + sizeof(unsigned long), + GFP_KERNEL); struct kmem_cache_node *n; if (!map) @@ -4722,8 +4723,9 @@ static int list_locations(struct kmem_cache *s, char *buf, unsigned long i; struct loc_track t = { 0, 0, NULL }; int node; - unsigned long *map = kmalloc(BITS_TO_LONGS(oo_objects(s->max)) * - sizeof(unsigned long), GFP_KERNEL); + unsigned long *map = kmalloc_array(BITS_TO_LONGS(oo_objects(s->max)), + sizeof(unsigned long), + GFP_KERNEL); struct kmem_cache_node *n; if (!map || !alloc_loc_track(&t, PAGE_SIZE / sizeof(struct location), @@ -5455,7 +5457,7 @@ static int show_stat(struct kmem_cache *s, char *buf, enum stat_item si) unsigned long sum = 0; int cpu; int len; - int *data = kmalloc(nr_cpu_ids * sizeof(int), GFP_KERNEL); + int *data = kmalloc_array(nr_cpu_ids, sizeof(int), GFP_KERNEL); if (!data) return -ENOMEM; diff --git a/net/9p/protocol.c b/net/9p/protocol.c index 1885403c9a3e..f44d17eef206 100644 --- a/net/9p/protocol.c +++ b/net/9p/protocol.c @@ -247,8 +247,9 @@ p9pdu_vreadf(struct p9_fcall *pdu, int proto_version, const char *fmt, "w", nwname); if (!errcode) { *wnames = - kmalloc(sizeof(char *) * *nwname, - GFP_NOFS); + kmalloc_array(*nwname, + sizeof(char *), + GFP_NOFS); if (!*wnames) errcode = -ENOMEM; } @@ -290,9 +291,9 @@ p9pdu_vreadf(struct p9_fcall *pdu, int proto_version, const char *fmt, p9pdu_readf(pdu, proto_version, "w", nwqid); if (!errcode) { *wqids = - kmalloc(*nwqid * - sizeof(struct p9_qid), - GFP_NOFS); + kmalloc_array(*nwqid, + sizeof(struct p9_qid), + GFP_NOFS); if (*wqids == NULL) errcode = -ENOMEM; } diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index f88911cffa1a..2cab31203e8f 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c @@ -362,7 +362,8 @@ static int p9_get_mapped_pages(struct virtio_chan *chan, nr_pages = DIV_ROUND_UP((unsigned long)p + len, PAGE_SIZE) - (unsigned long)p / PAGE_SIZE; - *pages = kmalloc(sizeof(struct page *) * nr_pages, GFP_NOFS); + *pages = kmalloc_array(nr_pages, sizeof(struct page *), + GFP_NOFS); if (!*pages) return -ENOMEM; diff --git a/net/atm/mpc.c b/net/atm/mpc.c index db9a1838687c..2622f779b599 100644 --- a/net/atm/mpc.c +++ b/net/atm/mpc.c @@ -472,7 +472,7 @@ static const uint8_t *copy_macs(struct mpoa_client *mpc, if (mpc->number_of_mps_macs != 0) kfree(mpc->mps_macs); mpc->number_of_mps_macs = 0; - mpc->mps_macs = kmalloc(num_macs * ETH_ALEN, GFP_KERNEL); + mpc->mps_macs = kmalloc_array(ETH_ALEN, num_macs, GFP_KERNEL); if (mpc->mps_macs == NULL) { pr_info("(%s) out of mem\n", mpc->dev->name); return NULL; diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index ff80a9d41ce1..9cb3d1674981 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1290,7 +1290,7 @@ int hci_inquiry(void __user *arg) /* cache_dump can't sleep. Therefore we allocate temp buffer and then * copy it to the user space. */ - buf = kmalloc(sizeof(struct inquiry_info) * max_rsp, GFP_KERNEL); + buf = kmalloc_array(max_rsp, sizeof(struct inquiry_info), GFP_KERNEL); if (!buf) { err = -ENOMEM; goto done; diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index ebdf1b0e576a..0d84d1f820d4 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -331,7 +331,7 @@ static int l2cap_seq_list_init(struct l2cap_seq_list *seq_list, u16 size) */ alloc_size = roundup_pow_of_two(size); - seq_list->list = kmalloc(sizeof(u16) * alloc_size, GFP_KERNEL); + seq_list->list = kmalloc_array(alloc_size, sizeof(u16), GFP_KERNEL); if (!seq_list->list) return -ENOMEM; diff --git a/net/can/bcm.c b/net/can/bcm.c index 12d851c4604d..81b2e1f5ddff 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c @@ -959,8 +959,9 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg, /* create array for CAN frames and copy the data */ if (msg_head->nframes > 1) { - op->frames = kmalloc(msg_head->nframes * op->cfsiz, - GFP_KERNEL); + op->frames = kmalloc_array(msg_head->nframes, + op->cfsiz, + GFP_KERNEL); if (!op->frames) { kfree(op); return -ENOMEM; @@ -1135,8 +1136,9 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg, if (msg_head->nframes > 1) { /* create array for CAN frames and copy the data */ - op->frames = kmalloc(msg_head->nframes * op->cfsiz, - GFP_KERNEL); + op->frames = kmalloc_array(msg_head->nframes, + op->cfsiz, + GFP_KERNEL); if (!op->frames) { kfree(op); return -ENOMEM; diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c index 0da27c66349a..190b6ed27aea 100644 --- a/net/ceph/osdmap.c +++ b/net/ceph/osdmap.c @@ -1300,8 +1300,9 @@ static int set_primary_affinity(struct ceph_osdmap *map, int osd, u32 aff) if (!map->osd_primary_affinity) { int i; - map->osd_primary_affinity = kmalloc(map->max_osd*sizeof(u32), - GFP_NOFS); + map->osd_primary_affinity = kmalloc_array(map->max_osd, + sizeof(u32), + GFP_NOFS); if (!map->osd_primary_affinity) return -ENOMEM; diff --git a/net/ceph/pagevec.c b/net/ceph/pagevec.c index ee43bc13221c..dc0f5d250ff7 100644 --- a/net/ceph/pagevec.c +++ b/net/ceph/pagevec.c @@ -20,7 +20,7 @@ struct page **ceph_get_direct_page_vector(const void __user *data, int got = 0; int rc = 0; - pages = kmalloc(sizeof(*pages) * num_pages, GFP_NOFS); + pages = kmalloc_array(num_pages, sizeof(*pages), GFP_NOFS); if (!pages) return ERR_PTR(-ENOMEM); @@ -74,7 +74,7 @@ struct page **ceph_alloc_page_vector(int num_pages, gfp_t flags) struct page **pages; int i; - pages = kmalloc(sizeof(*pages) * num_pages, flags); + pages = kmalloc_array(num_pages, sizeof(*pages), flags); if (!pages) return ERR_PTR(-ENOMEM); for (i = 0; i < num_pages; i++) { diff --git a/net/core/dev.c b/net/core/dev.c index 7c5a4afd10d6..03e66b52c992 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -8602,7 +8602,7 @@ static struct hlist_head * __net_init netdev_create_hash(void) int i; struct hlist_head *hash; - hash = kmalloc(sizeof(*hash) * NETDEV_HASHENTRIES, GFP_KERNEL); + hash = kmalloc_array(NETDEV_HASHENTRIES, sizeof(*hash), GFP_KERNEL); if (hash != NULL) for (i = 0; i < NETDEV_HASHENTRIES; i++) INIT_HLIST_HEAD(&hash[i]); diff --git a/net/core/ethtool.c b/net/core/ethtool.c index b234ff5e5a86..08781b9aa6bf 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -1795,7 +1795,7 @@ static int ethtool_self_test(struct net_device *dev, char __user *useraddr) return -EFAULT; test.len = test_len; - data = kmalloc(test_len * sizeof(u64), GFP_USER); + data = kmalloc_array(test_len, sizeof(u64), GFP_USER); if (!data) return -ENOMEM; diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c index fbeacbc2be5d..23ddee4036ff 100644 --- a/net/dcb/dcbnl.c +++ b/net/dcb/dcbnl.c @@ -983,7 +983,8 @@ static int dcbnl_build_peer_app(struct net_device *netdev, struct sk_buff* skb, */ err = ops->peer_getappinfo(netdev, &info, &app_count); if (!err && app_count) { - table = kmalloc(sizeof(struct dcb_app) * app_count, GFP_KERNEL); + table = kmalloc_array(app_count, sizeof(struct dcb_app), + GFP_KERNEL); if (!table) return -ENOMEM; diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c index fc31c02d616c..6946ee7ce3a9 100644 --- a/net/dccp/ccids/ccid2.c +++ b/net/dccp/ccids/ccid2.c @@ -46,7 +46,8 @@ static int ccid2_hc_tx_alloc_seq(struct ccid2_hc_tx_sock *hc) return -ENOMEM; /* allocate buffer and initialize linked list */ - seqp = kmalloc(CCID2_SEQBUF_LEN * sizeof(struct ccid2_seq), gfp_any()); + seqp = kmalloc_array(CCID2_SEQBUF_LEN, sizeof(struct ccid2_seq), + gfp_any()); if (seqp == NULL) return -ENOMEM; diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c index d5b1e0b3f687..f803e06ef789 100644 --- a/net/ipv4/netfilter/nf_nat_snmp_basic.c +++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c @@ -448,7 +448,7 @@ static unsigned char asn1_oid_decode(struct asn1_ctx *ctx, if (size < 2 || size > ULONG_MAX/sizeof(unsigned long)) return 0; - *oid = kmalloc(size * sizeof(unsigned long), GFP_ATOMIC); + *oid = kmalloc_array(size, sizeof(unsigned long), GFP_ATOMIC); if (*oid == NULL) return 0; diff --git a/net/ipv4/route.c b/net/ipv4/route.c index a894adbb6c9b..f6713119eaf4 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -3094,7 +3094,8 @@ int __init ip_rt_init(void) int rc = 0; int cpu; - ip_idents = kmalloc(IP_IDENTS_SZ * sizeof(*ip_idents), GFP_KERNEL); + ip_idents = kmalloc_array(IP_IDENTS_SZ, sizeof(*ip_idents), + GFP_KERNEL); if (!ip_idents) panic("IP: failed to allocate ip_idents\n"); diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 8a51f94ec1ce..5199a3015593 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -781,7 +781,7 @@ static int ieee80211_init_cipher_suites(struct ieee80211_local *local) if (have_mfp) n_suites += 4; - suites = kmalloc(sizeof(u32) * n_suites, GFP_KERNEL); + suites = kmalloc_array(n_suites, sizeof(u32), GFP_KERNEL); if (!suites) return -ENOMEM; diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index 9766c1cc4b0a..7c9d817e2b04 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c @@ -596,7 +596,7 @@ minstrel_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp) if (!mi->r) goto error; - mi->sample_table = kmalloc(SAMPLE_COLUMNS * max_rates, gfp); + mi->sample_table = kmalloc_array(max_rates, SAMPLE_COLUMNS, gfp); if (!mi->sample_table) goto error1; diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index 7ba4272642c9..e19919b6dd14 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c @@ -1321,7 +1321,7 @@ minstrel_ht_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp) if (!msp->ratelist) goto error; - msp->sample_table = kmalloc(SAMPLE_COLUMNS * max_rates, gfp); + msp->sample_table = kmalloc_array(max_rates, SAMPLE_COLUMNS, gfp); if (!msp->sample_table) goto error1; diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c index b3e489c859ec..ed3d9b3d6609 100644 --- a/net/netfilter/nf_conntrack_proto.c +++ b/net/netfilter/nf_conntrack_proto.c @@ -322,9 +322,9 @@ int nf_ct_l4proto_register_one(struct nf_conntrack_l4proto *l4proto) struct nf_conntrack_l4proto __rcu **proto_array; int i; - proto_array = kmalloc(MAX_NF_CT_PROTO * - sizeof(struct nf_conntrack_l4proto *), - GFP_KERNEL); + proto_array = kmalloc_array(MAX_NF_CT_PROTO, + sizeof(struct nf_conntrack_l4proto *), + GFP_KERNEL); if (proto_array == NULL) { ret = -ENOMEM; goto out_unlock; diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c index ed0ea64b8d04..0c989bf8791a 100644 --- a/net/netfilter/nf_nat_core.c +++ b/net/netfilter/nf_nat_core.c @@ -589,8 +589,9 @@ int nf_nat_l4proto_register(u8 l3proto, const struct nf_nat_l4proto *l4proto) mutex_lock(&nf_nat_proto_mutex); if (nf_nat_l4protos[l3proto] == NULL) { - l4protos = kmalloc(IPPROTO_MAX * sizeof(struct nf_nat_l4proto *), - GFP_KERNEL); + l4protos = kmalloc_array(IPPROTO_MAX, + sizeof(struct nf_nat_l4proto *), + GFP_KERNEL); if (l4protos == NULL) { ret = -ENOMEM; goto out; diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 5b8d5bfeb7ac..3c71099cb4c1 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -5958,8 +5958,8 @@ static int __init nf_tables_module_init(void) { int err; - info = kmalloc(sizeof(struct nft_expr_info) * NFT_RULE_MAXEXPRS, - GFP_KERNEL); + info = kmalloc_array(NFT_RULE_MAXEXPRS, sizeof(struct nft_expr_info), + GFP_KERNEL); if (info == NULL) { err = -ENOMEM; goto err1; diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 7bc631bfb101..ede73ecfb1f5 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -352,8 +352,9 @@ int genl_register_family(struct genl_family *family) } if (family->maxattr && !family->parallel_ops) { - family->attrbuf = kmalloc((family->maxattr+1) * - sizeof(struct nlattr *), GFP_KERNEL); + family->attrbuf = kmalloc_array(family->maxattr + 1, + sizeof(struct nlattr *), + GFP_KERNEL); if (family->attrbuf == NULL) { err = -ENOMEM; goto errout_locked; @@ -567,8 +568,9 @@ static int genl_family_rcv_msg(const struct genl_family *family, return -EOPNOTSUPP; if (family->maxattr && family->parallel_ops) { - attrbuf = kmalloc((family->maxattr+1) * - sizeof(struct nlattr *), GFP_KERNEL); + attrbuf = kmalloc_array(family->maxattr + 1, + sizeof(struct nlattr *), + GFP_KERNEL); if (attrbuf == NULL) return -ENOMEM; } else diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index 3248cf04d0b3..c82e3b9ad488 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c @@ -1616,8 +1616,9 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info) goto err_destroy_table; } - dp->ports = kmalloc(DP_VPORT_HASH_BUCKETS * sizeof(struct hlist_head), - GFP_KERNEL); + dp->ports = kmalloc_array(DP_VPORT_HASH_BUCKETS, + sizeof(struct hlist_head), + GFP_KERNEL); if (!dp->ports) { err = -ENOMEM; goto err_destroy_percpu; diff --git a/net/rds/info.c b/net/rds/info.c index 140a44a5f7b7..e367a97a18c8 100644 --- a/net/rds/info.c +++ b/net/rds/info.c @@ -188,7 +188,7 @@ int rds_info_getsockopt(struct socket *sock, int optname, char __user *optval, nr_pages = (PAGE_ALIGN(start + len) - (start & PAGE_MASK)) >> PAGE_SHIFT; - pages = kmalloc(nr_pages * sizeof(struct page *), GFP_KERNEL); + pages = kmalloc_array(nr_pages, sizeof(struct page *), GFP_KERNEL); if (!pages) { ret = -ENOMEM; goto out; diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c index 48fad9ba8601..09487b9f9dd3 100644 --- a/net/rxrpc/rxkad.c +++ b/net/rxrpc/rxkad.c @@ -432,7 +432,7 @@ static int rxkad_verify_packet_2(struct rxrpc_call *call, struct sk_buff *skb, sg = _sg; if (unlikely(nsg > 4)) { - sg = kmalloc(sizeof(*sg) * nsg, GFP_NOIO); + sg = kmalloc_array(nsg, sizeof(*sg), GFP_NOIO); if (!sg) goto nomem; } diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 8fe9c0646205..549c95313c6a 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -1456,7 +1456,7 @@ static __init int sctp_init(void) /* Allocate and initialize the endpoint hash table. */ sctp_ep_hashsize = 64; sctp_ep_hashtable = - kmalloc(64 * sizeof(struct sctp_hashbucket), GFP_KERNEL); + kmalloc_array(64, sizeof(struct sctp_hashbucket), GFP_KERNEL); if (!sctp_ep_hashtable) { pr_err("Failed endpoint_hash alloc\n"); status = -ENOMEM; diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 1281b967dbf9..27e2b2230d03 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -1757,7 +1757,8 @@ alloc_enc_pages(struct rpc_rqst *rqstp) last = (snd_buf->page_base + snd_buf->page_len - 1) >> PAGE_SHIFT; rqstp->rq_enc_pages_num = last - first + 1 + 1; rqstp->rq_enc_pages - = kmalloc(rqstp->rq_enc_pages_num * sizeof(struct page *), + = kmalloc_array(rqstp->rq_enc_pages_num, + sizeof(struct page *), GFP_NOFS); if (!rqstp->rq_enc_pages) goto out; diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c index fa0522cd683e..d8e1c328046e 100644 --- a/net/tipc/netlink_compat.c +++ b/net/tipc/netlink_compat.c @@ -307,8 +307,9 @@ static int __tipc_nl_compat_doit(struct tipc_nl_compat_cmd_doit *cmd, if (err) goto trans_out; - attrbuf = kmalloc((tipc_genl_family.maxattr + 1) * - sizeof(struct nlattr *), GFP_KERNEL); + attrbuf = kmalloc_array(tipc_genl_family.maxattr + 1, + sizeof(struct nlattr *), + GFP_KERNEL); if (!attrbuf) { err = -ENOMEM; goto trans_out; diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c index ca3d9ac05bc9..8c03e29f6718 100644 --- a/sound/core/pcm_compat.c +++ b/sound/core/pcm_compat.c @@ -432,7 +432,7 @@ static int snd_pcm_ioctl_xfern_compat(struct snd_pcm_substream *substream, get_user(frames, &data32->frames)) return -EFAULT; bufptr = compat_ptr(buf); - bufs = kmalloc(sizeof(void __user *) * ch, GFP_KERNEL); + bufs = kmalloc_array(ch, sizeof(void __user *), GFP_KERNEL); if (bufs == NULL) return -ENOMEM; for (i = 0; i < ch; i++) { diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index dc582c29abf7..c93f451d12e0 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -3171,7 +3171,7 @@ static ssize_t snd_pcm_readv(struct kiocb *iocb, struct iov_iter *to) if (!frame_aligned(runtime, to->iov->iov_len)) return -EINVAL; frames = bytes_to_samples(runtime, to->iov->iov_len); - bufs = kmalloc(sizeof(void *) * to->nr_segs, GFP_KERNEL); + bufs = kmalloc_array(to->nr_segs, sizeof(void *), GFP_KERNEL); if (bufs == NULL) return -ENOMEM; for (i = 0; i < to->nr_segs; ++i) @@ -3206,7 +3206,7 @@ static ssize_t snd_pcm_writev(struct kiocb *iocb, struct iov_iter *from) !frame_aligned(runtime, from->iov->iov_len)) return -EINVAL; frames = bytes_to_samples(runtime, from->iov->iov_len); - bufs = kmalloc(sizeof(void *) * from->nr_segs, GFP_KERNEL); + bufs = kmalloc_array(from->nr_segs, sizeof(void *), GFP_KERNEL); if (bufs == NULL) return -ENOMEM; for (i = 0; i < from->nr_segs; ++i) diff --git a/sound/core/seq/seq_midi_emul.c b/sound/core/seq/seq_midi_emul.c index 9e2912e3e80f..288f839a554b 100644 --- a/sound/core/seq/seq_midi_emul.c +++ b/sound/core/seq/seq_midi_emul.c @@ -657,7 +657,7 @@ static struct snd_midi_channel *snd_midi_channel_init_set(int n) struct snd_midi_channel *chan; int i; - chan = kmalloc(n * sizeof(struct snd_midi_channel), GFP_KERNEL); + chan = kmalloc_array(n, sizeof(struct snd_midi_channel), GFP_KERNEL); if (chan) { for (i = 0; i < n; i++) snd_midi_channel_init(chan+i, i); diff --git a/sound/firewire/packets-buffer.c b/sound/firewire/packets-buffer.c index 3b09b8ef3a09..715cd99f28de 100644 --- a/sound/firewire/packets-buffer.c +++ b/sound/firewire/packets-buffer.c @@ -27,7 +27,7 @@ int iso_packets_buffer_init(struct iso_packets_buffer *b, struct fw_unit *unit, void *p; int err; - b->packets = kmalloc(count * sizeof(*b->packets), GFP_KERNEL); + b->packets = kmalloc_array(count, sizeof(*b->packets), GFP_KERNEL); if (!b->packets) { err = -ENOMEM; goto error; diff --git a/sound/oss/dmasound/dmasound_core.c b/sound/oss/dmasound/dmasound_core.c index fb3bbceb1fef..5d51d88aea98 100644 --- a/sound/oss/dmasound/dmasound_core.c +++ b/sound/oss/dmasound/dmasound_core.c @@ -420,7 +420,7 @@ static int sq_allocate_buffers(struct sound_queue *sq, int num, int size) return 0; sq->numBufs = num; sq->bufSize = size; - sq->buffers = kmalloc (num * sizeof(char *), GFP_KERNEL); + sq->buffers = kmalloc_array (num, sizeof(char *), GFP_KERNEL); if (!sq->buffers) return -ENOMEM; for (i = 0; i < num; i++) { diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index 0020fd0efc46..97dfd9757b86 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c @@ -460,7 +460,7 @@ static int load_firmware(struct snd_cs46xx *chip, entry->size = le32_to_cpu(fwdat[fwlen++]); if (fwlen + entry->size > fwsize) goto error_inval; - entry->data = kmalloc(entry->size * 4, GFP_KERNEL); + entry->data = kmalloc_array(entry->size, 4, GFP_KERNEL); if (!entry->data) goto error; memcpy_le32(entry->data, &fwdat[fwlen], entry->size * 4); @@ -4036,8 +4036,9 @@ int snd_cs46xx_create(struct snd_card *card, snd_cs46xx_proc_init(card, chip); #ifdef CONFIG_PM_SLEEP - chip->saved_regs = kmalloc(sizeof(*chip->saved_regs) * - ARRAY_SIZE(saved_regs), GFP_KERNEL); + chip->saved_regs = kmalloc_array(ARRAY_SIZE(saved_regs), + sizeof(*chip->saved_regs), + GFP_KERNEL); if (!chip->saved_regs) { snd_cs46xx_free(chip); return -ENOMEM; diff --git a/sound/pci/cs46xx/dsp_spos.c b/sound/pci/cs46xx/dsp_spos.c index f03bbd0eb027..5e9ab685ac82 100644 --- a/sound/pci/cs46xx/dsp_spos.c +++ b/sound/pci/cs46xx/dsp_spos.c @@ -243,7 +243,9 @@ struct dsp_spos_instance *cs46xx_dsp_spos_create (struct snd_cs46xx * chip) ins->symbol_table.symbols = vmalloc(sizeof(struct dsp_symbol_entry) * DSP_MAX_SYMBOLS); ins->code.data = kmalloc(DSP_CODE_BYTE_SIZE, GFP_KERNEL); - ins->modules = kmalloc(sizeof(struct dsp_module_desc) * DSP_MAX_MODULES, GFP_KERNEL); + ins->modules = kmalloc_array(DSP_MAX_MODULES, + sizeof(struct dsp_module_desc), + GFP_KERNEL); if (!ins->symbol_table.symbols || !ins->code.data || !ins->modules) { cs46xx_dsp_spos_destroy(chip); goto error; diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c index 5c00e3536767..e300aa33ceec 100644 --- a/sound/pci/emu10k1/emufx.c +++ b/sound/pci/emu10k1/emufx.c @@ -2695,12 +2695,12 @@ int snd_emu10k1_efx_alloc_pm_buffer(struct snd_emu10k1 *emu) int len; len = emu->audigy ? 0x200 : 0x100; - emu->saved_gpr = kmalloc(len * 4, GFP_KERNEL); + emu->saved_gpr = kmalloc_array(len, 4, GFP_KERNEL); if (! emu->saved_gpr) return -ENOMEM; len = emu->audigy ? 0x100 : 0xa0; - emu->tram_val_saved = kmalloc(len * 4, GFP_KERNEL); - emu->tram_addr_saved = kmalloc(len * 4, GFP_KERNEL); + emu->tram_val_saved = kmalloc_array(len, 4, GFP_KERNEL); + emu->tram_addr_saved = kmalloc_array(len, 4, GFP_KERNEL); if (! emu->tram_val_saved || ! emu->tram_addr_saved) return -ENOMEM; len = emu->audigy ? 2 * 1024 : 2 * 512; diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 7d65fe31c825..5b5dce9a89c7 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -158,7 +158,7 @@ static int read_and_add_raw_conns(struct hda_codec *codec, hda_nid_t nid) len = snd_hda_get_raw_connections(codec, nid, list, ARRAY_SIZE(list)); if (len == -ENOSPC) { len = snd_hda_get_num_raw_conns(codec, nid); - result = kmalloc(sizeof(hda_nid_t) * len, GFP_KERNEL); + result = kmalloc_array(len, sizeof(hda_nid_t), GFP_KERNEL); if (!result) return -ENOMEM; len = snd_hda_get_raw_connections(codec, nid, result, len); @@ -438,7 +438,7 @@ static int read_widget_caps(struct hda_codec *codec, hda_nid_t fg_node) int i; hda_nid_t nid; - codec->wcaps = kmalloc(codec->core.num_nodes * 4, GFP_KERNEL); + codec->wcaps = kmalloc_array(codec->core.num_nodes, 4, GFP_KERNEL); if (!codec->wcaps) return -ENOMEM; nid = codec->core.start_nid; diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index 033aa84365b9..c6b778b2580c 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c @@ -825,8 +825,9 @@ static void print_codec_info(struct snd_info_entry *entry, if (wid_caps & AC_WCAP_CONN_LIST) { conn_len = snd_hda_get_num_raw_conns(codec, nid); if (conn_len > 0) { - conn = kmalloc(sizeof(hda_nid_t) * conn_len, - GFP_KERNEL); + conn = kmalloc_array(conn_len, + sizeof(hda_nid_t), + GFP_KERNEL); if (!conn) return; if (snd_hda_get_raw_connections(codec, nid, conn, diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 3a1c0b8b4ea2..c488c5afa195 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -439,7 +439,9 @@ static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substre return -ENOMEM; } if (! dev->idx_table) { - dev->idx_table = kmalloc(sizeof(*dev->idx_table) * VIA_TABLE_SIZE, GFP_KERNEL); + dev->idx_table = kmalloc_array(VIA_TABLE_SIZE, + sizeof(*dev->idx_table), + GFP_KERNEL); if (! dev->idx_table) return -ENOMEM; } diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c index 8a69221c1b86..b13c8688cc8d 100644 --- a/sound/pci/via82xx_modem.c +++ b/sound/pci/via82xx_modem.c @@ -292,7 +292,9 @@ static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substre return -ENOMEM; } if (! dev->idx_table) { - dev->idx_table = kmalloc(sizeof(*dev->idx_table) * VIA_TABLE_SIZE, GFP_KERNEL); + dev->idx_table = kmalloc_array(VIA_TABLE_SIZE, + sizeof(*dev->idx_table), + GFP_KERNEL); if (! dev->idx_table) return -ENOMEM; } diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index 8ca2e41e5827..6f81396aadc9 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c @@ -2435,8 +2435,8 @@ int snd_ymfpci_create(struct snd_card *card, goto free_chip; #ifdef CONFIG_PM_SLEEP - chip->saved_regs = kmalloc(YDSXGR_NUM_SAVED_REGS * sizeof(u32), - GFP_KERNEL); + chip->saved_regs = kmalloc_array(YDSXGR_NUM_SAVED_REGS, sizeof(u32), + GFP_KERNEL); if (chip->saved_regs == NULL) { err = -ENOMEM; goto free_chip; diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index 4fd350e8420d..3acaef24f184 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c @@ -2023,8 +2023,9 @@ static void wm8904_handle_pdata(struct snd_soc_codec *codec) wm8904_get_drc_enum, wm8904_put_drc_enum); /* We need an array of texts for the enum API */ - wm8904->drc_texts = kmalloc(sizeof(char *) - * pdata->num_drc_cfgs, GFP_KERNEL); + wm8904->drc_texts = kmalloc_array(pdata->num_drc_cfgs, + sizeof(char *), + GFP_KERNEL); if (!wm8904->drc_texts) return; diff --git a/sound/soc/codecs/wm8958-dsp2.c b/sound/soc/codecs/wm8958-dsp2.c index 6b864c0fc2b6..9038740d2a1c 100644 --- a/sound/soc/codecs/wm8958-dsp2.c +++ b/sound/soc/codecs/wm8958-dsp2.c @@ -932,8 +932,9 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) }; /* We need an array of texts for the enum API */ - wm8994->mbc_texts = kmalloc(sizeof(char *) - * pdata->num_mbc_cfgs, GFP_KERNEL); + wm8994->mbc_texts = kmalloc_array(pdata->num_mbc_cfgs, + sizeof(char *), + GFP_KERNEL); if (!wm8994->mbc_texts) return; @@ -957,8 +958,9 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) }; /* We need an array of texts for the enum API */ - wm8994->vss_texts = kmalloc(sizeof(char *) - * pdata->num_vss_cfgs, GFP_KERNEL); + wm8994->vss_texts = kmalloc_array(pdata->num_vss_cfgs, + sizeof(char *), + GFP_KERNEL); if (!wm8994->vss_texts) return; @@ -983,8 +985,9 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) }; /* We need an array of texts for the enum API */ - wm8994->vss_hpf_texts = kmalloc(sizeof(char *) - * pdata->num_vss_hpf_cfgs, GFP_KERNEL); + wm8994->vss_hpf_texts = kmalloc_array(pdata->num_vss_hpf_cfgs, + sizeof(char *), + GFP_KERNEL); if (!wm8994->vss_hpf_texts) return; @@ -1010,8 +1013,9 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) }; /* We need an array of texts for the enum API */ - wm8994->enh_eq_texts = kmalloc(sizeof(char *) - * pdata->num_enh_eq_cfgs, GFP_KERNEL); + wm8994->enh_eq_texts = kmalloc_array(pdata->num_enh_eq_cfgs, + sizeof(char *), + GFP_KERNEL); if (!wm8994->enh_eq_texts) return; diff --git a/sound/usb/caiaq/audio.c b/sound/usb/caiaq/audio.c index fb1c1eac0b5e..f35d29f49ffe 100644 --- a/sound/usb/caiaq/audio.c +++ b/sound/usb/caiaq/audio.c @@ -728,7 +728,7 @@ static struct urb **alloc_urbs(struct snd_usb_caiaqdev *cdev, int dir, int *ret) usb_sndisocpipe(usb_dev, ENDPOINT_PLAYBACK) : usb_rcvisocpipe(usb_dev, ENDPOINT_CAPTURE); - urbs = kmalloc(N_URBS * sizeof(*urbs), GFP_KERNEL); + urbs = kmalloc_array(N_URBS, sizeof(*urbs), GFP_KERNEL); if (!urbs) { *ret = -ENOMEM; return NULL; @@ -742,7 +742,8 @@ static struct urb **alloc_urbs(struct snd_usb_caiaqdev *cdev, int dir, int *ret) } urbs[i]->transfer_buffer = - kmalloc(FRAMES_PER_URB * BYTES_PER_FRAME, GFP_KERNEL); + kmalloc_array(BYTES_PER_FRAME, FRAMES_PER_URB, + GFP_KERNEL); if (!urbs[i]->transfer_buffer) { *ret = -ENOMEM; return urbs; @@ -857,7 +858,7 @@ int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *cdev) &snd_usb_caiaq_ops); cdev->data_cb_info = - kmalloc(sizeof(struct snd_usb_caiaq_cb_info) * N_URBS, + kmalloc_array(N_URBS, sizeof(struct snd_usb_caiaq_cb_info), GFP_KERNEL); if (!cdev->data_cb_info) diff --git a/sound/usb/format.c b/sound/usb/format.c index 2227b4cea338..79d6db652c60 100644 --- a/sound/usb/format.c +++ b/sound/usb/format.c @@ -204,7 +204,8 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof */ int r, idx; - fp->rate_table = kmalloc(sizeof(int) * nr_rates, GFP_KERNEL); + fp->rate_table = kmalloc_array(nr_rates, sizeof(int), + GFP_KERNEL); if (fp->rate_table == NULL) return -ENOMEM; @@ -429,7 +430,7 @@ static int parse_audio_format_rates_v2(struct snd_usb_audio *chip, goto err_free; } - fp->rate_table = kmalloc(sizeof(int) * fp->nr_rates, GFP_KERNEL); + fp->rate_table = kmalloc_array(fp->nr_rates, sizeof(int), GFP_KERNEL); if (!fp->rate_table) { ret = -ENOMEM; goto err_free; diff --git a/sound/usb/line6/pcm.c b/sound/usb/line6/pcm.c index 896add5ffee3..868f38682103 100644 --- a/sound/usb/line6/pcm.c +++ b/sound/usb/line6/pcm.c @@ -158,8 +158,8 @@ static int line6_buffer_acquire(struct snd_line6_pcm *line6pcm, /* Invoked multiple times in a row so allocate once only */ if (!test_and_set_bit(type, &pstr->opened) && !pstr->buffer) { - pstr->buffer = kmalloc(line6pcm->line6->iso_buffers * - LINE6_ISO_PACKETS * pkt_size, GFP_KERNEL); + pstr->buffer = kmalloc(array3_size(line6pcm->line6->iso_buffers, LINE6_ISO_PACKETS, pkt_size), + GFP_KERNEL); if (!pstr->buffer) return -ENOMEM; } diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 20f32c260fee..edb92a6941db 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -2443,7 +2443,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, cval->control = (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR) ? UAC2_CX_CLOCK_SELECTOR : UAC2_SU_SELECTOR; - namelist = kmalloc(sizeof(char *) * desc->bNrInPins, GFP_KERNEL); + namelist = kmalloc_array(desc->bNrInPins, sizeof(char *), GFP_KERNEL); if (!namelist) { kfree(cval); return -ENOMEM; diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 816c7d5a41e3..ff4a89af9368 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -1261,7 +1261,7 @@ static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime, return 0; subs->rate_list.list = rate_list = - kmalloc(sizeof(int) * count, GFP_KERNEL); + kmalloc_array(count, sizeof(int), GFP_KERNEL); if (!subs->rate_list.list) return -ENOMEM; subs->rate_list.count = count; diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c index 4569c0efac0a..9f71a0b8b14f 100644 --- a/sound/usb/usx2y/usbusx2y.c +++ b/sound/usb/usx2y/usbusx2y.c @@ -266,7 +266,7 @@ int usX2Y_AsyncSeq04_init(struct usX2Ydev *usX2Y) int err = 0, i; - if (NULL == (usX2Y->AS04.buffer = kmalloc(URB_DataLen_AsyncSeq*URBS_AsyncSeq, GFP_KERNEL))) { + if (NULL == (usX2Y->AS04.buffer = kmalloc_array(URBS_AsyncSeq, URB_DataLen_AsyncSeq, GFP_KERNEL))) { err = -ENOMEM; } else for (i = 0; i < URBS_AsyncSeq; ++i) { diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c index 2dfc0abf2e37..3c2898f82005 100644 --- a/sound/usb/usx2y/usbusx2yaudio.c +++ b/sound/usb/usx2y/usbusx2yaudio.c @@ -436,7 +436,9 @@ static int usX2Y_urbs_allocate(struct snd_usX2Y_substream *subs) } if (!is_playback && !(*purb)->transfer_buffer) { /* allocate a capture buffer per urb */ - (*purb)->transfer_buffer = kmalloc(subs->maxpacksize * nr_of_packs(), GFP_KERNEL); + (*purb)->transfer_buffer = kmalloc_array(subs->maxpacksize, + nr_of_packs(), + GFP_KERNEL); if (NULL == (*purb)->transfer_buffer) { usX2Y_urbs_release(subs); return -ENOMEM; @@ -662,7 +664,8 @@ static int usX2Y_rate_set(struct usX2Ydev *usX2Y, int rate) err = -ENOMEM; goto cleanup; } - usbdata = kmalloc(sizeof(int) * NOOF_SETRATE_URBS, GFP_KERNEL); + usbdata = kmalloc_array(NOOF_SETRATE_URBS, sizeof(int), + GFP_KERNEL); if (NULL == usbdata) { err = -ENOMEM; goto cleanup; diff --git a/techpack/audio/4.0/dsp/q6asm.c b/techpack/audio/4.0/dsp/q6asm.c index bb1df5b24432..a71ef087aa31 100644 --- a/techpack/audio/4.0/dsp/q6asm.c +++ b/techpack/audio/4.0/dsp/q6asm.c @@ -309,7 +309,7 @@ static ssize_t audio_output_latency_dbgfs_write(struct file *file, pr_err("%s: err count is more %zd\n", __func__, count); return -EINVAL; } - temp = kmalloc(2*sizeof(char), GFP_KERNEL); + temp = kmalloc(2, GFP_KERNEL); out_cold_index = 0; @@ -365,7 +365,7 @@ static ssize_t audio_input_latency_dbgfs_write(struct file *file, pr_err("%s: err count is more %zd\n", __func__, count); return -EINVAL; } - temp = kmalloc(2*sizeof(char), GFP_KERNEL); + temp = kmalloc(2, GFP_KERNEL); if (temp) { if (copy_from_user(temp, buf, 2*sizeof(char))) { diff --git a/techpack/audio/dsp/q6asm.c b/techpack/audio/dsp/q6asm.c index f89b01565870..6e4fb70f5f3f 100644 --- a/techpack/audio/dsp/q6asm.c +++ b/techpack/audio/dsp/q6asm.c @@ -311,7 +311,7 @@ static ssize_t audio_output_latency_dbgfs_write(struct file *file, pr_err("%s: err count is more %zd\n", __func__, count); return -EINVAL; } - temp = kmalloc(2*sizeof(char), GFP_KERNEL); + temp = kmalloc(2, GFP_KERNEL); out_cold_index = 0; @@ -367,7 +367,7 @@ static ssize_t audio_input_latency_dbgfs_write(struct file *file, pr_err("%s: err count is more %zd\n", __func__, count); return -EINVAL; } - temp = kmalloc(2*sizeof(char), GFP_KERNEL); + temp = kmalloc(2, GFP_KERNEL); if (temp) { if (copy_from_user(temp, buf, 2*sizeof(char))) { From 41b77821cf77d593231b0873dad88dee66516626 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 12 Jun 2018 14:03:40 -0700 Subject: [PATCH 574/592] treewide: kzalloc() -> kcalloc() The kzalloc() function has a 2-factor argument form, kcalloc(). This patch replaces cases of: kzalloc(a * b, gfp) with: kcalloc(a * b, gfp) as well as handling cases of: kzalloc(a * b * c, gfp) with: kzalloc(array3_size(a, b, c), gfp) as it's slightly less ugly than: kzalloc_array(array_size(a, b), c, gfp) This does, however, attempt to ignore constant size factors like: kzalloc(4 * 1024, gfp) though any constants defined via macros get caught up in the conversion. Any factors with a sizeof() of "unsigned char", "char", and "u8" were dropped, since they're redundant. The Coccinelle script used for this was: // Fix redundant parens around sizeof(). @@ type TYPE; expression THING, E; @@ ( kzalloc( - (sizeof(TYPE)) * E + sizeof(TYPE) * E , ...) | kzalloc( - (sizeof(THING)) * E + sizeof(THING) * E , ...) ) // Drop single-byte sizes and redundant parens. @@ expression COUNT; typedef u8; typedef __u8; @@ ( kzalloc( - sizeof(u8) * (COUNT) + COUNT , ...) | kzalloc( - sizeof(__u8) * (COUNT) + COUNT , ...) | kzalloc( - sizeof(char) * (COUNT) + COUNT , ...) | kzalloc( - sizeof(unsigned char) * (COUNT) + COUNT , ...) | kzalloc( - sizeof(u8) * COUNT + COUNT , ...) | kzalloc( - sizeof(__u8) * COUNT + COUNT , ...) | kzalloc( - sizeof(char) * COUNT + COUNT , ...) | kzalloc( - sizeof(unsigned char) * COUNT + COUNT , ...) ) // 2-factor product with sizeof(type/expression) and identifier or constant. @@ type TYPE; expression THING; identifier COUNT_ID; constant COUNT_CONST; @@ ( - kzalloc + kcalloc ( - sizeof(TYPE) * (COUNT_ID) + COUNT_ID, sizeof(TYPE) , ...) | - kzalloc + kcalloc ( - sizeof(TYPE) * COUNT_ID + COUNT_ID, sizeof(TYPE) , ...) | - kzalloc + kcalloc ( - sizeof(TYPE) * (COUNT_CONST) + COUNT_CONST, sizeof(TYPE) , ...) | - kzalloc + kcalloc ( - sizeof(TYPE) * COUNT_CONST + COUNT_CONST, sizeof(TYPE) , ...) | - kzalloc + kcalloc ( - sizeof(THING) * (COUNT_ID) + COUNT_ID, sizeof(THING) , ...) | - kzalloc + kcalloc ( - sizeof(THING) * COUNT_ID + COUNT_ID, sizeof(THING) , ...) | - kzalloc + kcalloc ( - sizeof(THING) * (COUNT_CONST) + COUNT_CONST, sizeof(THING) , ...) | - kzalloc + kcalloc ( - sizeof(THING) * COUNT_CONST + COUNT_CONST, sizeof(THING) , ...) ) // 2-factor product, only identifiers. @@ identifier SIZE, COUNT; @@ - kzalloc + kcalloc ( - SIZE * COUNT + COUNT, SIZE , ...) // 3-factor product with 1 sizeof(type) or sizeof(expression), with // redundant parens removed. @@ expression THING; identifier STRIDE, COUNT; type TYPE; @@ ( kzalloc( - sizeof(TYPE) * (COUNT) * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | kzalloc( - sizeof(TYPE) * (COUNT) * STRIDE + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | kzalloc( - sizeof(TYPE) * COUNT * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | kzalloc( - sizeof(TYPE) * COUNT * STRIDE + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | kzalloc( - sizeof(THING) * (COUNT) * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) | kzalloc( - sizeof(THING) * (COUNT) * STRIDE + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) | kzalloc( - sizeof(THING) * COUNT * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) | kzalloc( - sizeof(THING) * COUNT * STRIDE + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) ) // 3-factor product with 2 sizeof(variable), with redundant parens removed. @@ expression THING1, THING2; identifier COUNT; type TYPE1, TYPE2; @@ ( kzalloc( - sizeof(TYPE1) * sizeof(TYPE2) * COUNT + array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2)) , ...) | kzalloc( - sizeof(TYPE1) * sizeof(THING2) * (COUNT) + array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2)) , ...) | kzalloc( - sizeof(THING1) * sizeof(THING2) * COUNT + array3_size(COUNT, sizeof(THING1), sizeof(THING2)) , ...) | kzalloc( - sizeof(THING1) * sizeof(THING2) * (COUNT) + array3_size(COUNT, sizeof(THING1), sizeof(THING2)) , ...) | kzalloc( - sizeof(TYPE1) * sizeof(THING2) * COUNT + array3_size(COUNT, sizeof(TYPE1), sizeof(THING2)) , ...) | kzalloc( - sizeof(TYPE1) * sizeof(THING2) * (COUNT) + array3_size(COUNT, sizeof(TYPE1), sizeof(THING2)) , ...) ) // 3-factor product, only identifiers, with redundant parens removed. @@ identifier STRIDE, SIZE, COUNT; @@ ( kzalloc( - (COUNT) * STRIDE * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) | kzalloc( - COUNT * (STRIDE) * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) | kzalloc( - COUNT * STRIDE * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | kzalloc( - (COUNT) * (STRIDE) * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) | kzalloc( - COUNT * (STRIDE) * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | kzalloc( - (COUNT) * STRIDE * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | kzalloc( - (COUNT) * (STRIDE) * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | kzalloc( - COUNT * STRIDE * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) ) // Any remaining multi-factor products, first at least 3-factor products, // when they're not all constants... @@ expression E1, E2, E3; constant C1, C2, C3; @@ ( kzalloc(C1 * C2 * C3, ...) | kzalloc( - (E1) * E2 * E3 + array3_size(E1, E2, E3) , ...) | kzalloc( - (E1) * (E2) * E3 + array3_size(E1, E2, E3) , ...) | kzalloc( - (E1) * (E2) * (E3) + array3_size(E1, E2, E3) , ...) | kzalloc( - E1 * E2 * E3 + array3_size(E1, E2, E3) , ...) ) // And then all remaining 2 factors products when they're not all constants, // keeping sizeof() as the second factor argument. @@ expression THING, E1, E2; type TYPE; constant C1, C2, C3; @@ ( kzalloc(sizeof(THING) * C2, ...) | kzalloc(sizeof(TYPE) * C2, ...) | kzalloc(C1 * C2 * C3, ...) | kzalloc(C1 * C2, ...) | - kzalloc + kcalloc ( - sizeof(TYPE) * (E2) + E2, sizeof(TYPE) , ...) | - kzalloc + kcalloc ( - sizeof(TYPE) * E2 + E2, sizeof(TYPE) , ...) | - kzalloc + kcalloc ( - sizeof(THING) * (E2) + E2, sizeof(THING) , ...) | - kzalloc + kcalloc ( - sizeof(THING) * E2 + E2, sizeof(THING) , ...) | - kzalloc + kcalloc ( - (E1) * E2 + E1, E2 , ...) | - kzalloc + kcalloc ( - (E1) * (E2) + E1, E2 , ...) | - kzalloc + kcalloc ( - E1 * E2 + E1, E2 , ...) ) Signed-off-by: Kees Cook Signed-off-by: Adam W. Willis Signed-off-by: UtsavBalar1231 --- arch/arm/mach-footbridge/dc21285.c | 2 +- arch/arm/mach-ixp4xx/common-pci.c | 2 +- arch/arm/mach-omap1/mcbsp.c | 2 +- arch/arm/mach-omap2/hsmmc.c | 2 +- arch/arm/mach-omap2/omap_device.c | 4 +- arch/arm/mach-omap2/prm_common.c | 9 ++- arch/arm/mach-vexpress/spc.c | 2 +- arch/arm/mm/dma-mapping.c | 4 +- arch/arm/plat-omap/dma.c | 5 +- arch/arm64/kernel/armv8_deprecated.c | 4 +- arch/arm64/mm/context.c | 2 +- arch/ia64/kernel/topology.c | 6 +- arch/ia64/sn/kernel/io_common.c | 2 +- arch/ia64/sn/pci/pcibr/pcibr_provider.c | 2 +- arch/mips/alchemy/common/clock.c | 2 +- arch/mips/alchemy/common/dbdma.c | 2 +- arch/mips/alchemy/common/platform.c | 4 +- arch/mips/alchemy/devboards/platform.c | 4 +- arch/mips/bmips/dma.c | 2 +- arch/mips/txx9/rbtx4939/setup.c | 2 +- arch/powerpc/kernel/vdso.c | 4 +- arch/powerpc/mm/numa.c | 2 +- arch/powerpc/net/bpf_jit_comp.c | 2 +- arch/powerpc/net/bpf_jit_comp64.c | 2 +- arch/powerpc/oprofile/cell/spu_profiler.c | 4 +- arch/powerpc/platforms/4xx/pci.c | 2 +- arch/powerpc/platforms/powernv/opal-async.c | 6 +- .../powerpc/platforms/powernv/opal-sysparam.c | 8 +- arch/powerpc/sysdev/mpic.c | 4 +- arch/powerpc/sysdev/xive/native.c | 2 +- arch/s390/appldata/appldata_base.c | 2 +- arch/s390/kernel/vdso.c | 4 +- arch/sh/drivers/dma/dmabrg.c | 2 +- arch/sh/drivers/pci/pcie-sh7786.c | 2 +- arch/sparc/kernel/sys_sparc_64.c | 3 +- arch/tile/kernel/vdso.c | 2 +- arch/x86/events/amd/iommu.c | 2 +- arch/x86/events/intel/uncore.c | 2 +- arch/x86/kernel/cpu/mcheck/mce_amd.c | 2 +- arch/x86/kernel/cpu/mtrr/if.c | 2 +- arch/x86/kernel/hpet.c | 2 +- arch/x86/pci/xen.c | 2 +- arch/x86/platform/uv/uv_time.c | 2 +- block/bio.c | 3 +- block/blk-tag.c | 4 +- crypto/tcrypt.c | 2 +- drivers/acpi/acpi_platform.c | 2 +- drivers/acpi/sysfs.c | 6 +- drivers/ata/libata-core.c | 2 +- drivers/ata/libata-pmp.c | 2 +- drivers/atm/fore200e.c | 3 +- drivers/atm/iphase.c | 2 +- drivers/block/drbd/drbd_main.c | 3 +- drivers/block/null_blk.c | 9 ++- drivers/block/ps3vram.c | 5 +- drivers/block/rsxx/core.c | 3 +- drivers/block/rsxx/dma.c | 2 +- drivers/block/xen-blkback/xenbus.c | 3 +- drivers/block/xen-blkfront.c | 21 ++--- drivers/char/agp/amd-k7-agp.c | 3 +- drivers/char/agp/ati-agp.c | 3 +- drivers/char/agp/sworks-agp.c | 2 +- drivers/char/diag/diag_debugfs.c | 23 +++--- drivers/char/diag/diagchar_core.c | 2 +- drivers/char/diag/diagfwd_peripheral.c | 6 +- drivers/char/ipmi/ipmi_ssif.c | 3 +- drivers/char/vservices_serial.c | 4 +- drivers/clk/renesas/clk-r8a7740.c | 2 +- drivers/clk/renesas/clk-r8a7779.c | 2 +- drivers/clk/renesas/clk-rcar-gen2.c | 2 +- drivers/clk/renesas/clk-rz.c | 2 +- drivers/clk/rockchip/clk-rockchip.c | 2 +- drivers/clk/st/clkgen-fsyn.c | 2 +- drivers/clk/st/clkgen-pll.c | 2 +- drivers/clk/sunxi/clk-usb.c | 2 +- drivers/clk/tegra/clk.c | 7 +- drivers/clk/ti/apll.c | 2 +- drivers/clk/ti/divider.c | 4 +- drivers/clk/ti/dpll.c | 2 +- drivers/clocksource/sh_cmt.c | 2 +- drivers/clocksource/sh_mtu2.c | 2 +- drivers/clocksource/sh_tmu.c | 2 +- drivers/cpufreq/acpi-cpufreq.c | 4 +- drivers/cpufreq/arm_big_little.c | 2 +- drivers/cpufreq/at32ap-cpufreq.c | 4 +- drivers/cpufreq/cppc_cpufreq.c | 3 +- drivers/cpufreq/ia64-acpi-cpufreq.c | 4 +- drivers/cpufreq/longhaul.c | 4 +- drivers/cpufreq/pxa3xx-cpufreq.c | 2 +- drivers/cpufreq/s3c24xx-cpufreq.c | 2 +- drivers/cpufreq/sfi-cpufreq.c | 4 +- drivers/cpufreq/spear-cpufreq.c | 2 +- drivers/crypto/amcc/crypto4xx_core.c | 4 +- drivers/crypto/inside-secure/safexcel_hash.c | 2 +- drivers/crypto/marvell/hash.c | 2 +- drivers/crypto/n2_core.c | 4 +- drivers/crypto/qat/qat_common/qat_uclo.c | 5 +- drivers/crypto/talitos.c | 10 ++- drivers/dma/ioat/init.c | 4 +- drivers/dma/mv_xor.c | 2 +- drivers/dma/pl330.c | 4 +- drivers/dma/sh/shdma-base.c | 5 +- drivers/dma/xilinx/zynqmp_dma.c | 2 +- drivers/edac/amd64_edac.c | 2 +- drivers/edac/i7core_edac.c | 2 +- drivers/extcon/extcon.c | 24 +++--- drivers/firmware/dell_rbu.c | 2 +- drivers/firmware/efi/capsule.c | 2 +- drivers/firmware/efi/runtime-map.c | 2 +- drivers/fmc/fmc-sdb.c | 4 +- drivers/gpio/gpio-ml-ioh.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c | 6 +- drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_test.c | 2 +- drivers/gpu/drm/amd/amdgpu/atom.c | 2 +- drivers/gpu/drm/amd/amdgpu/ci_dpm.c | 9 ++- drivers/gpu/drm/amd/amdgpu/kv_dpm.c | 5 +- drivers/gpu/drm/amd/amdgpu/si_dpm.c | 9 ++- drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c | 2 +- drivers/gpu/drm/drm_crtc_helper.c | 10 ++- drivers/gpu/drm/drm_fb_helper.c | 5 +- drivers/gpu/drm/drm_plane_helper.c | 2 +- drivers/gpu/drm/i915/gvt/vgpu.c | 2 +- drivers/gpu/drm/i915/selftests/intel_uncore.c | 2 +- drivers/gpu/drm/msm/dsi-staging/dsi_panel.c | 2 +- drivers/gpu/drm/msm/sde/sde_hw_catalog.c | 81 ++++++++++--------- .../msm/sde/sde_hw_reg_dma_v1_color_proc.c | 4 +- drivers/gpu/drm/msm/sde/sde_hw_rot.c | 4 +- drivers/gpu/drm/nouveau/nvif/object.c | 2 +- drivers/gpu/drm/nouveau/nvkm/core/event.c | 2 +- .../gpu/drm/nouveau/nvkm/engine/fifo/gk104.c | 2 +- drivers/gpu/drm/omapdrm/omap_gem.c | 2 +- drivers/gpu/drm/radeon/atom.c | 2 +- drivers/gpu/drm/radeon/btc_dpm.c | 4 +- drivers/gpu/drm/radeon/ci_dpm.c | 9 ++- drivers/gpu/drm/radeon/kv_dpm.c | 5 +- drivers/gpu/drm/radeon/ni_dpm.c | 9 ++- drivers/gpu/drm/radeon/r600_dpm.c | 2 +- drivers/gpu/drm/radeon/radeon_atombios.c | 31 ++++--- drivers/gpu/drm/radeon/radeon_combios.c | 9 ++- drivers/gpu/drm/radeon/radeon_test.c | 2 +- drivers/gpu/drm/radeon/rs780_dpm.c | 5 +- drivers/gpu/drm/radeon/rv6xx_dpm.c | 5 +- drivers/gpu/drm/radeon/rv770_dpm.c | 5 +- drivers/gpu/drm/radeon/si_dpm.c | 9 ++- drivers/gpu/drm/radeon/sumo_dpm.c | 5 +- drivers/gpu/drm/radeon/trinity_dpm.c | 5 +- drivers/gpu/drm/selftests/test-drm_mm.c | 4 +- drivers/gpu/drm/tegra/fb.c | 2 +- drivers/gpu/msm/kgsl_pwrctrl.c | 5 +- drivers/hv/hv.c | 2 +- drivers/hv/ring_buffer.c | 2 +- drivers/hwmon/acpi_power_meter.c | 7 +- drivers/hwmon/coretemp.c | 2 +- drivers/hwmon/i5k_amb.c | 2 +- drivers/hwmon/ibmpex.c | 2 +- drivers/i2c/busses/i2c-amd756-s4882.c | 4 +- drivers/i2c/busses/i2c-nforce2-s4985.c | 4 +- drivers/i2c/busses/i2c-nforce2.c | 2 +- drivers/i2c/i2c-stub.c | 5 +- drivers/ide/hpt366.c | 2 +- drivers/ide/it821x.c | 2 +- drivers/iio/imu/adis_buffer.c | 2 +- drivers/iio/inkern.c | 2 +- drivers/infiniband/core/cache.c | 5 +- drivers/infiniband/core/device.c | 4 +- drivers/infiniband/core/iwpm_util.c | 10 ++- drivers/infiniband/hw/cxgb3/cxio_hal.c | 4 +- drivers/infiniband/hw/cxgb4/device.c | 7 +- drivers/infiniband/hw/cxgb4/qp.c | 8 +- drivers/infiniband/hw/mlx4/mad.c | 3 +- drivers/infiniband/hw/mthca/mthca_mr.c | 2 +- drivers/infiniband/hw/mthca/mthca_profile.c | 2 +- drivers/infiniband/hw/nes/nes_mgt.c | 3 +- drivers/infiniband/hw/nes/nes_verbs.c | 5 +- drivers/infiniband/hw/ocrdma/ocrdma_hw.c | 2 +- drivers/infiniband/hw/ocrdma/ocrdma_main.c | 11 +-- drivers/infiniband/hw/ocrdma/ocrdma_verbs.c | 12 +-- drivers/infiniband/hw/qedr/main.c | 4 +- drivers/infiniband/hw/qedr/verbs.c | 4 +- drivers/infiniband/hw/qib/qib_iba7322.c | 5 +- drivers/infiniband/hw/qib/qib_init.c | 4 +- drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c | 2 +- drivers/infiniband/hw/usnic/usnic_vnic.c | 2 +- drivers/infiniband/ulp/ipoib/ipoib_main.c | 7 +- drivers/infiniband/ulp/isert/ib_isert.c | 5 +- drivers/input/keyboard/omap4-keypad.c | 3 +- .../touchscreen/hxchipset/himax_common.c | 25 ++++-- .../input/touchscreen/hxchipset/himax_debug.c | 12 ++- drivers/input/touchscreen/st/fts.c | 5 +- .../synaptics_dsx/synaptics_dsx_core.c | 2 +- .../synaptics_dsx/synaptics_dsx_gesture.c | 6 +- drivers/iommu/dmar.c | 2 +- drivers/iommu/intel-iommu.c | 4 +- drivers/ipack/carriers/tpci200.c | 4 +- drivers/irqchip/irq-alpine-msi.c | 3 +- drivers/irqchip/irq-gic-v2m.c | 2 +- drivers/irqchip/irq-gic-v3-its.c | 15 ++-- drivers/irqchip/irq-gic-v3.c | 5 +- drivers/irqchip/irq-partition-percpu.c | 2 +- drivers/irqchip/irq-s3c24xx.c | 2 +- drivers/isdn/capi/capi.c | 2 +- drivers/isdn/gigaset/capi.c | 2 +- drivers/isdn/gigaset/i4l.c | 2 +- drivers/isdn/hardware/avm/b1.c | 2 +- drivers/isdn/hisax/fsm.c | 3 +- drivers/isdn/i4l/isdn_common.c | 4 +- drivers/isdn/mISDN/fsm.c | 4 +- drivers/mailbox/pcc.c | 4 +- drivers/md/bcache/super.c | 5 +- drivers/md/bitmap.c | 2 +- drivers/md/dm-android-verity.c | 5 +- drivers/md/dm-crypt.c | 5 +- drivers/md/md-cluster.c | 6 +- drivers/md/multipath.c | 3 +- drivers/md/raid0.c | 8 +- drivers/md/raid1.c | 5 +- drivers/md/raid10.c | 12 ++- drivers/md/raid5.c | 15 ++-- drivers/media/dvb-frontends/dib7000p.c | 4 +- drivers/media/dvb-frontends/dib8000.c | 4 +- drivers/media/dvb-frontends/dib9000.c | 4 +- .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 17 ++-- .../msm/ais/cam_isp/cam_isp_context.c | 3 +- .../irq_controller/cam_irq_controller.c | 19 +++-- .../ais/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c | 20 +++-- .../msm/ais/cam_req_mgr/cam_req_mgr_core.c | 4 +- .../cam_actuator/cam_actuator_dev.c | 10 ++- .../cam_sensor_module/cam_cci/cam_cci_core.c | 5 +- .../cam_flash/cam_flash_dev.c | 10 ++- .../cam_sensor/cam_sensor_dev.c | 10 ++- .../cam_sensor_utils/cam_sensor_util.c | 10 ++- .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 17 ++-- .../msm/camera/cam_isp/cam_isp_context.c | 3 +- .../irq_controller/cam_irq_controller.c | 19 +++-- .../camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c | 20 +++-- .../msm/camera/cam_req_mgr/cam_req_mgr_core.c | 4 +- .../cam_actuator/cam_actuator_dev.c | 10 ++- .../cam_sensor_module/cam_cci/cam_cci_core.c | 5 +- .../cam_flash/cam_flash_dev.c | 10 ++- .../cam_sensor/cam_sensor_dev.c | 10 ++- .../cam_sensor_utils/cam_sensor_util.c | 10 ++- .../msm/camera_v2/common/cam_smmu_api.c | 2 +- .../platform/msm/camera_v2/isp/msm_buf_mgr.c | 5 +- .../msm/camera_v2/isp/msm_isp_util_32.c | 5 +- .../msm/camera_v2/sensor/cci/msm_cci.c | 7 +- .../msm/camera_v2/sensor/flash/msm_flash.c | 5 +- .../camera_v2/sensor/io/msm_camera_cci_i2c.c | 5 +- .../sensor/laser_led/msm_laser_led.c | 20 +++-- .../msm/camera_v2/sensor/msm_sensor.c | 44 +++++----- .../msm/camera_v2/sensor/msm_sensor_driver.c | 12 ++- .../msm/camera_v2/sensor/ois/msm_ois.c | 6 +- drivers/media/platform/msm/npu/npu_mgr.c | 4 +- drivers/media/platform/msm/vidc/venus_hfi.c | 4 +- drivers/media/usb/au0828/au0828-video.c | 6 +- drivers/media/usb/cx231xx/cx231xx-core.c | 8 +- drivers/media/usb/cx231xx/cx231xx-vbi.c | 4 +- drivers/media/usb/em28xx/em28xx-core.c | 4 +- drivers/media/usb/go7007/go7007-fw.c | 2 +- drivers/media/usb/pvrusb2/pvrusb2-hdw.c | 2 +- drivers/media/usb/pvrusb2/pvrusb2-std.c | 2 +- drivers/media/usb/stk1160/stk1160-video.c | 6 +- drivers/media/usb/stkwebcam/stk-webcam.c | 5 +- drivers/media/usb/usbtv/usbtv-video.c | 2 +- drivers/mfd/mfd-core.c | 2 +- drivers/mfd/timberdale.c | 4 +- drivers/misc/altera-stapl/altera.c | 6 +- drivers/misc/cxl/guest.c | 2 +- drivers/misc/cxl/of.c | 2 +- drivers/misc/genwqe/card_ddcb.c | 9 ++- drivers/misc/sgi-xp/xpc_main.c | 8 +- drivers/misc/sgi-xp/xpc_partition.c | 2 +- drivers/misc/sgi-xp/xpnet.c | 5 +- drivers/misc/sram.c | 2 +- drivers/mmc/core/core.c | 7 +- drivers/mtd/ar7part.c | 2 +- drivers/mtd/bcm47xxpart.c | 2 +- drivers/mtd/chips/cfi_cmdset_0001.c | 5 +- drivers/mtd/chips/cfi_cmdset_0002.c | 2 +- drivers/mtd/devices/docg3.c | 2 +- drivers/mtd/maps/physmap_of_core.c | 4 +- drivers/mtd/ofpart.c | 4 +- drivers/mtd/onenand/onenand_base.c | 5 +- drivers/mtd/parsers/parser_trx.c | 2 +- drivers/mtd/sm_ftl.c | 4 +- drivers/mtd/tests/pagetest.c | 2 +- drivers/mtd/ubi/wl.c | 2 +- drivers/net/bonding/bond_main.c | 2 +- drivers/net/can/grcan.c | 4 +- drivers/net/can/slcan.c | 2 +- drivers/net/ethernet/broadcom/bcm63xx_enet.c | 4 +- .../net/ethernet/broadcom/bnx2x/bnx2x_sriov.c | 13 +-- drivers/net/ethernet/broadcom/cnic.c | 10 +-- drivers/net/ethernet/broadcom/tg3.c | 5 +- drivers/net/ethernet/brocade/bna/bnad.c | 4 +- drivers/net/ethernet/calxeda/xgmac.c | 4 +- .../ethernet/cavium/liquidio/lio_vf_main.c | 4 +- .../ethernet/cavium/thunder/nicvf_queues.c | 4 +- .../net/ethernet/chelsio/cxgb4/cxgb4_uld.c | 4 +- drivers/net/ethernet/hisilicon/hns/hns_enet.c | 2 +- drivers/net/ethernet/intel/e1000e/netdev.c | 2 +- drivers/net/ethernet/intel/igb/igb_main.c | 7 +- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 4 +- drivers/net/ethernet/jme.c | 10 ++- drivers/net/ethernet/mellanox/mlx4/alloc.c | 4 +- drivers/net/ethernet/mellanox/mlx4/cmd.c | 15 ++-- .../net/ethernet/mellanox/mlx4/en_netdev.c | 20 +++-- drivers/net/ethernet/mellanox/mlx4/main.c | 5 +- .../ethernet/mellanox/mlx4/resource_tracker.c | 15 ++-- .../ethernet/mellanox/mlx5/core/en_clock.c | 5 +- .../net/ethernet/mellanox/mlx5/core/eswitch.c | 2 +- .../ethernet/mellanox/mlx5/core/fpga/ipsec.c | 2 +- drivers/net/ethernet/micrel/ksz884x.c | 2 +- .../net/ethernet/neterion/vxge/vxge-config.c | 8 +- .../net/ethernet/neterion/vxge/vxge-main.c | 4 +- drivers/net/ethernet/pasemi/pasemi_mac.c | 10 ++- drivers/net/ethernet/qlogic/qed/qed_debug.c | 5 +- drivers/net/ethernet/qlogic/qed/qed_dev.c | 16 ++-- .../net/ethernet/qlogic/qed/qed_init_ops.c | 4 +- drivers/net/ethernet/qlogic/qed/qed_l2.c | 2 +- .../net/ethernet/qlogic/qlcnic/qlcnic_main.c | 10 ++- .../qlogic/qlcnic/qlcnic_sriov_common.c | 8 +- .../net/ethernet/toshiba/ps3_gelic_wireless.c | 5 +- drivers/net/phy/dp83640.c | 5 +- drivers/net/slip/slip.c | 2 +- drivers/net/team/team.c | 2 +- drivers/net/usb/smsc95xx.c | 2 +- drivers/net/virtio_net.c | 8 +- drivers/net/wan/fsl_ucc_hdlc.c | 6 +- drivers/net/wireless/ath/ath10k/htt_rx.c | 2 +- drivers/net/wireless/ath/ath10k/wmi-tlv.c | 2 +- drivers/net/wireless/ath/ath6kl/cfg80211.c | 2 +- drivers/net/wireless/ath/carl9170/main.c | 7 +- drivers/net/wireless/broadcom/b43/phy_n.c | 2 +- .../net/wireless/broadcom/b43legacy/main.c | 4 +- .../broadcom/brcm80211/brcmfmac/msgbuf.c | 5 +- .../broadcom/brcm80211/brcmfmac/p2p.c | 2 +- .../broadcom/brcm80211/brcmsmac/main.c | 7 +- drivers/net/wireless/intel/iwlegacy/common.c | 13 +-- drivers/net/wireless/intel/iwlwifi/mvm/scan.c | 2 +- drivers/net/wireless/intersil/p54/eeprom.c | 12 +-- .../net/wireless/intersil/prism54/oid_mgt.c | 2 +- .../wireless/marvell/mwifiex/11n_rxreorder.c | 4 +- drivers/net/wireless/marvell/mwifiex/sdio.c | 9 ++- .../net/wireless/quantenna/qtnfmac/commands.c | 5 +- .../net/wireless/ralink/rt2x00/rt2x00debug.c | 2 +- drivers/net/wireless/realtek/rtlwifi/efuse.c | 8 +- drivers/net/wireless/realtek/rtlwifi/usb.c | 2 +- drivers/net/wireless/st/cw1200/queue.c | 10 +-- drivers/net/wireless/st/cw1200/scan.c | 6 +- drivers/nvmem/rockchip-efuse.c | 3 +- drivers/nvmem/sunxi_sid.c | 2 +- drivers/of/platform.c | 2 +- drivers/of/unittest.c | 2 +- drivers/pci/host/pci-msm.c | 5 +- drivers/pci/msi.c | 4 +- drivers/pci/pci-sysfs.c | 2 +- drivers/pcmcia/pd6729.c | 2 +- drivers/pinctrl/bcm/pinctrl-bcm2835.c | 4 +- drivers/pinctrl/freescale/pinctrl-mxs.c | 2 +- drivers/pinctrl/pinctrl-lantiq.c | 3 +- drivers/pinctrl/samsung/pinctrl-exynos5440.c | 4 +- drivers/pinctrl/sirf/pinctrl-sirf.c | 2 +- drivers/pinctrl/spear/pinctrl-spear.c | 2 +- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 2 +- drivers/pinctrl/vt8500/pinctrl-wmt.c | 2 +- drivers/platform/chrome/cros_ec_dev.c | 7 +- drivers/platform/msm/ipa/ipa_rm_peers_list.c | 5 +- .../msm/ipa/ipa_v3/ethernet/ipa_eth_net.c | 4 +- drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c | 4 +- drivers/platform/msm/ipa/ipa_v3/ipa_dp.c | 2 +- drivers/platform/msm/ipa/ipa_v3/ipa_utils.c | 2 +- drivers/platform/msm/ipa/test/ipa_test_dma.c | 5 +- .../platform/msm/ipa/test/ipa_test_hw_stats.c | 10 ++- drivers/platform/msm/qcom-geni-se.c | 5 +- drivers/platform/x86/alienware-wmi.c | 6 +- drivers/platform/x86/intel_ips.c | 12 +-- drivers/platform/x86/panasonic-laptop.c | 2 +- drivers/platform/x86/thinkpad_acpi.c | 2 +- drivers/power/supply/wm97xx_battery.c | 2 +- drivers/power/supply/z2_battery.c | 2 +- drivers/powercap/powercap_sys.c | 9 ++- drivers/rapidio/rio-scan.c | 5 +- drivers/regulator/cpr-regulator.c | 25 +++--- drivers/regulator/s2mps11.c | 2 +- drivers/s390/block/dcssblk.c | 6 +- drivers/s390/char/keyboard.c | 2 +- drivers/s390/char/vmur.c | 2 +- drivers/s390/char/zcore.c | 2 +- drivers/s390/cio/qdio_setup.c | 2 +- drivers/s390/cio/qdio_thinint.c | 5 +- drivers/s390/net/ctcm_main.c | 2 +- drivers/s390/net/qeth_core_main.c | 26 +++--- drivers/scsi/BusLogic.c | 2 +- drivers/scsi/aacraid/linit.c | 4 +- drivers/scsi/aic7xxx/aic7xxx_core.c | 4 +- drivers/scsi/aic94xx/aic94xx_hwi.c | 5 +- drivers/scsi/aic94xx/aic94xx_init.c | 2 +- drivers/scsi/be2iscsi/be_main.c | 37 +++++---- drivers/scsi/bfa/bfad_attr.c | 2 +- drivers/scsi/bfa/bfad_bsg.c | 4 +- drivers/scsi/bnx2fc/bnx2fc_fcoe.c | 2 +- drivers/scsi/bnx2fc/bnx2fc_io.c | 8 +- drivers/scsi/csiostor/csio_wr.c | 4 +- drivers/scsi/esas2r/esas2r_init.c | 11 +-- drivers/scsi/hpsa.c | 22 ++--- drivers/scsi/ipr.c | 10 ++- drivers/scsi/libsas/sas_expander.c | 2 +- drivers/scsi/lpfc/lpfc_init.c | 7 +- drivers/scsi/lpfc/lpfc_sli.c | 50 +++++------- drivers/scsi/lpfc/lpfc_vport.c | 2 +- drivers/scsi/megaraid/megaraid_sas_base.c | 8 +- drivers/scsi/megaraid/megaraid_sas_fusion.c | 2 +- drivers/scsi/osst.c | 2 +- drivers/scsi/pm8001/pm8001_ctl.c | 2 +- drivers/scsi/pmcraid.c | 5 +- drivers/scsi/qedi/qedi_main.c | 2 +- drivers/scsi/qla2xxx/qla_init.c | 10 ++- drivers/scsi/qla2xxx/qla_isr.c | 5 +- drivers/scsi/qla2xxx/qla_os.c | 14 ++-- drivers/scsi/qla2xxx/qla_target.c | 10 ++- drivers/scsi/scsi_debug.c | 2 +- drivers/scsi/ses.c | 2 +- drivers/scsi/sg.c | 2 +- drivers/scsi/smartpqi/smartpqi_init.c | 5 +- drivers/scsi/st.c | 2 +- drivers/scsi/ufs/ufs-debugfs.c | 8 +- drivers/scsi/ufs/ufshcd.c | 5 +- drivers/sh/clk/cpg.c | 2 +- drivers/sh/intc/core.c | 10 +-- drivers/sh/maple/maple.c | 2 +- drivers/slimbus/slim-msm-ctrl.c | 8 +- drivers/slimbus/slim-msm-ngd.c | 2 +- drivers/soc/qcom/msm_bus/msm_bus_arb_adhoc.c | 5 +- drivers/soc/qcom/msm_bus/msm_bus_arb_rpmh.c | 5 +- drivers/soc/qcom/rpmh.c | 4 +- drivers/soc/qcom/spcom.c | 2 +- drivers/staging/ccree/ssi_sysfs.c | 2 +- .../lustre/lustre/obdclass/cl_object.c | 2 +- .../pci/atomisp2/atomisp_compat_css20.c | 4 +- .../pci/atomisp2/css2400/sh_css_firmware.c | 3 +- drivers/staging/rtlwifi/efuse.c | 8 +- .../staging/unisys/visorhba/visorhba_main.c | 2 +- drivers/target/target_core_transport.c | 2 +- .../int340x_thermal/acpi_thermal_rel.c | 4 +- .../int340x_thermal/int340x_thermal_zone.c | 6 +- drivers/thermal/of-thermal.c | 4 +- drivers/thermal/qcom/lmh_dbg.c | 4 +- drivers/thermal/x86_pkg_temp_thermal.c | 3 +- drivers/tty/ehv_bytechan.c | 2 +- drivers/tty/goldfish.c | 5 +- drivers/tty/hvc/hvc_iucv.c | 2 +- drivers/tty/serial/pch_uart.c | 2 +- drivers/tty/serial/serial_core.c | 2 +- drivers/tty/serial/sunsab.c | 5 +- drivers/uio/uio_pruss.c | 2 +- drivers/usb/core/hub.c | 2 +- drivers/usb/dwc2/hcd.c | 11 +-- drivers/usb/gadget/function/f_cdev.c | 2 +- drivers/usb/gadget/udc/bdc/bdc_ep.c | 6 +- drivers/usb/gadget/udc/fsl_udc_core.c | 2 +- drivers/usb/host/ehci-sched.c | 5 +- drivers/usb/host/imx21-hcd.c | 4 +- drivers/usb/host/xhci-mem.c | 15 ++-- drivers/usb/misc/diag_bridge.c | 2 +- drivers/usb/mon/mon_bin.c | 3 +- drivers/usb/renesas_usbhs/mod_gadget.c | 2 +- drivers/usb/renesas_usbhs/pipe.c | 3 +- drivers/usb/wusbcore/wa-rpipe.c | 3 +- drivers/vhost/scsi.c | 15 ++-- drivers/video/console/sticore.c | 2 +- drivers/video/fbdev/bfin_adv7393fb.c | 2 +- drivers/video/fbdev/broadsheetfb.c | 2 +- drivers/video/fbdev/core/fbmon.c | 2 +- drivers/video/fbdev/igafb.c | 2 +- drivers/video/fbdev/mmp/fb/mmpfb.c | 4 +- drivers/video/fbdev/msm/mdss_mdp_pp.c | 5 +- drivers/video/fbdev/msm/mdss_mdp_pp_v1_7.c | 7 +- .../video/fbdev/omap2/omapfb/dss/manager.c | 4 +- .../video/fbdev/omap2/omapfb/dss/overlay.c | 4 +- drivers/video/fbdev/uvesafb.c | 7 +- drivers/video/of_display_timing.c | 5 +- drivers/virt/fsl_hypervisor.c | 2 +- drivers/virtio/virtio_pci_common.c | 2 +- drivers/vservices/devio.c | 4 +- drivers/xen/arm-device.c | 6 +- fs/btrfs/check-integrity.c | 3 +- fs/ext4/extents.c | 8 +- fs/ext4/hash.c | 2 +- fs/nfs/flexfilelayout/flexfilelayout.c | 2 +- fs/nfs/flexfilelayout/flexfilelayoutdev.c | 3 +- fs/nfsd/export.c | 5 +- fs/ocfs2/journal.c | 2 +- fs/ocfs2/sysfile.c | 4 +- fs/overlayfs/namei.c | 2 +- fs/proc/proc_sysctl.c | 2 +- fs/reiserfs/inode.c | 3 +- kernel/debug/kdb/kdb_main.c | 2 +- kernel/events/uprobes.c | 3 +- kernel/locking/lockdep.c | 2 +- kernel/locking/locktorture.c | 6 +- kernel/rcu/rcutorture.c | 8 +- kernel/sched/fair.c | 4 +- kernel/sched/rt.c | 4 +- kernel/sysctl.c | 3 +- kernel/trace/ftrace.c | 2 +- kernel/trace/trace.c | 3 +- kernel/workqueue.c | 2 +- lib/lru_cache.c | 2 +- lib/mpi/mpiutil.c | 2 +- mm/slab.c | 3 +- mm/slub.c | 7 +- net/bridge/br_multicast.c | 2 +- net/can/bcm.c | 3 +- net/core/ethtool.c | 4 +- net/ieee802154/nl-phy.c | 2 +- net/ipv4/fib_frontend.c | 2 +- net/ipv4/route.c | 2 +- net/ipv6/icmp.c | 2 +- net/ipv6/route.c | 2 +- net/mac80211/chan.c | 2 +- net/mac80211/rc80211_minstrel.c | 2 +- net/mac80211/rc80211_minstrel_ht.c | 2 +- net/mac80211/scan.c | 2 +- net/mac80211/util.c | 5 +- net/netfilter/nfnetlink_cthelper.c | 5 +- net/netrom/af_netrom.c | 2 +- net/openvswitch/vport.c | 2 +- net/rds/ib.c | 3 +- net/rose/af_rose.c | 3 +- net/sched/cls_u32.c | 3 +- net/sctp/auth.c | 5 +- net/smc/smc_wr.c | 6 +- net/sunrpc/auth_gss/gss_rpc_upcall.c | 2 +- net/sunrpc/cache.c | 2 +- net/wireless/nl80211.c | 4 +- security/apparmor/policy_unpack.c | 2 +- security/selinux/ss/services.c | 2 +- sound/firewire/fireface/ff-protocol-ff400.c | 2 +- sound/oss/swarm_cs4297a.c | 3 +- sound/pci/ctxfi/ctatc.c | 18 ++--- sound/pci/ctxfi/ctdaio.c | 3 +- sound/pci/ctxfi/ctmixer.c | 5 +- sound/pci/ctxfi/ctsrc.c | 2 +- sound/pci/hda/patch_ca0132.c | 4 +- sound/soc/blackfin/bf5xx-sport.c | 2 +- sound/soc/codecs/wm_adsp.c | 2 +- sound/soc/intel/common/sst-ipc.c | 4 +- sound/soc/soc-core.c | 4 +- sound/soc/soc-dapm.c | 2 +- sound/soc/soc-topology.c | 2 +- sound/usb/6fire/pcm.c | 10 ++- sound/usb/line6/capture.c | 4 +- sound/usb/line6/playback.c | 4 +- techpack/audio/4.0/asoc/codecs/wcd9xxx-core.c | 4 +- techpack/audio/4.0/asoc/msm-dai-q6-v2.c | 12 +-- techpack/audio/4.0/asoc/msm-lsm-client.c | 2 +- techpack/audio/4.0/dsp/q6asm.c | 2 +- techpack/audio/4.0/dsp/q6lsm.c | 5 +- techpack/audio/4.0/dsp/q6usm.c | 2 +- techpack/audio/asoc/codecs/wcd9xxx-core.c | 4 +- techpack/audio/asoc/msm-dai-q6-v2.c | 12 +-- techpack/audio/asoc/msm-lsm-client.c | 2 +- techpack/audio/dsp/elliptic/elliptic.c | 2 +- techpack/audio/dsp/q6asm.c | 2 +- techpack/audio/dsp/q6lsm.c | 5 +- techpack/audio/dsp/q6usm.c | 2 +- .../drivers/emac-dwc-eqos/DWC_ETH_QOS_desc.c | 36 ++++++--- 569 files changed, 1566 insertions(+), 1306 deletions(-) diff --git a/arch/arm/mach-footbridge/dc21285.c b/arch/arm/mach-footbridge/dc21285.c index 96a3d73ef4bf..7460f2b73d5e 100644 --- a/arch/arm/mach-footbridge/dc21285.c +++ b/arch/arm/mach-footbridge/dc21285.c @@ -257,7 +257,7 @@ int __init dc21285_setup(int nr, struct pci_sys_data *sys) if (nr || !footbridge_cfn_mode()) return 0; - res = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL); + res = kcalloc(2, sizeof(struct resource), GFP_KERNEL); if (!res) { printk("out of memory for root bus resources"); return 0; diff --git a/arch/arm/mach-ixp4xx/common-pci.c b/arch/arm/mach-ixp4xx/common-pci.c index bcf3df59f71b..6835b17113e5 100644 --- a/arch/arm/mach-ixp4xx/common-pci.c +++ b/arch/arm/mach-ixp4xx/common-pci.c @@ -421,7 +421,7 @@ int ixp4xx_setup(int nr, struct pci_sys_data *sys) if (nr >= 1) return 0; - res = kzalloc(sizeof(*res) * 2, GFP_KERNEL); + res = kcalloc(2, sizeof(*res), GFP_KERNEL); if (res == NULL) { /* * If we're out of memory this early, something is wrong, diff --git a/arch/arm/mach-omap1/mcbsp.c b/arch/arm/mach-omap1/mcbsp.c index 8ed67f8d1762..27e22e702f96 100644 --- a/arch/arm/mach-omap1/mcbsp.c +++ b/arch/arm/mach-omap1/mcbsp.c @@ -389,7 +389,7 @@ static void omap_mcbsp_register_board_cfg(struct resource *res, int res_count, { int i; - omap_mcbsp_devices = kzalloc(size * sizeof(struct platform_device *), + omap_mcbsp_devices = kcalloc(size, sizeof(struct platform_device *), GFP_KERNEL); if (!omap_mcbsp_devices) { printk(KERN_ERR "Could not register McBSP devices\n"); diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index 6d28aa20a7d3..c77efc90eaa1 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c @@ -37,7 +37,7 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, { char *hc_name; - hc_name = kzalloc(sizeof(char) * (HSMMC_NAME_LEN + 1), GFP_KERNEL); + hc_name = kzalloc(HSMMC_NAME_LEN + 1, GFP_KERNEL); if (!hc_name) { kfree(hc_name); return -ENOMEM; diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c index acbede082b5b..7aee7443f01f 100644 --- a/arch/arm/mach-omap2/omap_device.c +++ b/arch/arm/mach-omap2/omap_device.c @@ -148,7 +148,7 @@ static int omap_device_build_from_dt(struct platform_device *pdev) return -ENODEV; } - hwmods = kzalloc(sizeof(struct omap_hwmod *) * oh_cnt, GFP_KERNEL); + hwmods = kcalloc(oh_cnt, sizeof(struct omap_hwmod *), GFP_KERNEL); if (!hwmods) { ret = -ENOMEM; goto odbfd_exit; @@ -468,7 +468,7 @@ struct omap_device *omap_device_alloc(struct platform_device *pdev, } /* Allocate resources memory to account for new resources */ - res = kzalloc(sizeof(struct resource) * res_count, GFP_KERNEL); + res = kcalloc(res_count, sizeof(struct resource), GFP_KERNEL); if (!res) goto oda_exit3; diff --git a/arch/arm/mach-omap2/prm_common.c b/arch/arm/mach-omap2/prm_common.c index 2f215facba10..8a24e36c3c05 100644 --- a/arch/arm/mach-omap2/prm_common.c +++ b/arch/arm/mach-omap2/prm_common.c @@ -288,10 +288,11 @@ int omap_prcm_register_chain_handler(struct omap_prcm_irq_setup *irq_setup) prcm_irq_setup = irq_setup; - prcm_irq_chips = kzalloc(sizeof(void *) * nr_regs, GFP_KERNEL); - prcm_irq_setup->saved_mask = kzalloc(sizeof(u32) * nr_regs, GFP_KERNEL); - prcm_irq_setup->priority_mask = kzalloc(sizeof(u32) * nr_regs, - GFP_KERNEL); + prcm_irq_chips = kcalloc(nr_regs, sizeof(void *), GFP_KERNEL); + prcm_irq_setup->saved_mask = kcalloc(nr_regs, sizeof(u32), + GFP_KERNEL); + prcm_irq_setup->priority_mask = kcalloc(nr_regs, sizeof(u32), + GFP_KERNEL); if (!prcm_irq_chips || !prcm_irq_setup->saved_mask || !prcm_irq_setup->priority_mask) diff --git a/arch/arm/mach-vexpress/spc.c b/arch/arm/mach-vexpress/spc.c index 635b0d549487..8e0a39689312 100644 --- a/arch/arm/mach-vexpress/spc.c +++ b/arch/arm/mach-vexpress/spc.c @@ -403,7 +403,7 @@ static int ve_spc_populate_opps(uint32_t cluster) uint32_t data = 0, off, ret, idx; struct ve_spc_opp *opps; - opps = kzalloc(sizeof(*opps) * MAX_OPPS, GFP_KERNEL); + opps = kcalloc(MAX_OPPS, sizeof(*opps), GFP_KERNEL); if (!opps) return -ENOMEM; diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 9498cdfdbfe6..37b558a93473 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -2398,8 +2398,8 @@ iommu_init_mapping(struct device *dev, struct dma_iommu_mapping *mapping) } mapping->bitmap_size = bitmap_size; - mapping->bitmaps = kzalloc(extensions * sizeof(unsigned long *), - GFP_KERNEL); + mapping->bitmaps = kcalloc(extensions, sizeof(unsigned long *), + GFP_KERNEL); if (!mapping->bitmaps) return -ENOMEM; diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index 1e460b4ee3b9..094e33a5f9f2 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -1324,8 +1324,9 @@ static int omap_system_dma_probe(struct platform_device *pdev) if (dma_omap2plus()) { - dma_linked_lch = kzalloc(sizeof(struct dma_link_info) * - dma_lch_count, GFP_KERNEL); + dma_linked_lch = kcalloc(dma_lch_count, + sizeof(struct dma_link_info), + GFP_KERNEL); if (!dma_linked_lch) { ret = -ENOMEM; goto exit_dma_lch_fail; diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c index 092046704cbc..20cf50f0dac3 100644 --- a/arch/arm64/kernel/armv8_deprecated.c +++ b/arch/arm64/kernel/armv8_deprecated.c @@ -243,8 +243,8 @@ static void __init register_insn_emulation_sysctl(struct ctl_table *table) struct insn_emulation *insn; struct ctl_table *insns_sysctl, *sysctl; - insns_sysctl = kzalloc(sizeof(*sysctl) * (nr_insn_emulated + 1), - GFP_KERNEL); + insns_sysctl = kcalloc(nr_insn_emulated + 1, sizeof(*sysctl), + GFP_KERNEL); raw_spin_lock_irqsave(&insn_emulation_lock, flags); list_for_each_entry(insn, &insn_emulation, node) { diff --git a/arch/arm64/mm/context.c b/arch/arm64/mm/context.c index 9284788733d6..c5af439c172d 100644 --- a/arch/arm64/mm/context.c +++ b/arch/arm64/mm/context.c @@ -256,7 +256,7 @@ static int asids_init(void) */ WARN_ON(NUM_USER_ASIDS - 1 <= num_possible_cpus()); atomic64_set(&asid_generation, ASID_FIRST_VERSION); - asid_map = kzalloc(BITS_TO_LONGS(NUM_USER_ASIDS) * sizeof(*asid_map), + asid_map = kcalloc(BITS_TO_LONGS(NUM_USER_ASIDS), sizeof(*asid_map), GFP_KERNEL); if (!asid_map) panic("Failed to allocate bitmap for %lu ASIDs\n", diff --git a/arch/ia64/kernel/topology.c b/arch/ia64/kernel/topology.c index d76529cbff20..9b820f7a6a98 100644 --- a/arch/ia64/kernel/topology.c +++ b/arch/ia64/kernel/topology.c @@ -85,7 +85,7 @@ static int __init topology_init(void) } #endif - sysfs_cpus = kzalloc(sizeof(struct ia64_cpu) * NR_CPUS, GFP_KERNEL); + sysfs_cpus = kcalloc(NR_CPUS, sizeof(struct ia64_cpu), GFP_KERNEL); if (!sysfs_cpus) panic("kzalloc in topology_init failed - NR_CPUS too big?"); @@ -319,8 +319,8 @@ static int cpu_cache_sysfs_init(unsigned int cpu) return -1; } - this_cache=kzalloc(sizeof(struct cache_info)*unique_caches, - GFP_KERNEL); + this_cache=kcalloc(unique_caches, sizeof(struct cache_info), + GFP_KERNEL); if (this_cache == NULL) return -ENOMEM; diff --git a/arch/ia64/sn/kernel/io_common.c b/arch/ia64/sn/kernel/io_common.c index 11f2275570fb..5b009d54d3df 100644 --- a/arch/ia64/sn/kernel/io_common.c +++ b/arch/ia64/sn/kernel/io_common.c @@ -132,7 +132,7 @@ static s64 sn_device_fixup_war(u64 nasid, u64 widget, int device, printk_once(KERN_WARNING "PROM version < 4.50 -- implementing old PROM flush WAR\n"); - war_list = kzalloc(DEV_PER_WIDGET * sizeof(*war_list), GFP_KERNEL); + war_list = kcalloc(DEV_PER_WIDGET, sizeof(*war_list), GFP_KERNEL); BUG_ON(!war_list); SAL_CALL_NOLOCK(isrv, SN_SAL_IOIF_GET_WIDGET_DMAFLUSH_LIST, diff --git a/arch/ia64/sn/pci/pcibr/pcibr_provider.c b/arch/ia64/sn/pci/pcibr/pcibr_provider.c index 8dbbef4a4f47..7195df1da121 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_provider.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_provider.c @@ -184,7 +184,7 @@ pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont /* Setup the PMU ATE map */ soft->pbi_int_ate_resource.lowest_free_index = 0; soft->pbi_int_ate_resource.ate = - kzalloc(soft->pbi_int_ate_size * sizeof(u64), GFP_KERNEL); + kcalloc(soft->pbi_int_ate_size, sizeof(u64), GFP_KERNEL); if (!soft->pbi_int_ate_resource.ate) { kfree(soft); diff --git a/arch/mips/alchemy/common/clock.c b/arch/mips/alchemy/common/clock.c index a83c7b7e2eb1..afebd7b99299 100644 --- a/arch/mips/alchemy/common/clock.c +++ b/arch/mips/alchemy/common/clock.c @@ -985,7 +985,7 @@ static int __init alchemy_clk_setup_imux(int ctype) return -ENODEV; } - a = kzalloc((sizeof(*a)) * 6, GFP_KERNEL); + a = kcalloc(6, sizeof(*a), GFP_KERNEL); if (!a) return -ENOMEM; diff --git a/arch/mips/alchemy/common/dbdma.c b/arch/mips/alchemy/common/dbdma.c index 067a7bd17182..c55a02422b38 100644 --- a/arch/mips/alchemy/common/dbdma.c +++ b/arch/mips/alchemy/common/dbdma.c @@ -1050,7 +1050,7 @@ static int __init dbdma_setup(unsigned int irq, dbdev_tab_t *idtable) { int ret; - dbdev_tab = kzalloc(sizeof(dbdev_tab_t) * DBDEV_TAB_SIZE, GFP_KERNEL); + dbdev_tab = kcalloc(DBDEV_TAB_SIZE, sizeof(dbdev_tab_t), GFP_KERNEL); if (!dbdev_tab) return -ENOMEM; diff --git a/arch/mips/alchemy/common/platform.c b/arch/mips/alchemy/common/platform.c index d77a64f4c78b..1454d9f6ab2d 100644 --- a/arch/mips/alchemy/common/platform.c +++ b/arch/mips/alchemy/common/platform.c @@ -115,7 +115,7 @@ static void __init alchemy_setup_uarts(int ctype) uartclk = clk_get_rate(clk); clk_put(clk); - ports = kzalloc(s * (c + 1), GFP_KERNEL); + ports = kcalloc(s, (c + 1), GFP_KERNEL); if (!ports) { printk(KERN_INFO "Alchemy: no memory for UART data\n"); return; @@ -198,7 +198,7 @@ static unsigned long alchemy_ehci_data[][2] __initdata = { static int __init _new_usbres(struct resource **r, struct platform_device **d) { - *r = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL); + *r = kcalloc(2, sizeof(struct resource), GFP_KERNEL); if (!*r) return -ENOMEM; *d = kzalloc(sizeof(struct platform_device), GFP_KERNEL); diff --git a/arch/mips/alchemy/devboards/platform.c b/arch/mips/alchemy/devboards/platform.c index 4640edab207c..203854ddd1bb 100644 --- a/arch/mips/alchemy/devboards/platform.c +++ b/arch/mips/alchemy/devboards/platform.c @@ -103,7 +103,7 @@ int __init db1x_register_pcmcia_socket(phys_addr_t pcmcia_attr_start, if (stschg_irq) cnt++; - sr = kzalloc(sizeof(struct resource) * cnt, GFP_KERNEL); + sr = kcalloc(cnt, sizeof(struct resource), GFP_KERNEL); if (!sr) return -ENOMEM; @@ -178,7 +178,7 @@ int __init db1x_register_norflash(unsigned long size, int width, return -EINVAL; ret = -ENOMEM; - parts = kzalloc(sizeof(struct mtd_partition) * 5, GFP_KERNEL); + parts = kcalloc(5, sizeof(struct mtd_partition), GFP_KERNEL); if (!parts) goto out; diff --git a/arch/mips/bmips/dma.c b/arch/mips/bmips/dma.c index 04790f4e1805..6dec30842b2f 100644 --- a/arch/mips/bmips/dma.c +++ b/arch/mips/bmips/dma.c @@ -94,7 +94,7 @@ static int __init bmips_init_dma_ranges(void) goto out_bad; /* add a dummy (zero) entry at the end as a sentinel */ - bmips_dma_ranges = kzalloc(sizeof(struct bmips_dma_range) * (len + 1), + bmips_dma_ranges = kcalloc(len + 1, sizeof(struct bmips_dma_range), GFP_KERNEL); if (!bmips_dma_ranges) goto out_bad; diff --git a/arch/mips/txx9/rbtx4939/setup.c b/arch/mips/txx9/rbtx4939/setup.c index fd26fadc8617..ef29a9c2ffd6 100644 --- a/arch/mips/txx9/rbtx4939/setup.c +++ b/arch/mips/txx9/rbtx4939/setup.c @@ -219,7 +219,7 @@ static int __init rbtx4939_led_probe(struct platform_device *pdev) "nand-disk", }; - leds_data = kzalloc(sizeof(*leds_data) * RBTX4939_MAX_7SEGLEDS, + leds_data = kcalloc(RBTX4939_MAX_7SEGLEDS, sizeof(*leds_data), GFP_KERNEL); if (!leds_data) return -ENOMEM; diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c index 22b01a3962f0..c4f59971e515 100644 --- a/arch/powerpc/kernel/vdso.c +++ b/arch/powerpc/kernel/vdso.c @@ -789,7 +789,7 @@ static int __init vdso_init(void) #ifdef CONFIG_VDSO32 /* Make sure pages are in the correct state */ - vdso32_pagelist = kzalloc(sizeof(struct page *) * (vdso32_pages + 2), + vdso32_pagelist = kcalloc(vdso32_pages + 2, sizeof(struct page *), GFP_KERNEL); BUG_ON(vdso32_pagelist == NULL); for (i = 0; i < vdso32_pages; i++) { @@ -803,7 +803,7 @@ static int __init vdso_init(void) #endif #ifdef CONFIG_PPC64 - vdso64_pagelist = kzalloc(sizeof(struct page *) * (vdso64_pages + 2), + vdso64_pagelist = kcalloc(vdso64_pages + 2, sizeof(struct page *), GFP_KERNEL); BUG_ON(vdso64_pagelist == NULL); for (i = 0; i < vdso64_pages; i++) { diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 417ea6db7b1d..d378fe1bed4f 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -1387,7 +1387,7 @@ int numa_update_cpu_topology(bool cpus_locked) if (!weight) return 0; - updates = kzalloc(weight * (sizeof(*updates)), GFP_KERNEL); + updates = kcalloc(weight, sizeof(*updates), GFP_KERNEL); if (!updates) return 0; diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c index a9636d8cba15..5b061fc81df3 100644 --- a/arch/powerpc/net/bpf_jit_comp.c +++ b/arch/powerpc/net/bpf_jit_comp.c @@ -566,7 +566,7 @@ void bpf_jit_compile(struct bpf_prog *fp) if (!bpf_jit_enable) return; - addrs = kzalloc((flen+1) * sizeof(*addrs), GFP_KERNEL); + addrs = kcalloc(flen + 1, sizeof(*addrs), GFP_KERNEL); if (addrs == NULL) return; diff --git a/arch/powerpc/net/bpf_jit_comp64.c b/arch/powerpc/net/bpf_jit_comp64.c index df15e4463f67..93ec56fbe0b8 100644 --- a/arch/powerpc/net/bpf_jit_comp64.c +++ b/arch/powerpc/net/bpf_jit_comp64.c @@ -999,7 +999,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp) } flen = fp->len; - addrs = kzalloc((flen+1) * sizeof(*addrs), GFP_KERNEL); + addrs = kcalloc(flen + 1, sizeof(*addrs), GFP_KERNEL); if (addrs == NULL) { fp = org_fp; goto out; diff --git a/arch/powerpc/oprofile/cell/spu_profiler.c b/arch/powerpc/oprofile/cell/spu_profiler.c index 5182f2936af2..4e099e556645 100644 --- a/arch/powerpc/oprofile/cell/spu_profiler.c +++ b/arch/powerpc/oprofile/cell/spu_profiler.c @@ -210,8 +210,8 @@ int start_spu_profiling_cycles(unsigned int cycles_reset) timer.function = profile_spus; /* Allocate arrays for collecting SPU PC samples */ - samples = kzalloc(SPUS_PER_NODE * - TRACE_ARRAY_SIZE * sizeof(u32), GFP_KERNEL); + samples = kcalloc(SPUS_PER_NODE * TRACE_ARRAY_SIZE, sizeof(u32), + GFP_KERNEL); if (!samples) return -ENOMEM; diff --git a/arch/powerpc/platforms/4xx/pci.c b/arch/powerpc/platforms/4xx/pci.c index 256943af58aa..2f237027fdcc 100644 --- a/arch/powerpc/platforms/4xx/pci.c +++ b/arch/powerpc/platforms/4xx/pci.c @@ -1447,7 +1447,7 @@ static int __init ppc4xx_pciex_check_core_init(struct device_node *np) count = ppc4xx_pciex_hwops->core_init(np); if (count > 0) { ppc4xx_pciex_ports = - kzalloc(count * sizeof(struct ppc4xx_pciex_port), + kcalloc(count, sizeof(struct ppc4xx_pciex_port), GFP_KERNEL); if (ppc4xx_pciex_ports) { ppc4xx_pciex_port_count = count; diff --git a/arch/powerpc/platforms/powernv/opal-async.c b/arch/powerpc/platforms/powernv/opal-async.c index 45b3feb8aa2f..64b1c863206c 100644 --- a/arch/powerpc/platforms/powernv/opal-async.c +++ b/arch/powerpc/platforms/powernv/opal-async.c @@ -189,9 +189,9 @@ int __init opal_async_comp_init(void) goto out_opal_node; } - opal_async_responses = kzalloc( - sizeof(*opal_async_responses) * opal_max_async_tokens, - GFP_KERNEL); + opal_async_responses = kcalloc(opal_max_async_tokens, + sizeof(*opal_async_responses), + GFP_KERNEL); if (!opal_async_responses) { pr_err("%s: Out of memory, failed to do asynchronous " "completion init\n", __func__); diff --git a/arch/powerpc/platforms/powernv/opal-sysparam.c b/arch/powerpc/platforms/powernv/opal-sysparam.c index 23fb6647dced..c0b5cfd9e9b0 100644 --- a/arch/powerpc/platforms/powernv/opal-sysparam.c +++ b/arch/powerpc/platforms/powernv/opal-sysparam.c @@ -198,21 +198,21 @@ void __init opal_sys_param_init(void) goto out_param_buf; } - id = kzalloc(sizeof(*id) * count, GFP_KERNEL); + id = kcalloc(count, sizeof(*id), GFP_KERNEL); if (!id) { pr_err("SYSPARAM: Failed to allocate memory to read parameter " "id\n"); goto out_param_buf; } - size = kzalloc(sizeof(*size) * count, GFP_KERNEL); + size = kcalloc(count, sizeof(*size), GFP_KERNEL); if (!size) { pr_err("SYSPARAM: Failed to allocate memory to read parameter " "size\n"); goto out_free_id; } - perm = kzalloc(sizeof(*perm) * count, GFP_KERNEL); + perm = kcalloc(count, sizeof(*perm), GFP_KERNEL); if (!perm) { pr_err("SYSPARAM: Failed to allocate memory to read supported " "action on the parameter"); @@ -235,7 +235,7 @@ void __init opal_sys_param_init(void) goto out_free_perm; } - attr = kzalloc(sizeof(*attr) * count, GFP_KERNEL); + attr = kcalloc(count, sizeof(*attr), GFP_KERNEL); if (!attr) { pr_err("SYSPARAM: Failed to allocate memory for parameter " "attributes\n"); diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 62e1b4321b58..835348fc42c3 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -544,7 +544,7 @@ static void __init mpic_scan_ht_pics(struct mpic *mpic) printk(KERN_INFO "mpic: Setting up HT PICs workarounds for U3/U4\n"); /* Allocate fixups array */ - mpic->fixups = kzalloc(128 * sizeof(*mpic->fixups), GFP_KERNEL); + mpic->fixups = kcalloc(128, sizeof(*mpic->fixups), GFP_KERNEL); BUG_ON(mpic->fixups == NULL); /* Init spinlock */ @@ -1326,7 +1326,7 @@ struct mpic * __init mpic_alloc(struct device_node *node, if (psrc) { /* Allocate a bitmap with one bit per interrupt */ unsigned int mapsize = BITS_TO_LONGS(intvec_top + 1); - mpic->protected = kzalloc(mapsize*sizeof(long), GFP_KERNEL); + mpic->protected = kcalloc(mapsize, sizeof(long), GFP_KERNEL); BUG_ON(mpic->protected == NULL); for (i = 0; i < psize/sizeof(u32); i++) { if (psrc[i] > intvec_top) diff --git a/arch/powerpc/sysdev/xive/native.c b/arch/powerpc/sysdev/xive/native.c index 30cdcbfa1c04..a0d003e8daf3 100644 --- a/arch/powerpc/sysdev/xive/native.c +++ b/arch/powerpc/sysdev/xive/native.c @@ -499,7 +499,7 @@ static bool xive_parse_provisioning(struct device_node *np) if (rc == 0) return true; - xive_provision_chips = kzalloc(4 * xive_provision_chip_count, + xive_provision_chips = kcalloc(4, xive_provision_chip_count, GFP_KERNEL); if (WARN_ON(!xive_provision_chips)) return false; diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c index ef3fb1b9201f..f748b666e519 100644 --- a/arch/s390/appldata/appldata_base.c +++ b/arch/s390/appldata/appldata_base.c @@ -390,7 +390,7 @@ int appldata_register_ops(struct appldata_ops *ops) if (ops->size > APPLDATA_MAX_REC_SIZE) return -EINVAL; - ops->ctl_table = kzalloc(4 * sizeof(struct ctl_table), GFP_KERNEL); + ops->ctl_table = kcalloc(4, sizeof(struct ctl_table), GFP_KERNEL); if (!ops->ctl_table) return -ENOMEM; diff --git a/arch/s390/kernel/vdso.c b/arch/s390/kernel/vdso.c index eacda05b45d7..bfa5a0269139 100644 --- a/arch/s390/kernel/vdso.c +++ b/arch/s390/kernel/vdso.c @@ -311,7 +311,7 @@ static int __init vdso_init(void) + PAGE_SIZE - 1) >> PAGE_SHIFT) + 1; /* Make sure pages are in the correct state */ - vdso32_pagelist = kzalloc(sizeof(struct page *) * (vdso32_pages + 1), + vdso32_pagelist = kcalloc(vdso32_pages + 1, sizeof(struct page *), GFP_KERNEL); BUG_ON(vdso32_pagelist == NULL); for (i = 0; i < vdso32_pages - 1; i++) { @@ -329,7 +329,7 @@ static int __init vdso_init(void) + PAGE_SIZE - 1) >> PAGE_SHIFT) + 1; /* Make sure pages are in the correct state */ - vdso64_pagelist = kzalloc(sizeof(struct page *) * (vdso64_pages + 1), + vdso64_pagelist = kcalloc(vdso64_pages + 1, sizeof(struct page *), GFP_KERNEL); BUG_ON(vdso64_pagelist == NULL); for (i = 0; i < vdso64_pages - 1; i++) { diff --git a/arch/sh/drivers/dma/dmabrg.c b/arch/sh/drivers/dma/dmabrg.c index c0dd904483c7..e5a57a109d6c 100644 --- a/arch/sh/drivers/dma/dmabrg.c +++ b/arch/sh/drivers/dma/dmabrg.c @@ -154,7 +154,7 @@ static int __init dmabrg_init(void) unsigned long or; int ret; - dmabrg_handlers = kzalloc(10 * sizeof(struct dmabrg_handler), + dmabrg_handlers = kcalloc(10, sizeof(struct dmabrg_handler), GFP_KERNEL); if (!dmabrg_handlers) return -ENOMEM; diff --git a/arch/sh/drivers/pci/pcie-sh7786.c b/arch/sh/drivers/pci/pcie-sh7786.c index 0167a7352719..ab4c765846e2 100644 --- a/arch/sh/drivers/pci/pcie-sh7786.c +++ b/arch/sh/drivers/pci/pcie-sh7786.c @@ -539,7 +539,7 @@ static int __init sh7786_pcie_init(void) if (unlikely(nr_ports == 0)) return -ENODEV; - sh7786_pcie_ports = kzalloc(nr_ports * sizeof(struct sh7786_pcie_port), + sh7786_pcie_ports = kcalloc(nr_ports, sizeof(struct sh7786_pcie_port), GFP_KERNEL); if (unlikely(!sh7786_pcie_ports)) return -ENOMEM; diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c index fb228d16b1d7..a9de37a60863 100644 --- a/arch/sparc/kernel/sys_sparc_64.c +++ b/arch/sparc/kernel/sys_sparc_64.c @@ -577,7 +577,8 @@ SYSCALL_DEFINE5(utrap_install, utrap_entry_t, type, } if (!current_thread_info()->utraps) { current_thread_info()->utraps = - kzalloc((UT_TRAP_INSTRUCTION_31+1)*sizeof(long), GFP_KERNEL); + kcalloc(UT_TRAP_INSTRUCTION_31 + 1, sizeof(long), + GFP_KERNEL); if (!current_thread_info()->utraps) return -ENOMEM; current_thread_info()->utraps[0] = 1; diff --git a/arch/tile/kernel/vdso.c b/arch/tile/kernel/vdso.c index 5bc51d7dfdcb..029ad21b09ee 100644 --- a/arch/tile/kernel/vdso.c +++ b/arch/tile/kernel/vdso.c @@ -54,7 +54,7 @@ static struct page **vdso_setup(void *vdso_kbase, unsigned int pages) int i; struct page **pagelist; - pagelist = kzalloc(sizeof(struct page *) * (pages + 1), GFP_KERNEL); + pagelist = kcalloc(pages + 1, sizeof(struct page *), GFP_KERNEL); BUG_ON(pagelist == NULL); for (i = 0; i < pages - 1; i++) { struct page *pg = virt_to_page(vdso_kbase + i*PAGE_SIZE); diff --git a/arch/x86/events/amd/iommu.c b/arch/x86/events/amd/iommu.c index 3641e24fdac5..263cceb97f2f 100644 --- a/arch/x86/events/amd/iommu.c +++ b/arch/x86/events/amd/iommu.c @@ -387,7 +387,7 @@ static __init int _init_events_attrs(void) while (amd_iommu_v2_event_descs[i].attr.attr.name) i++; - attrs = kzalloc(sizeof(struct attribute **) * (i + 1), GFP_KERNEL); + attrs = kcalloc(i + 1, sizeof(struct attribute **), GFP_KERNEL); if (!attrs) return -ENOMEM; diff --git a/arch/x86/events/intel/uncore.c b/arch/x86/events/intel/uncore.c index c56cb37b88e3..462bd189672d 100644 --- a/arch/x86/events/intel/uncore.c +++ b/arch/x86/events/intel/uncore.c @@ -810,7 +810,7 @@ static int __init uncore_type_init(struct intel_uncore_type *type, bool setid) size_t size; int i, j; - pmus = kzalloc(sizeof(*pmus) * type->num_boxes, GFP_KERNEL); + pmus = kcalloc(type->num_boxes, sizeof(*pmus), GFP_KERNEL); if (!pmus) return -ENOMEM; diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c index bbe94b682119..5a1cb67cbcc0 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c @@ -1417,7 +1417,7 @@ int mce_threshold_create_device(unsigned int cpu) if (bp) return 0; - bp = kzalloc(sizeof(struct threshold_bank *) * mca_cfg.banks, + bp = kcalloc(mca_cfg.banks, sizeof(struct threshold_bank *), GFP_KERNEL); if (!bp) return -ENOMEM; diff --git a/arch/x86/kernel/cpu/mtrr/if.c b/arch/x86/kernel/cpu/mtrr/if.c index c2987daa6a6b..01a2de01e5c9 100644 --- a/arch/x86/kernel/cpu/mtrr/if.c +++ b/arch/x86/kernel/cpu/mtrr/if.c @@ -43,7 +43,7 @@ mtrr_file_add(unsigned long base, unsigned long size, max = num_var_ranges; if (fcount == NULL) { - fcount = kzalloc(max * sizeof *fcount, GFP_KERNEL); + fcount = kcalloc(max, sizeof(*fcount), GFP_KERNEL); if (!fcount) return -ENOMEM; FILE_FCOUNT(file) = fcount; diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index 7e26c1eaf00d..ff2703240cf5 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c @@ -611,7 +611,7 @@ static void hpet_msi_capability_lookup(unsigned int start_timer) if (!hpet_domain) return; - hpet_devs = kzalloc(sizeof(struct hpet_dev) * num_timers, GFP_KERNEL); + hpet_devs = kcalloc(num_timers, sizeof(struct hpet_dev), GFP_KERNEL); if (!hpet_devs) return; diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index c4b3646bd04c..8be380e4e39f 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c @@ -168,7 +168,7 @@ static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) if (type == PCI_CAP_ID_MSI && nvec > 1) return 1; - v = kzalloc(sizeof(int) * max(1, nvec), GFP_KERNEL); + v = kcalloc(max(1, nvec), sizeof(int), GFP_KERNEL); if (!v) return -ENOMEM; diff --git a/arch/x86/platform/uv/uv_time.c b/arch/x86/platform/uv/uv_time.c index b082d71b08ee..a36b368eea08 100644 --- a/arch/x86/platform/uv/uv_time.c +++ b/arch/x86/platform/uv/uv_time.c @@ -158,7 +158,7 @@ static __init int uv_rtc_allocate_timers(void) { int cpu; - blade_info = kzalloc(uv_possible_blades * sizeof(void *), GFP_KERNEL); + blade_info = kcalloc(uv_possible_blades, sizeof(void *), GFP_KERNEL); if (!blade_info) return -ENOMEM; diff --git a/block/bio.c b/block/bio.c index 0e9e16764586..6913e2ba4fdc 100644 --- a/block/bio.c +++ b/block/bio.c @@ -2206,7 +2206,8 @@ static int __init init_bio(void) { bio_slab_max = 2; bio_slab_nr = 0; - bio_slabs = kzalloc(bio_slab_max * sizeof(struct bio_slab), GFP_KERNEL); + bio_slabs = kcalloc(bio_slab_max, sizeof(struct bio_slab), + GFP_KERNEL); if (!bio_slabs) panic("bio: can't allocate bios\n"); diff --git a/block/blk-tag.c b/block/blk-tag.c index 09f19c6c52ce..24b20d86bcbc 100644 --- a/block/blk-tag.c +++ b/block/blk-tag.c @@ -99,12 +99,12 @@ init_tag_map(struct request_queue *q, struct blk_queue_tag *tags, int depth) __func__, depth); } - tag_index = kzalloc(depth * sizeof(struct request *), GFP_ATOMIC); + tag_index = kcalloc(depth, sizeof(struct request *), GFP_ATOMIC); if (!tag_index) goto fail; nr_ulongs = ALIGN(depth, BITS_PER_LONG) / BITS_PER_LONG; - tag_map = kzalloc(nr_ulongs * sizeof(unsigned long), GFP_ATOMIC); + tag_map = kcalloc(nr_ulongs, sizeof(unsigned long), GFP_ATOMIC); if (!tag_map) goto fail; diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c index 77abff18fde6..84bf3d473ae2 100644 --- a/crypto/tcrypt.c +++ b/crypto/tcrypt.c @@ -430,7 +430,7 @@ static void test_mb_ahash_speed(const char *algo, unsigned int sec, unsigned int i, j, k; int ret; - data = kzalloc(sizeof(*data) * 8, GFP_KERNEL); + data = kcalloc(8, sizeof(*data), GFP_KERNEL); if (!data) return; diff --git a/drivers/acpi/acpi_platform.c b/drivers/acpi/acpi_platform.c index ecd84d910ed2..1f32caa87686 100644 --- a/drivers/acpi/acpi_platform.c +++ b/drivers/acpi/acpi_platform.c @@ -83,7 +83,7 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev, if (count < 0) { return NULL; } else if (count > 0) { - resources = kzalloc(count * sizeof(struct resource), + resources = kcalloc(count, sizeof(struct resource), GFP_KERNEL); if (!resources) { dev_err(&adev->dev, "No memory for resources\n"); diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c index 1828b335c28a..5375e8894c0a 100644 --- a/drivers/acpi/sysfs.c +++ b/drivers/acpi/sysfs.c @@ -866,12 +866,12 @@ void acpi_irq_stats_init(void) num_gpes = acpi_current_gpe_count; num_counters = num_gpes + ACPI_NUM_FIXED_EVENTS + NUM_COUNTERS_EXTRA; - all_attrs = kzalloc(sizeof(struct attribute *) * (num_counters + 1), + all_attrs = kcalloc(num_counters + 1, sizeof(struct attribute *), GFP_KERNEL); if (all_attrs == NULL) return; - all_counters = kzalloc(sizeof(struct event_counter) * (num_counters), + all_counters = kcalloc(num_counters, sizeof(struct event_counter), GFP_KERNEL); if (all_counters == NULL) goto fail; @@ -880,7 +880,7 @@ void acpi_irq_stats_init(void) if (ACPI_FAILURE(status)) goto fail; - counter_attrs = kzalloc(sizeof(struct kobj_attribute) * (num_counters), + counter_attrs = kcalloc(num_counters, sizeof(struct kobj_attribute), GFP_KERNEL); if (counter_attrs == NULL) goto fail; diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index a3a65f5490c0..0eb1ec5941f9 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -6980,7 +6980,7 @@ static void __init ata_parse_force_param(void) if (*p == ',') size++; - ata_force_tbl = kzalloc(sizeof(ata_force_tbl[0]) * size, GFP_KERNEL); + ata_force_tbl = kcalloc(size, sizeof(ata_force_tbl[0]), GFP_KERNEL); if (!ata_force_tbl) { printk(KERN_WARNING "ata: failed to extend force table, " "libata.force ignored\n"); diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c index 7924d0635718..51eeaea65833 100644 --- a/drivers/ata/libata-pmp.c +++ b/drivers/ata/libata-pmp.c @@ -340,7 +340,7 @@ static int sata_pmp_init_links (struct ata_port *ap, int nr_ports) int i, err; if (!pmp_link) { - pmp_link = kzalloc(sizeof(pmp_link[0]) * SATA_PMP_MAX_PORTS, + pmp_link = kcalloc(SATA_PMP_MAX_PORTS, sizeof(pmp_link[0]), GFP_NOIO); if (!pmp_link) return -ENOMEM; diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c index 0a1ad1a1d34f..de03d213bc76 100644 --- a/drivers/atm/fore200e.c +++ b/drivers/atm/fore200e.c @@ -2097,7 +2097,8 @@ static int fore200e_alloc_rx_buf(struct fore200e *fore200e) DPRINTK(2, "rx buffers %d / %d are being allocated\n", scheme, magn); /* allocate the array of receive buffers */ - buffer = bsq->buffer = kzalloc(nbr * sizeof(struct buffer), GFP_KERNEL); + buffer = bsq->buffer = kcalloc(nbr, sizeof(struct buffer), + GFP_KERNEL); if (buffer == NULL) return -ENOMEM; diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c index 2b29598791e8..2658b75f0ca8 100644 --- a/drivers/atm/iphase.c +++ b/drivers/atm/iphase.c @@ -1619,7 +1619,7 @@ static int rx_init(struct atm_dev *dev) skb_queue_head_init(&iadev->rx_dma_q); iadev->rx_free_desc_qhead = NULL; - iadev->rx_open = kzalloc(4 * iadev->num_vc, GFP_KERNEL); + iadev->rx_open = kcalloc(4, iadev->num_vc, GFP_KERNEL); if (!iadev->rx_open) { printk(KERN_ERR DEV_LABEL "itf %d couldn't get free page\n", dev->number); diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index b998e3abca7a..1ae93c30ae8c 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -513,7 +513,8 @@ static void drbd_calc_cpu_mask(cpumask_var_t *cpu_mask) { unsigned int *resources_per_cpu, min_index = ~0; - resources_per_cpu = kzalloc(nr_cpu_ids * sizeof(*resources_per_cpu), GFP_KERNEL); + resources_per_cpu = kcalloc(nr_cpu_ids, sizeof(*resources_per_cpu), + GFP_KERNEL); if (resources_per_cpu) { struct drbd_resource *resource; unsigned int cpu, min = ~0; diff --git a/drivers/block/null_blk.c b/drivers/block/null_blk.c index b12e373aa956..1918c275c9a3 100644 --- a/drivers/block/null_blk.c +++ b/drivers/block/null_blk.c @@ -1687,12 +1687,12 @@ static int setup_commands(struct nullb_queue *nq) struct nullb_cmd *cmd; int i, tag_size; - nq->cmds = kzalloc(nq->queue_depth * sizeof(*cmd), GFP_KERNEL); + nq->cmds = kcalloc(nq->queue_depth, sizeof(*cmd), GFP_KERNEL); if (!nq->cmds) return -ENOMEM; tag_size = ALIGN(nq->queue_depth, BITS_PER_LONG) / BITS_PER_LONG; - nq->tag_map = kzalloc(tag_size * sizeof(unsigned long), GFP_KERNEL); + nq->tag_map = kcalloc(tag_size, sizeof(unsigned long), GFP_KERNEL); if (!nq->tag_map) { kfree(nq->cmds); return -ENOMEM; @@ -1710,8 +1710,9 @@ static int setup_commands(struct nullb_queue *nq) static int setup_queues(struct nullb *nullb) { - nullb->queues = kzalloc(nullb->dev->submit_queues * - sizeof(struct nullb_queue), GFP_KERNEL); + nullb->queues = kcalloc(nullb->dev->submit_queues, + sizeof(struct nullb_queue), + GFP_KERNEL); if (!nullb->queues) return -ENOMEM; diff --git a/drivers/block/ps3vram.c b/drivers/block/ps3vram.c index 6a55959cbf78..a6744ee7cf67 100644 --- a/drivers/block/ps3vram.c +++ b/drivers/block/ps3vram.c @@ -407,8 +407,9 @@ static int ps3vram_cache_init(struct ps3_system_bus_device *dev) priv->cache.page_count = CACHE_PAGE_COUNT; priv->cache.page_size = CACHE_PAGE_SIZE; - priv->cache.tags = kzalloc(sizeof(struct ps3vram_tag) * - CACHE_PAGE_COUNT, GFP_KERNEL); + priv->cache.tags = kcalloc(CACHE_PAGE_COUNT, + sizeof(struct ps3vram_tag), + GFP_KERNEL); if (!priv->cache.tags) return -ENOMEM; diff --git a/drivers/block/rsxx/core.c b/drivers/block/rsxx/core.c index 6beafaa335c7..f3ab828abf85 100644 --- a/drivers/block/rsxx/core.c +++ b/drivers/block/rsxx/core.c @@ -873,7 +873,8 @@ static int rsxx_pci_probe(struct pci_dev *dev, dev_info(CARD_TO_DEV(card), "Failed reading the number of DMA targets\n"); - card->ctrl = kzalloc(card->n_targets * sizeof(*card->ctrl), GFP_KERNEL); + card->ctrl = kcalloc(card->n_targets, sizeof(*card->ctrl), + GFP_KERNEL); if (!card->ctrl) { st = -ENOMEM; goto failed_dma_setup; diff --git a/drivers/block/rsxx/dma.c b/drivers/block/rsxx/dma.c index 6a1b2177951c..b5d7ea121450 100644 --- a/drivers/block/rsxx/dma.c +++ b/drivers/block/rsxx/dma.c @@ -1039,7 +1039,7 @@ int rsxx_eeh_save_issued_dmas(struct rsxx_cardinfo *card) struct rsxx_dma *dma; struct list_head *issued_dmas; - issued_dmas = kzalloc(sizeof(*issued_dmas) * card->n_targets, + issued_dmas = kcalloc(card->n_targets, sizeof(*issued_dmas), GFP_KERNEL); if (!issued_dmas) return -ENOMEM; diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index e9fa4a1fc791..d33e72a649b2 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c @@ -139,7 +139,8 @@ static int xen_blkif_alloc_rings(struct xen_blkif *blkif) { unsigned int r; - blkif->rings = kzalloc(blkif->nr_rings * sizeof(struct xen_blkif_ring), GFP_KERNEL); + blkif->rings = kcalloc(blkif->nr_rings, sizeof(struct xen_blkif_ring), + GFP_KERNEL); if (!blkif->rings) return -ENOMEM; diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index e6887714fe0a..5b9488201b93 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -1907,7 +1907,9 @@ static int negotiate_mq(struct blkfront_info *info) if (!info->nr_rings) info->nr_rings = 1; - info->rinfo = kzalloc(sizeof(struct blkfront_ring_info) * info->nr_rings, GFP_KERNEL); + info->rinfo = kcalloc(info->nr_rings, + sizeof(struct blkfront_ring_info), + GFP_KERNEL); if (!info->rinfo) { xenbus_dev_fatal(info->xbdev, -ENOMEM, "allocating ring_info structure"); info->nr_rings = 0; @@ -2218,15 +2220,16 @@ static int blkfront_setup_indirect(struct blkfront_ring_info *rinfo) } for (i = 0; i < BLK_RING_SIZE(info); i++) { - rinfo->shadow[i].grants_used = kzalloc( - sizeof(rinfo->shadow[i].grants_used[0]) * grants, - GFP_NOIO); - rinfo->shadow[i].sg = kzalloc(sizeof(rinfo->shadow[i].sg[0]) * psegs, GFP_NOIO); + rinfo->shadow[i].grants_used = kcalloc(grants, + sizeof(rinfo->shadow[i].grants_used[0]), + GFP_NOIO); + rinfo->shadow[i].sg = kcalloc(psegs, + sizeof(rinfo->shadow[i].sg[0]), + GFP_NOIO); if (info->max_indirect_segments) - rinfo->shadow[i].indirect_grants = kzalloc( - sizeof(rinfo->shadow[i].indirect_grants[0]) * - INDIRECT_GREFS(grants), - GFP_NOIO); + rinfo->shadow[i].indirect_grants = kcalloc(INDIRECT_GREFS(grants), + sizeof(rinfo->shadow[i].indirect_grants[0]), + GFP_NOIO); if ((rinfo->shadow[i].grants_used == NULL) || (rinfo->shadow[i].sg == NULL) || (info->max_indirect_segments && diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c index b450544dcaf0..6914e4f0ce98 100644 --- a/drivers/char/agp/amd-k7-agp.c +++ b/drivers/char/agp/amd-k7-agp.c @@ -85,7 +85,8 @@ static int amd_create_gatt_pages(int nr_tables) int retval = 0; int i; - tables = kzalloc((nr_tables + 1) * sizeof(struct amd_page_map *),GFP_KERNEL); + tables = kcalloc(nr_tables + 1, sizeof(struct amd_page_map *), + GFP_KERNEL); if (tables == NULL) return -ENOMEM; diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c index 88b4cbee4dac..20bf5f78a362 100644 --- a/drivers/char/agp/ati-agp.c +++ b/drivers/char/agp/ati-agp.c @@ -108,7 +108,8 @@ static int ati_create_gatt_pages(int nr_tables) int retval = 0; int i; - tables = kzalloc((nr_tables + 1) * sizeof(struct ati_page_map *),GFP_KERNEL); + tables = kcalloc(nr_tables + 1, sizeof(struct ati_page_map *), + GFP_KERNEL); if (tables == NULL) return -ENOMEM; diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c index 03be4ac79b0d..71ea2cac20d0 100644 --- a/drivers/char/agp/sworks-agp.c +++ b/drivers/char/agp/sworks-agp.c @@ -96,7 +96,7 @@ static int serverworks_create_gatt_pages(int nr_tables) int retval = 0; int i; - tables = kzalloc((nr_tables + 1) * sizeof(struct serverworks_page_map *), + tables = kcalloc(nr_tables + 1, sizeof(struct serverworks_page_map *), GFP_KERNEL); if (tables == NULL) return -ENOMEM; diff --git a/drivers/char/diag/diag_debugfs.c b/drivers/char/diag/diag_debugfs.c index 0e7c657807dd..49ee66f248f2 100644 --- a/drivers/char/diag/diag_debugfs.c +++ b/drivers/char/diag/diag_debugfs.c @@ -60,7 +60,7 @@ static ssize_t diag_dbgfs_read_status(struct file *file, char __user *ubuf, int ret, i; unsigned int buf_size; - buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL); + buf = kzalloc(DEBUG_BUF_SIZE, GFP_KERNEL); if (!buf) return -ENOMEM; buf_size = ksize(buf); @@ -227,7 +227,7 @@ static ssize_t diag_dbgfs_read_power(struct file *file, char __user *ubuf, int ret; unsigned int buf_size; - buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL); + buf = kzalloc(DEBUG_BUF_SIZE, GFP_KERNEL); if (!buf) return -ENOMEM; @@ -355,7 +355,7 @@ static ssize_t diag_dbgfs_read_mempool(struct file *file, char __user *ubuf, return 0; } - buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL); + buf = kzalloc(DEBUG_BUF_SIZE, GFP_KERNEL); if (ZERO_OR_NULL_PTR(buf)) { pr_err("diag: %s, Error allocating memory\n", __func__); return -ENOMEM; @@ -420,7 +420,7 @@ static ssize_t diag_dbgfs_read_usbinfo(struct file *file, char __user *ubuf, return 0; } - buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL); + buf = kzalloc(DEBUG_BUF_SIZE, GFP_KERNEL); if (ZERO_OR_NULL_PTR(buf)) { pr_err("diag: %s, Error allocating memory\n", __func__); return -ENOMEM; @@ -559,7 +559,7 @@ static ssize_t diag_dbgfs_read_socketinfo(struct file *file, char __user *ubuf, return 0; } - buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL); + buf = kzalloc(DEBUG_BUF_SIZE, GFP_KERNEL); if (ZERO_OR_NULL_PTR(buf)) { pr_err("diag: %s, Error allocating memory\n", __func__); return -ENOMEM; @@ -665,7 +665,7 @@ static ssize_t diag_dbgfs_read_rpmsginfo(struct file *file, char __user *ubuf, return 0; } - buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL); + buf = kzalloc(DEBUG_BUF_SIZE, GFP_KERNEL); if (!buf) return -ENOMEM; @@ -802,7 +802,7 @@ static ssize_t diag_dbgfs_read_hsicinfo(struct file *file, char __user *ubuf, return 0; } - buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL); + buf = kzalloc(DEBUG_BUF_SIZE, GFP_KERNEL); if (ZERO_OR_NULL_PTR(buf)) { pr_err("diag: %s, Error allocating memory\n", __func__); return -ENOMEM; @@ -874,7 +874,7 @@ static ssize_t diag_dbgfs_read_mhiinfo(struct file *file, char __user *ubuf, return 0; } - buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL); + buf = kzalloc(DEBUG_BUF_SIZE, GFP_KERNEL); if (ZERO_OR_NULL_PTR(buf)) { pr_err("diag: %s, Error allocating memory\n", __func__); return -ENOMEM; @@ -947,7 +947,7 @@ static ssize_t diag_dbgfs_read_bridge(struct file *file, char __user *ubuf, return 0; } - buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL); + buf = kzalloc(DEBUG_BUF_SIZE, GFP_KERNEL); if (ZERO_OR_NULL_PTR(buf)) { pr_err("diag: %s, Error allocating memory\n", __func__); return -ENOMEM; @@ -1131,8 +1131,9 @@ int diag_debugfs_init(void) diag_dbgfs_dci_finished = 0; /* DCI related structures */ - dci_traffic = kzalloc(sizeof(struct diag_dci_data_info) * - DIAG_DCI_DEBUG_CNT, GFP_KERNEL); + dci_traffic = kcalloc(DIAG_DCI_DEBUG_CNT, + sizeof(struct diag_dci_data_info), + GFP_KERNEL); if (ZERO_OR_NULL_PTR(dci_traffic)) pr_warn("diag: could not allocate memory for dci debug info\n"); diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c index 848ca8422015..ea053d354804 100644 --- a/drivers/char/diag/diagchar_core.c +++ b/drivers/char/diag/diagchar_core.c @@ -2684,7 +2684,7 @@ static int diag_cmd_register_tbl(struct diag_cmd_reg_tbl_t *reg_tbl) return -EFAULT; } - entries = kzalloc(count * entry_len, GFP_KERNEL); + entries = kcalloc(entry_len, count, GFP_KERNEL); if (!entries) return -ENOMEM; diff --git a/drivers/char/diag/diagfwd_peripheral.c b/drivers/char/diag/diagfwd_peripheral.c index b348e3c2bbbe..047131e45a91 100644 --- a/drivers/char/diag/diagfwd_peripheral.c +++ b/drivers/char/diag/diagfwd_peripheral.c @@ -863,9 +863,9 @@ int diagfwd_peripheral_init(void) struct diagfwd_info *fwd_info = NULL; for (transport = 0; transport < NUM_TRANSPORT; transport++) { - early_init_info[transport] = kzalloc( - sizeof(struct diagfwd_info) * NUM_PERIPHERALS, - GFP_KERNEL); + early_init_info[transport] = kcalloc(NUM_PERIPHERALS, + sizeof(struct diagfwd_info), + GFP_KERNEL); if (!early_init_info[transport]) return -ENOMEM; kmemleak_not_leak(early_init_info[transport]); diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c index cf87bfe971e6..6c3026a3de76 100644 --- a/drivers/char/ipmi/ipmi_ssif.c +++ b/drivers/char/ipmi/ipmi_ssif.c @@ -1834,7 +1834,8 @@ static unsigned short *ssif_address_list(void) list_for_each_entry(info, &ssif_infos, link) count++; - address_list = kzalloc(sizeof(*address_list) * (count + 1), GFP_KERNEL); + address_list = kcalloc(count + 1, sizeof(*address_list), + GFP_KERNEL); if (!address_list) return NULL; diff --git a/drivers/char/vservices_serial.c b/drivers/char/vservices_serial.c index 0194eacc563a..985befd6134d 100644 --- a/drivers/char/vservices_serial.c +++ b/drivers/char/vservices_serial.c @@ -576,8 +576,8 @@ static int __init vs_serial_init(void) if (max_ttys == 0) return -EINVAL; - alloced_ttys = kzalloc(sizeof(unsigned long) * BITS_TO_LONGS(max_ttys), - GFP_KERNEL); + alloced_ttys = kcalloc(BITS_TO_LONGS(max_ttys), sizeof(unsigned long), + GFP_KERNEL); if (!alloced_ttys) { err = -ENOMEM; goto fail_alloc_ttys; diff --git a/drivers/clk/renesas/clk-r8a7740.c b/drivers/clk/renesas/clk-r8a7740.c index 2f7ce6696b6c..718a65ac84f1 100644 --- a/drivers/clk/renesas/clk-r8a7740.c +++ b/drivers/clk/renesas/clk-r8a7740.c @@ -161,7 +161,7 @@ static void __init r8a7740_cpg_clocks_init(struct device_node *np) } cpg = kzalloc(sizeof(*cpg), GFP_KERNEL); - clks = kzalloc(num_clks * sizeof(*clks), GFP_KERNEL); + clks = kcalloc(num_clks, sizeof(*clks), GFP_KERNEL); if (cpg == NULL || clks == NULL) { /* We're leaking memory on purpose, there's no point in cleaning * up as the system won't boot anyway. diff --git a/drivers/clk/renesas/clk-r8a7779.c b/drivers/clk/renesas/clk-r8a7779.c index 27fbfafaf2cd..5adcca4656c3 100644 --- a/drivers/clk/renesas/clk-r8a7779.c +++ b/drivers/clk/renesas/clk-r8a7779.c @@ -138,7 +138,7 @@ static void __init r8a7779_cpg_clocks_init(struct device_node *np) } cpg = kzalloc(sizeof(*cpg), GFP_KERNEL); - clks = kzalloc(CPG_NUM_CLOCKS * sizeof(*clks), GFP_KERNEL); + clks = kcalloc(CPG_NUM_CLOCKS, sizeof(*clks), GFP_KERNEL); if (cpg == NULL || clks == NULL) { /* We're leaking memory on purpose, there's no point in cleaning * up as the system won't boot anyway. diff --git a/drivers/clk/renesas/clk-rcar-gen2.c b/drivers/clk/renesas/clk-rcar-gen2.c index 0b2e56d0d94b..563bb70362ef 100644 --- a/drivers/clk/renesas/clk-rcar-gen2.c +++ b/drivers/clk/renesas/clk-rcar-gen2.c @@ -418,7 +418,7 @@ static void __init rcar_gen2_cpg_clocks_init(struct device_node *np) } cpg = kzalloc(sizeof(*cpg), GFP_KERNEL); - clks = kzalloc(num_clks * sizeof(*clks), GFP_KERNEL); + clks = kcalloc(num_clks, sizeof(*clks), GFP_KERNEL); if (cpg == NULL || clks == NULL) { /* We're leaking memory on purpose, there's no point in cleaning * up as the system won't boot anyway. diff --git a/drivers/clk/renesas/clk-rz.c b/drivers/clk/renesas/clk-rz.c index 5adb934326d1..e582ee6e25ad 100644 --- a/drivers/clk/renesas/clk-rz.c +++ b/drivers/clk/renesas/clk-rz.c @@ -97,7 +97,7 @@ static void __init rz_cpg_clocks_init(struct device_node *np) return; cpg = kzalloc(sizeof(*cpg), GFP_KERNEL); - clks = kzalloc(num_clks * sizeof(*clks), GFP_KERNEL); + clks = kcalloc(num_clks, sizeof(*clks), GFP_KERNEL); BUG_ON(!cpg || !clks); cpg->data.clks = clks; diff --git a/drivers/clk/rockchip/clk-rockchip.c b/drivers/clk/rockchip/clk-rockchip.c index 2c9bb81144c9..1feb4e233d48 100644 --- a/drivers/clk/rockchip/clk-rockchip.c +++ b/drivers/clk/rockchip/clk-rockchip.c @@ -58,7 +58,7 @@ static void __init rk2928_gate_clk_init(struct device_node *node) return; } - clk_data->clks = kzalloc(qty * sizeof(struct clk *), GFP_KERNEL); + clk_data->clks = kcalloc(qty, sizeof(struct clk *), GFP_KERNEL); if (!clk_data->clks) { kfree(clk_data); iounmap(reg); diff --git a/drivers/clk/st/clkgen-fsyn.c b/drivers/clk/st/clkgen-fsyn.c index 14819d919df1..a79d81985c4e 100644 --- a/drivers/clk/st/clkgen-fsyn.c +++ b/drivers/clk/st/clkgen-fsyn.c @@ -874,7 +874,7 @@ static void __init st_of_create_quadfs_fsynths( return; clk_data->clk_num = QUADFS_MAX_CHAN; - clk_data->clks = kzalloc(QUADFS_MAX_CHAN * sizeof(struct clk *), + clk_data->clks = kcalloc(QUADFS_MAX_CHAN, sizeof(struct clk *), GFP_KERNEL); if (!clk_data->clks) { diff --git a/drivers/clk/st/clkgen-pll.c b/drivers/clk/st/clkgen-pll.c index 25bda48a5d35..7a7106dc80bf 100644 --- a/drivers/clk/st/clkgen-pll.c +++ b/drivers/clk/st/clkgen-pll.c @@ -738,7 +738,7 @@ static void __init clkgen_c32_pll_setup(struct device_node *np, return; clk_data->clk_num = num_odfs; - clk_data->clks = kzalloc(clk_data->clk_num * sizeof(struct clk *), + clk_data->clks = kcalloc(clk_data->clk_num, sizeof(struct clk *), GFP_KERNEL); if (!clk_data->clks) diff --git a/drivers/clk/sunxi/clk-usb.c b/drivers/clk/sunxi/clk-usb.c index fe0c3d169377..917fc27a33dd 100644 --- a/drivers/clk/sunxi/clk-usb.c +++ b/drivers/clk/sunxi/clk-usb.c @@ -122,7 +122,7 @@ static void __init sunxi_usb_clk_setup(struct device_node *node, if (!clk_data) return; - clk_data->clks = kzalloc((qty+1) * sizeof(struct clk *), GFP_KERNEL); + clk_data->clks = kcalloc(qty + 1, sizeof(struct clk *), GFP_KERNEL); if (!clk_data->clks) { kfree(clk_data); return; diff --git a/drivers/clk/tegra/clk.c b/drivers/clk/tegra/clk.c index ba923f0d5953..e64b41dd2837 100644 --- a/drivers/clk/tegra/clk.c +++ b/drivers/clk/tegra/clk.c @@ -216,14 +216,15 @@ struct clk ** __init tegra_clk_init(void __iomem *regs, int num, int banks) if (WARN_ON(banks > ARRAY_SIZE(periph_regs))) return NULL; - periph_clk_enb_refcnt = kzalloc(32 * banks * - sizeof(*periph_clk_enb_refcnt), GFP_KERNEL); + periph_clk_enb_refcnt = kcalloc(32 * banks, + sizeof(*periph_clk_enb_refcnt), + GFP_KERNEL); if (!periph_clk_enb_refcnt) return NULL; periph_banks = banks; - clks = kzalloc(num * sizeof(struct clk *), GFP_KERNEL); + clks = kcalloc(num, sizeof(struct clk *), GFP_KERNEL); if (!clks) kfree(periph_clk_enb_refcnt); diff --git a/drivers/clk/ti/apll.c b/drivers/clk/ti/apll.c index 83b148f8037c..30453a4e5b2c 100644 --- a/drivers/clk/ti/apll.c +++ b/drivers/clk/ti/apll.c @@ -205,7 +205,7 @@ static void __init of_dra7_apll_setup(struct device_node *node) goto cleanup; } - parent_names = kzalloc(sizeof(char *) * init->num_parents, GFP_KERNEL); + parent_names = kcalloc(init->num_parents, sizeof(char *), GFP_KERNEL); if (!parent_names) goto cleanup; diff --git a/drivers/clk/ti/divider.c b/drivers/clk/ti/divider.c index 88f04a4cb890..82136450b2c5 100644 --- a/drivers/clk/ti/divider.c +++ b/drivers/clk/ti/divider.c @@ -364,7 +364,7 @@ int ti_clk_parse_divider_data(int *div_table, int num_dividers, int max_div, num_dividers = i; - tmp = kzalloc(sizeof(*tmp) * (valid_div + 1), GFP_KERNEL); + tmp = kcalloc(valid_div + 1, sizeof(*tmp), GFP_KERNEL); if (!tmp) return -ENOMEM; @@ -493,7 +493,7 @@ __init ti_clk_get_div_table(struct device_node *node) return ERR_PTR(-EINVAL); } - table = kzalloc(sizeof(*table) * (valid_div + 1), GFP_KERNEL); + table = kcalloc(valid_div + 1, sizeof(*table), GFP_KERNEL); if (!table) return ERR_PTR(-ENOMEM); diff --git a/drivers/clk/ti/dpll.c b/drivers/clk/ti/dpll.c index d4e4444bc5ca..69280f37e3c0 100644 --- a/drivers/clk/ti/dpll.c +++ b/drivers/clk/ti/dpll.c @@ -398,7 +398,7 @@ static void __init of_ti_dpll_setup(struct device_node *node, goto cleanup; } - parent_names = kzalloc(sizeof(char *) * init->num_parents, GFP_KERNEL); + parent_names = kcalloc(init->num_parents, sizeof(char *), GFP_KERNEL); if (!parent_names) goto cleanup; diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c index 3cd62f7c33e3..d8fd71b303f8 100644 --- a/drivers/clocksource/sh_cmt.c +++ b/drivers/clocksource/sh_cmt.c @@ -1004,7 +1004,7 @@ static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev) /* Allocate and setup the channels. */ cmt->num_channels = hweight8(cmt->hw_channels); - cmt->channels = kzalloc(cmt->num_channels * sizeof(*cmt->channels), + cmt->channels = kcalloc(cmt->num_channels, sizeof(*cmt->channels), GFP_KERNEL); if (cmt->channels == NULL) { ret = -ENOMEM; diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c index 53aa7e92a7d7..6812e099b6a3 100644 --- a/drivers/clocksource/sh_mtu2.c +++ b/drivers/clocksource/sh_mtu2.c @@ -418,7 +418,7 @@ static int sh_mtu2_setup(struct sh_mtu2_device *mtu, /* Allocate and setup the channels. */ mtu->num_channels = 3; - mtu->channels = kzalloc(sizeof(*mtu->channels) * mtu->num_channels, + mtu->channels = kcalloc(mtu->num_channels, sizeof(*mtu->channels), GFP_KERNEL); if (mtu->channels == NULL) { ret = -ENOMEM; diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c index 31d881621e41..c74a6c543ca2 100644 --- a/drivers/clocksource/sh_tmu.c +++ b/drivers/clocksource/sh_tmu.c @@ -569,7 +569,7 @@ static int sh_tmu_setup(struct sh_tmu_device *tmu, struct platform_device *pdev) } /* Allocate and setup the channels. */ - tmu->channels = kzalloc(sizeof(*tmu->channels) * tmu->num_channels, + tmu->channels = kcalloc(tmu->num_channels, sizeof(*tmu->channels), GFP_KERNEL); if (tmu->channels == NULL) { ret = -ENOMEM; diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c index 51a3c15ace09..5073db1ef6b1 100644 --- a/drivers/cpufreq/acpi-cpufreq.c +++ b/drivers/cpufreq/acpi-cpufreq.c @@ -759,8 +759,8 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) goto err_unreg; } - freq_table = kzalloc(sizeof(*freq_table) * - (perf->state_count+1), GFP_KERNEL); + freq_table = kcalloc(perf->state_count + 1, sizeof(*freq_table), + GFP_KERNEL); if (!freq_table) { result = -ENOMEM; goto err_unreg; diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c index 0c41ab3b16eb..82db77f91c62 100644 --- a/drivers/cpufreq/arm_big_little.c +++ b/drivers/cpufreq/arm_big_little.c @@ -280,7 +280,7 @@ static int merge_cluster_tables(void) for (i = 0; i < MAX_CLUSTERS; i++) count += get_table_count(freq_table[i]); - table = kzalloc(sizeof(*table) * count, GFP_KERNEL); + table = kcalloc(count, sizeof(*table), GFP_KERNEL); if (!table) return -ENOMEM; diff --git a/drivers/cpufreq/at32ap-cpufreq.c b/drivers/cpufreq/at32ap-cpufreq.c index 7b612c8bb09e..55b5f0fe1795 100644 --- a/drivers/cpufreq/at32ap-cpufreq.c +++ b/drivers/cpufreq/at32ap-cpufreq.c @@ -77,8 +77,8 @@ static int at32_cpufreq_driver_init(struct cpufreq_policy *policy) * frequency table. */ steps = fls(frequency / min_freq) + 1; - freq_table = kzalloc(steps * sizeof(struct cpufreq_frequency_table), - GFP_KERNEL); + freq_table = kcalloc(steps, sizeof(struct cpufreq_frequency_table), + GFP_KERNEL); if (!freq_table) { retval = -ENOMEM; goto out_err_put_clk; diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c index c9ce716247c1..251873356ce5 100644 --- a/drivers/cpufreq/cppc_cpufreq.c +++ b/drivers/cpufreq/cppc_cpufreq.c @@ -258,7 +258,8 @@ static int __init cppc_cpufreq_init(void) if (acpi_disabled) return -ENODEV; - all_cpu_data = kzalloc(sizeof(void *) * num_possible_cpus(), GFP_KERNEL); + all_cpu_data = kcalloc(num_possible_cpus(), sizeof(void *), + GFP_KERNEL); if (!all_cpu_data) return -ENOMEM; diff --git a/drivers/cpufreq/ia64-acpi-cpufreq.c b/drivers/cpufreq/ia64-acpi-cpufreq.c index a757c0a1e7b5..247f30f9ddb1 100644 --- a/drivers/cpufreq/ia64-acpi-cpufreq.c +++ b/drivers/cpufreq/ia64-acpi-cpufreq.c @@ -241,8 +241,8 @@ acpi_cpufreq_cpu_init ( } /* alloc freq_table */ - freq_table = kzalloc(sizeof(*freq_table) * - (data->acpi_data.state_count + 1), + freq_table = kcalloc(data->acpi_data.state_count + 1, + sizeof(*freq_table), GFP_KERNEL); if (!freq_table) { result = -ENOMEM; diff --git a/drivers/cpufreq/longhaul.c b/drivers/cpufreq/longhaul.c index 859a62ea6120..7a2fdd9f688a 100644 --- a/drivers/cpufreq/longhaul.c +++ b/drivers/cpufreq/longhaul.c @@ -474,8 +474,8 @@ static int longhaul_get_ranges(void) return -EINVAL; } - longhaul_table = kzalloc((numscales + 1) * sizeof(*longhaul_table), - GFP_KERNEL); + longhaul_table = kcalloc(numscales + 1, sizeof(*longhaul_table), + GFP_KERNEL); if (!longhaul_table) return -ENOMEM; diff --git a/drivers/cpufreq/pxa3xx-cpufreq.c b/drivers/cpufreq/pxa3xx-cpufreq.c index a01275900389..4d49f6e2ff60 100644 --- a/drivers/cpufreq/pxa3xx-cpufreq.c +++ b/drivers/cpufreq/pxa3xx-cpufreq.c @@ -93,7 +93,7 @@ static int setup_freqs_table(struct cpufreq_policy *policy, struct cpufreq_frequency_table *table; int i; - table = kzalloc((num + 1) * sizeof(*table), GFP_KERNEL); + table = kcalloc(num + 1, sizeof(*table), GFP_KERNEL); if (table == NULL) return -ENOMEM; diff --git a/drivers/cpufreq/s3c24xx-cpufreq.c b/drivers/cpufreq/s3c24xx-cpufreq.c index 6bebc1f9f55a..4181a6f62f02 100644 --- a/drivers/cpufreq/s3c24xx-cpufreq.c +++ b/drivers/cpufreq/s3c24xx-cpufreq.c @@ -567,7 +567,7 @@ static int s3c_cpufreq_build_freq(void) size = cpu_cur.info->calc_freqtable(&cpu_cur, NULL, 0); size++; - ftab = kzalloc(sizeof(*ftab) * size, GFP_KERNEL); + ftab = kcalloc(size, sizeof(*ftab), GFP_KERNEL); if (!ftab) { pr_err("%s: no memory for tables\n", __func__); return -ENOMEM; diff --git a/drivers/cpufreq/sfi-cpufreq.c b/drivers/cpufreq/sfi-cpufreq.c index 3779742f86e3..346403ecb7d4 100644 --- a/drivers/cpufreq/sfi-cpufreq.c +++ b/drivers/cpufreq/sfi-cpufreq.c @@ -94,8 +94,8 @@ static int __init sfi_cpufreq_init(void) if (ret) return ret; - freq_table = kzalloc(sizeof(*freq_table) * - (num_freq_table_entries + 1), GFP_KERNEL); + freq_table = kcalloc(num_freq_table_entries + 1, sizeof(*freq_table), + GFP_KERNEL); if (!freq_table) { ret = -ENOMEM; goto err_free_array; diff --git a/drivers/cpufreq/spear-cpufreq.c b/drivers/cpufreq/spear-cpufreq.c index 4894924a3ca2..1c8e8c3a5f1b 100644 --- a/drivers/cpufreq/spear-cpufreq.c +++ b/drivers/cpufreq/spear-cpufreq.c @@ -195,7 +195,7 @@ static int spear_cpufreq_probe(struct platform_device *pdev) cnt = prop->length / sizeof(u32); val = prop->value; - freq_tbl = kzalloc(sizeof(*freq_tbl) * (cnt + 1), GFP_KERNEL); + freq_tbl = kcalloc(cnt + 1, sizeof(*freq_tbl), GFP_KERNEL); if (!freq_tbl) { ret = -ENOMEM; goto out_put_node; diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c index d1d041de7f8a..b68a4f232f6d 100644 --- a/drivers/crypto/amcc/crypto4xx_core.c +++ b/drivers/crypto/amcc/crypto4xx_core.c @@ -198,8 +198,8 @@ static u32 crypto4xx_build_pdr(struct crypto4xx_device *dev) if (!dev->pdr) return -ENOMEM; - dev->pdr_uinfo = kzalloc(sizeof(struct pd_uinfo) * PPC4XX_NUM_PD, - GFP_KERNEL); + dev->pdr_uinfo = kcalloc(PPC4XX_NUM_PD, sizeof(struct pd_uinfo), + GFP_KERNEL); if (!dev->pdr_uinfo) { dma_free_coherent(dev->core_dev->device, sizeof(struct ce_pd) * PPC4XX_NUM_PD, diff --git a/drivers/crypto/inside-secure/safexcel_hash.c b/drivers/crypto/inside-secure/safexcel_hash.c index 69f29776591a..221ad7468aaf 100644 --- a/drivers/crypto/inside-secure/safexcel_hash.c +++ b/drivers/crypto/inside-secure/safexcel_hash.c @@ -901,7 +901,7 @@ static int safexcel_hmac_setkey(const char *alg, const u8 *key, crypto_ahash_clear_flags(tfm, ~0); blocksize = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); - ipad = kzalloc(2 * blocksize, GFP_KERNEL); + ipad = kcalloc(2, blocksize, GFP_KERNEL); if (!ipad) { ret = -ENOMEM; goto free_request; diff --git a/drivers/crypto/marvell/hash.c b/drivers/crypto/marvell/hash.c index e61b08566093..e34d80b6b7e5 100644 --- a/drivers/crypto/marvell/hash.c +++ b/drivers/crypto/marvell/hash.c @@ -1198,7 +1198,7 @@ static int mv_cesa_ahmac_setkey(const char *hash_alg_name, blocksize = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); - ipad = kzalloc(2 * blocksize, GFP_KERNEL); + ipad = kcalloc(2, blocksize, GFP_KERNEL); if (!ipad) { ret = -ENOMEM; goto free_req; diff --git a/drivers/crypto/n2_core.c b/drivers/crypto/n2_core.c index 699ee5a9a8f9..545ceae44ea0 100644 --- a/drivers/crypto/n2_core.c +++ b/drivers/crypto/n2_core.c @@ -1907,12 +1907,12 @@ static int grab_global_resources(void) goto out_hvapi_release; err = -ENOMEM; - cpu_to_cwq = kzalloc(sizeof(struct spu_queue *) * NR_CPUS, + cpu_to_cwq = kcalloc(NR_CPUS, sizeof(struct spu_queue *), GFP_KERNEL); if (!cpu_to_cwq) goto out_queue_cache_destroy; - cpu_to_mau = kzalloc(sizeof(struct spu_queue *) * NR_CPUS, + cpu_to_mau = kcalloc(NR_CPUS, sizeof(struct spu_queue *), GFP_KERNEL); if (!cpu_to_mau) goto out_free_cwq_table; diff --git a/drivers/crypto/qat/qat_common/qat_uclo.c b/drivers/crypto/qat/qat_common/qat_uclo.c index e2454d90d949..506e9a7d9acb 100644 --- a/drivers/crypto/qat/qat_common/qat_uclo.c +++ b/drivers/crypto/qat/qat_common/qat_uclo.c @@ -1159,8 +1159,9 @@ static int qat_uclo_map_suof(struct icp_qat_fw_loader_handle *handle, suof_handle->img_table.num_simgs = suof_ptr->num_chunks - 1; if (suof_handle->img_table.num_simgs != 0) { - suof_img_hdr = kzalloc(suof_handle->img_table.num_simgs * - sizeof(img_header), GFP_KERNEL); + suof_img_hdr = kcalloc(suof_handle->img_table.num_simgs, + sizeof(img_header), + GFP_KERNEL); if (!suof_img_hdr) return -ENOMEM; suof_handle->img_table.simg_hdr = suof_img_hdr; diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index 6c8a03a1132f..a54f16a43b35 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c @@ -3326,8 +3326,9 @@ static int talitos_probe(struct platform_device *ofdev) } } - priv->chan = kzalloc(sizeof(struct talitos_channel) * - priv->num_channels, GFP_KERNEL); + priv->chan = kcalloc(priv->num_channels, + sizeof(struct talitos_channel), + GFP_KERNEL); if (!priv->chan) { dev_err(dev, "failed to allocate channel management space\n"); err = -ENOMEM; @@ -3344,8 +3345,9 @@ static int talitos_probe(struct platform_device *ofdev) spin_lock_init(&priv->chan[i].head_lock); spin_lock_init(&priv->chan[i].tail_lock); - priv->chan[i].fifo = kzalloc(sizeof(struct talitos_request) * - priv->fifo_len, GFP_KERNEL); + priv->chan[i].fifo = kcalloc(priv->fifo_len, + sizeof(struct talitos_request), + GFP_KERNEL); if (!priv->chan[i].fifo) { dev_err(dev, "failed to allocate request fifo %d\n", i); err = -ENOMEM; diff --git a/drivers/dma/ioat/init.c b/drivers/dma/ioat/init.c index 9103a0425f75..758e1a450cb3 100644 --- a/drivers/dma/ioat/init.c +++ b/drivers/dma/ioat/init.c @@ -322,10 +322,10 @@ static int ioat_dma_self_test(struct ioatdma_device *ioat_dma) unsigned long tmo; unsigned long flags; - src = kzalloc(sizeof(u8) * IOAT_TEST_SIZE, GFP_KERNEL); + src = kzalloc(IOAT_TEST_SIZE, GFP_KERNEL); if (!src) return -ENOMEM; - dest = kzalloc(sizeof(u8) * IOAT_TEST_SIZE, GFP_KERNEL); + dest = kzalloc(IOAT_TEST_SIZE, GFP_KERNEL); if (!dest) { kfree(src); return -ENOMEM; diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c index 25a52d8b7ee0..abc8d3e0487b 100644 --- a/drivers/dma/mv_xor.c +++ b/drivers/dma/mv_xor.c @@ -781,7 +781,7 @@ static int mv_chan_memcpy_self_test(struct mv_xor_chan *mv_chan) if (!src) return -ENOMEM; - dest = kzalloc(sizeof(u8) * PAGE_SIZE, GFP_KERNEL); + dest = kzalloc(PAGE_SIZE, GFP_KERNEL); if (!dest) { kfree(src); return -ENOMEM; diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c index b4fa555a243f..cbcba1f022ce 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -1767,7 +1767,7 @@ static int dmac_alloc_threads(struct pl330_dmac *pl330) int i; /* Allocate 1 Manager and 'chans' Channel threads */ - pl330->channels = kzalloc((1 + chans) * sizeof(*thrd), + pl330->channels = kcalloc(1 + chans, sizeof(*thrd), GFP_KERNEL); if (!pl330->channels) return -ENOMEM; @@ -2885,7 +2885,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) pl330->num_peripherals = num_chan; - pl330->peripherals = kzalloc(num_chan * sizeof(*pch), GFP_KERNEL); + pl330->peripherals = kcalloc(num_chan, sizeof(*pch), GFP_KERNEL); if (!pl330->peripherals) { ret = -ENOMEM; goto probe_err2; diff --git a/drivers/dma/sh/shdma-base.c b/drivers/dma/sh/shdma-base.c index 12fa48e380cf..6b5626e299b2 100644 --- a/drivers/dma/sh/shdma-base.c +++ b/drivers/dma/sh/shdma-base.c @@ -1045,8 +1045,9 @@ EXPORT_SYMBOL(shdma_cleanup); static int __init shdma_enter(void) { - shdma_slave_used = kzalloc(DIV_ROUND_UP(slave_num, BITS_PER_LONG) * - sizeof(long), GFP_KERNEL); + shdma_slave_used = kcalloc(DIV_ROUND_UP(slave_num, BITS_PER_LONG), + sizeof(long), + GFP_KERNEL); if (!shdma_slave_used) return -ENOMEM; return 0; diff --git a/drivers/dma/xilinx/zynqmp_dma.c b/drivers/dma/xilinx/zynqmp_dma.c index 6d86d05e53aa..11bd68f0ce30 100644 --- a/drivers/dma/xilinx/zynqmp_dma.c +++ b/drivers/dma/xilinx/zynqmp_dma.c @@ -463,7 +463,7 @@ static int zynqmp_dma_alloc_chan_resources(struct dma_chan *dchan) struct zynqmp_dma_desc_sw *desc; int i; - chan->sw_desc_pool = kzalloc(sizeof(*desc) * ZYNQMP_DMA_NUM_DESCS, + chan->sw_desc_pool = kcalloc(ZYNQMP_DMA_NUM_DESCS, sizeof(*desc), GFP_KERNEL); if (!chan->sw_desc_pool) return -ENOMEM; diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 21c5f95596be..3878065e1bcd 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -3473,7 +3473,7 @@ static int __init amd64_edac_init(void) opstate_init(); err = -ENOMEM; - ecc_stngs = kzalloc(amd_nb_num() * sizeof(ecc_stngs[0]), GFP_KERNEL); + ecc_stngs = kcalloc(amd_nb_num(), sizeof(ecc_stngs[0]), GFP_KERNEL); if (!ecc_stngs) goto err_free; diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index 2054a24b41d7..59bf8612d439 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c @@ -461,7 +461,7 @@ static struct i7core_dev *alloc_i7core_dev(u8 socket, if (!i7core_dev) return NULL; - i7core_dev->pdev = kzalloc(sizeof(*i7core_dev->pdev) * table->n_devs, + i7core_dev->pdev = kcalloc(table->n_devs, sizeof(*i7core_dev->pdev), GFP_KERNEL); if (!i7core_dev->pdev) { kfree(i7core_dev); diff --git a/drivers/extcon/extcon.c b/drivers/extcon/extcon.c index 97bd841334e4..3a0089d0735a 100644 --- a/drivers/extcon/extcon.c +++ b/drivers/extcon/extcon.c @@ -1185,8 +1185,9 @@ int extcon_dev_register(struct extcon_dev *edev) char *str; struct extcon_cable *cable; - edev->cables = kzalloc(sizeof(struct extcon_cable) * - edev->max_supported, GFP_KERNEL); + edev->cables = kcalloc(edev->max_supported, + sizeof(struct extcon_cable), + GFP_KERNEL); if (!edev->cables) { ret = -ENOMEM; goto err_sysfs_alloc; @@ -1195,7 +1196,7 @@ int extcon_dev_register(struct extcon_dev *edev) cable = &edev->cables[index]; snprintf(buf, 10, "cable.%d", index); - str = kzalloc(sizeof(char) * (strlen(buf) + 1), + str = kzalloc(strlen(buf) + 1, GFP_KERNEL); if (!str) { for (index--; index >= 0; index--) { @@ -1236,15 +1237,17 @@ int extcon_dev_register(struct extcon_dev *edev) for (index = 0; edev->mutually_exclusive[index]; index++) ; - edev->attrs_muex = kzalloc(sizeof(struct attribute *) * - (index + 1), GFP_KERNEL); + edev->attrs_muex = kcalloc(index + 1, + sizeof(struct attribute *), + GFP_KERNEL); if (!edev->attrs_muex) { ret = -ENOMEM; goto err_muex; } - edev->d_attrs_muex = kzalloc(sizeof(struct device_attribute) * - index, GFP_KERNEL); + edev->d_attrs_muex = kcalloc(index, + sizeof(struct device_attribute), + GFP_KERNEL); if (!edev->d_attrs_muex) { ret = -ENOMEM; kfree(edev->attrs_muex); @@ -1253,7 +1256,7 @@ int extcon_dev_register(struct extcon_dev *edev) for (index = 0; edev->mutually_exclusive[index]; index++) { sprintf(buf, "0x%x", edev->mutually_exclusive[index]); - name = kzalloc(sizeof(char) * (strlen(buf) + 1), + name = kzalloc(strlen(buf) + 1, GFP_KERNEL); if (!name) { for (index--; index >= 0; index--) { @@ -1279,8 +1282,9 @@ int extcon_dev_register(struct extcon_dev *edev) if (edev->max_supported) { edev->extcon_dev_type.groups = - kzalloc(sizeof(struct attribute_group *) * - (edev->max_supported + 2), GFP_KERNEL); + kcalloc(edev->max_supported + 2, + sizeof(struct attribute_group *), + GFP_KERNEL); if (!edev->extcon_dev_type.groups) { ret = -ENOMEM; goto err_alloc_groups; diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c index 53f27a6e2d76..ccefa84f7305 100644 --- a/drivers/firmware/dell_rbu.c +++ b/drivers/firmware/dell_rbu.c @@ -147,7 +147,7 @@ static int create_packet(void *data, size_t length) packet_array_size = max( (unsigned int)(allocation_floor / rbu_data.packetsize), (unsigned int)1); - invalid_addr_packet_array = kzalloc(packet_array_size * sizeof(void*), + invalid_addr_packet_array = kcalloc(packet_array_size, sizeof(void *), GFP_KERNEL); if (!invalid_addr_packet_array) { diff --git a/drivers/firmware/efi/capsule.c b/drivers/firmware/efi/capsule.c index 901b9306bf94..4938c29b7c5d 100644 --- a/drivers/firmware/efi/capsule.c +++ b/drivers/firmware/efi/capsule.c @@ -231,7 +231,7 @@ int efi_capsule_update(efi_capsule_header_t *capsule, phys_addr_t *pages) count = DIV_ROUND_UP(imagesize, PAGE_SIZE); sg_count = sg_pages_num(count); - sg_pages = kzalloc(sg_count * sizeof(*sg_pages), GFP_KERNEL); + sg_pages = kcalloc(sg_count, sizeof(*sg_pages), GFP_KERNEL); if (!sg_pages) return -ENOMEM; diff --git a/drivers/firmware/efi/runtime-map.c b/drivers/firmware/efi/runtime-map.c index f377609ff141..84a11d0a8023 100644 --- a/drivers/firmware/efi/runtime-map.c +++ b/drivers/firmware/efi/runtime-map.c @@ -166,7 +166,7 @@ int __init efi_runtime_map_init(struct kobject *efi_kobj) if (!efi_enabled(EFI_MEMMAP)) return 0; - map_entries = kzalloc(efi.memmap.nr_map * sizeof(entry), GFP_KERNEL); + map_entries = kcalloc(efi.memmap.nr_map, sizeof(entry), GFP_KERNEL); if (!map_entries) { ret = -ENOMEM; goto out; diff --git a/drivers/fmc/fmc-sdb.c b/drivers/fmc/fmc-sdb.c index ffdc1762b580..d0e65b86dc22 100644 --- a/drivers/fmc/fmc-sdb.c +++ b/drivers/fmc/fmc-sdb.c @@ -48,8 +48,8 @@ static struct sdb_array *__fmc_scan_sdb_tree(struct fmc_device *fmc, arr = kzalloc(sizeof(*arr), GFP_KERNEL); if (!arr) return ERR_PTR(-ENOMEM); - arr->record = kzalloc(sizeof(arr->record[0]) * n, GFP_KERNEL); - arr->subtree = kzalloc(sizeof(arr->subtree[0]) * n, GFP_KERNEL); + arr->record = kcalloc(n, sizeof(arr->record[0]), GFP_KERNEL); + arr->subtree = kcalloc(n, sizeof(arr->subtree[0]), GFP_KERNEL); if (!arr->record || !arr->subtree) { kfree(arr->record); kfree(arr->subtree); diff --git a/drivers/gpio/gpio-ml-ioh.c b/drivers/gpio/gpio-ml-ioh.c index 1022fe8d09c7..a10af0628591 100644 --- a/drivers/gpio/gpio-ml-ioh.c +++ b/drivers/gpio/gpio-ml-ioh.c @@ -443,7 +443,7 @@ static int ioh_gpio_probe(struct pci_dev *pdev, goto err_iomap; } - chip_save = kzalloc(sizeof(*chip) * 8, GFP_KERNEL); + chip_save = kcalloc(8, sizeof(*chip), GFP_KERNEL); if (chip_save == NULL) { dev_err(&pdev->dev, "%s : kzalloc failed", __func__); ret = -ENOMEM; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c index a52795d9b458..2877567bd047 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c @@ -300,20 +300,20 @@ static int acp_hw_init(void *handle) pm_genpd_init(&adev->acp.acp_genpd->gpd, NULL, false); } - adev->acp.acp_cell = kzalloc(sizeof(struct mfd_cell) * ACP_DEVS, + adev->acp.acp_cell = kcalloc(ACP_DEVS, sizeof(struct mfd_cell), GFP_KERNEL); if (adev->acp.acp_cell == NULL) return -ENOMEM; - adev->acp.acp_res = kzalloc(sizeof(struct resource) * 4, GFP_KERNEL); + adev->acp.acp_res = kcalloc(4, sizeof(struct resource), GFP_KERNEL); if (adev->acp.acp_res == NULL) { kfree(adev->acp.acp_cell); return -ENOMEM; } - i2s_pdata = kzalloc(sizeof(struct i2s_platform_data) * 2, GFP_KERNEL); + i2s_pdata = kcalloc(2, sizeof(struct i2s_platform_data), GFP_KERNEL); if (i2s_pdata == NULL) { kfree(adev->acp.acp_res); kfree(adev->acp.acp_cell); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c index bb4b804255a8..42bb16404779 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c @@ -973,7 +973,9 @@ static int amdgpu_cgs_acpi_eval_object(struct cgs_device *cgs_device, /* parse input parameters */ if (input.count > 0) { input.pointer = params = - kzalloc(sizeof(union acpi_object) * input.count, GFP_KERNEL); + kcalloc(input.count, + sizeof(union acpi_object), + GFP_KERNEL); if (params == NULL) return -EINVAL; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c index 1cb52fd19060..911624b101c2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c @@ -432,7 +432,7 @@ int amdgpu_parse_extended_power_table(struct amdgpu_device *adev) ATOM_PPLIB_PhaseSheddingLimits_Record *entry; adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries = - kzalloc(psl->ucNumEntries * + kcalloc(psl->ucNumEntries, sizeof(struct amdgpu_phase_shedding_limits_entry), GFP_KERNEL); if (!adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_test.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_test.c index b35b0741fd97..284554614368 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_test.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_test.c @@ -52,7 +52,7 @@ static void amdgpu_do_test_moves(struct amdgpu_device *adev) n -= adev->irq.ih.ring_size; n /= size; - gtt_obj = kzalloc(n * sizeof(*gtt_obj), GFP_KERNEL); + gtt_obj = kcalloc(n, sizeof(*gtt_obj), GFP_KERNEL); if (!gtt_obj) { DRM_ERROR("Failed to allocate %d pointers\n", n); r = 1; diff --git a/drivers/gpu/drm/amd/amdgpu/atom.c b/drivers/gpu/drm/amd/amdgpu/atom.c index d69aa2e179bb..868bef501a5f 100644 --- a/drivers/gpu/drm/amd/amdgpu/atom.c +++ b/drivers/gpu/drm/amd/amdgpu/atom.c @@ -1221,7 +1221,7 @@ static int amdgpu_atom_execute_table_locked(struct atom_context *ctx, int index, ectx.abort = false; ectx.last_jump = 0; if (ws) - ectx.ws = kzalloc(4 * ws, GFP_KERNEL); + ectx.ws = kcalloc(4, ws, GFP_KERNEL); else ectx.ws = NULL; diff --git a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c index cb508a211b2f..57fd92b8e0d9 100644 --- a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c @@ -5705,8 +5705,9 @@ static int ci_parse_power_table(struct amdgpu_device *adev) (mode_info->atom_context->bios + data_offset + le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset)); - adev->pm.dpm.ps = kzalloc(sizeof(struct amdgpu_ps) * - state_array->ucNumEntries, GFP_KERNEL); + adev->pm.dpm.ps = kcalloc(state_array->ucNumEntries, + sizeof(struct amdgpu_ps), + GFP_KERNEL); if (!adev->pm.dpm.ps) return -ENOMEM; power_state_offset = (u8 *)state_array->states; @@ -5953,7 +5954,9 @@ static int ci_dpm_init(struct amdgpu_device *adev) ci_set_private_data_variables_based_on_pptable(adev); adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries = - kzalloc(4 * sizeof(struct amdgpu_clock_voltage_dependency_entry), GFP_KERNEL); + kcalloc(4, + sizeof(struct amdgpu_clock_voltage_dependency_entry), + GFP_KERNEL); if (!adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries) { ci_dpm_fini(adev); return -ENOMEM; diff --git a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c b/drivers/gpu/drm/amd/amdgpu/kv_dpm.c index c76073b422d6..f94a27e0d482 100644 --- a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/kv_dpm.c @@ -2718,8 +2718,9 @@ static int kv_parse_power_table(struct amdgpu_device *adev) (mode_info->atom_context->bios + data_offset + le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset)); - adev->pm.dpm.ps = kzalloc(sizeof(struct amdgpu_ps) * - state_array->ucNumEntries, GFP_KERNEL); + adev->pm.dpm.ps = kcalloc(state_array->ucNumEntries, + sizeof(struct amdgpu_ps), + GFP_KERNEL); if (!adev->pm.dpm.ps) return -ENOMEM; power_state_offset = (u8 *)state_array->states; diff --git a/drivers/gpu/drm/amd/amdgpu/si_dpm.c b/drivers/gpu/drm/amd/amdgpu/si_dpm.c index 55613f425931..66481cfcdd1a 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/si_dpm.c @@ -7233,8 +7233,9 @@ static int si_parse_power_table(struct amdgpu_device *adev) (mode_info->atom_context->bios + data_offset + le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset)); - adev->pm.dpm.ps = kzalloc(sizeof(struct amdgpu_ps) * - state_array->ucNumEntries, GFP_KERNEL); + adev->pm.dpm.ps = kcalloc(state_array->ucNumEntries, + sizeof(struct amdgpu_ps), + GFP_KERNEL); if (!adev->pm.dpm.ps) return -ENOMEM; power_state_offset = (u8 *)state_array->states; @@ -7337,7 +7338,9 @@ static int si_dpm_init(struct amdgpu_device *adev) return ret; adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries = - kzalloc(4 * sizeof(struct amdgpu_clock_voltage_dependency_entry), GFP_KERNEL); + kcalloc(4, + sizeof(struct amdgpu_clock_voltage_dependency_entry), + GFP_KERNEL); if (!adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries) { amdgpu_free_extended_power_table(adev); return -ENOMEM; diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c index 9547f265a8bb..ff23a397a078 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c @@ -150,7 +150,7 @@ static int hw_init_power_state_table(struct pp_hwmgr *hwmgr) hwmgr->ps_size = size = hwmgr->hwmgr_func->get_power_state_size(hwmgr) + sizeof(struct pp_power_state); - hwmgr->ps = kzalloc(size * table_entries, GFP_KERNEL); + hwmgr->ps = kcalloc(table_entries, size, GFP_KERNEL); if (hwmgr->ps == NULL) return -ENOMEM; diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index eab36a460638..2a83b91ee054 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -562,13 +562,15 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set, * Allocate space for the backup of all (non-pointer) encoder and * connector data. */ - save_encoder_crtcs = kzalloc(dev->mode_config.num_encoder * - sizeof(struct drm_crtc *), GFP_KERNEL); + save_encoder_crtcs = kcalloc(dev->mode_config.num_encoder, + sizeof(struct drm_crtc *), + GFP_KERNEL); if (!save_encoder_crtcs) return -ENOMEM; - save_connector_encoders = kzalloc(dev->mode_config.num_connector * - sizeof(struct drm_encoder *), GFP_KERNEL); + save_connector_encoders = kcalloc(dev->mode_config.num_connector, + sizeof(struct drm_encoder *), + GFP_KERNEL); if (!save_connector_encoders) { kfree(save_encoder_crtcs); return -ENOMEM; diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index eb6bf881c465..e58b6d9cfc8f 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -2261,8 +2261,9 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper, if (modes[n] == NULL) return best_score; - crtcs = kzalloc(fb_helper->connector_count * - sizeof(struct drm_fb_helper_crtc *), GFP_KERNEL); + crtcs = kcalloc(fb_helper->connector_count, + sizeof(struct drm_fb_helper_crtc *), + GFP_KERNEL); if (!crtcs) return best_score; diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c index 06aee1741e96..759ed93f4ba8 100644 --- a/drivers/gpu/drm/drm_plane_helper.c +++ b/drivers/gpu/drm/drm_plane_helper.c @@ -354,7 +354,7 @@ int drm_primary_helper_update(struct drm_plane *plane, struct drm_crtc *crtc, /* Find current connectors for CRTC */ num_connectors = get_connectors_for_crtc(crtc, NULL, 0); BUG_ON(num_connectors == 0); - connector_list = kzalloc(num_connectors * sizeof(*connector_list), + connector_list = kcalloc(num_connectors, sizeof(*connector_list), GFP_KERNEL); if (!connector_list) return -ENOMEM; diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c b/drivers/gpu/drm/i915/gvt/vgpu.c index e9f9063dbf63..b23eb4856009 100644 --- a/drivers/gpu/drm/i915/gvt/vgpu.c +++ b/drivers/gpu/drm/i915/gvt/vgpu.c @@ -118,7 +118,7 @@ int intel_gvt_init_vgpu_types(struct intel_gvt *gvt) high_avail = gvt_hidden_sz(gvt) - HOST_HIGH_GM_SIZE; num_types = sizeof(vgpu_types) / sizeof(vgpu_types[0]); - gvt->types = kzalloc(num_types * sizeof(struct intel_vgpu_type), + gvt->types = kcalloc(num_types, sizeof(struct intel_vgpu_type), GFP_KERNEL); if (!gvt->types) return -ENOMEM; diff --git a/drivers/gpu/drm/i915/selftests/intel_uncore.c b/drivers/gpu/drm/i915/selftests/intel_uncore.c index 3cac22eb47ce..7ee3bd09fe22 100644 --- a/drivers/gpu/drm/i915/selftests/intel_uncore.c +++ b/drivers/gpu/drm/i915/selftests/intel_uncore.c @@ -126,7 +126,7 @@ static int intel_uncore_check_forcewake_domains(struct drm_i915_private *dev_pri if (IS_BROADWELL(dev_priv)) /* XXX random GPU hang afterwards! */ return 0; - valid = kzalloc(BITS_TO_LONGS(FW_RANGE) * sizeof(*valid), + valid = kcalloc(BITS_TO_LONGS(FW_RANGE), sizeof(*valid), GFP_KERNEL); if (!valid) return -ENOMEM; diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c index b6207249c02c..461c33d25cf6 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c @@ -3432,7 +3432,7 @@ int dsi_panel_parse_esd_reg_read_configs(struct dsi_panel *panel) } esd_config->status_value = - kzalloc(sizeof(u32) * status_len * esd_config->groups, + kzalloc(array3_size(sizeof(u32), status_len, esd_config->groups), GFP_KERNEL); if (!esd_config->status_value) { rc = -ENOMEM; diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c index e0f33def74ac..b25e352bc16b 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c +++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c @@ -1411,9 +1411,9 @@ static int sde_sspp_parse_dt(struct device_node *np, if (snp) { dgm_count = of_get_child_count(snp); if (dgm_count > 0 && dgm_count <= SSPP_SUBBLK_COUNT_MAX) { - dgm_prop_value = kzalloc(dgm_count * DMA_PROP_MAX * - sizeof(struct sde_prop_value), - GFP_KERNEL); + dgm_prop_value = kcalloc(dgm_count * DMA_PROP_MAX, + sizeof(struct sde_prop_value), + GFP_KERNEL); if (!dgm_prop_value) { rc = -ENOMEM; goto end; @@ -1564,8 +1564,8 @@ static int sde_ctl_parse_dt(struct device_node *np, goto end; } - prop_value = kzalloc(HW_PROP_MAX * - sizeof(struct sde_prop_value), GFP_KERNEL); + prop_value = kcalloc(HW_PROP_MAX, sizeof(struct sde_prop_value), + GFP_KERNEL); if (!prop_value) { rc = -ENOMEM; goto end; @@ -1662,9 +1662,9 @@ static int sde_mixer_parse_dt(struct device_node *np, /* get mixer feature dt properties if they exist */ snp = of_get_child_by_name(np, mixer_prop[MIXER_BLOCKS].prop_name); if (snp) { - blocks_prop_value = kzalloc(MIXER_BLOCKS_PROP_MAX * - MAX_SDE_HW_BLK * sizeof(struct sde_prop_value), - GFP_KERNEL); + blocks_prop_value = kcalloc(MIXER_BLOCKS_PROP_MAX * MAX_SDE_HW_BLK, + sizeof(struct sde_prop_value), + GFP_KERNEL); if (!blocks_prop_value) { rc = -ENOMEM; goto end; @@ -1680,8 +1680,9 @@ static int sde_mixer_parse_dt(struct device_node *np, } /* get the blend_op register offsets */ - blend_prop_value = kzalloc(MIXER_BLEND_PROP_MAX * - sizeof(struct sde_prop_value), GFP_KERNEL); + blend_prop_value = kcalloc(MIXER_BLEND_PROP_MAX, + sizeof(struct sde_prop_value), + GFP_KERNEL); if (!blend_prop_value) { rc = -ENOMEM; goto end; @@ -1803,8 +1804,8 @@ static int sde_intf_parse_dt(struct device_node *np, goto end; } - prop_value = kzalloc(INTF_PROP_MAX * - sizeof(struct sde_prop_value), GFP_KERNEL); + prop_value = kcalloc(INTF_PROP_MAX, sizeof(struct sde_prop_value), + GFP_KERNEL); if (!prop_value) { rc = -ENOMEM; goto end; @@ -1886,8 +1887,8 @@ static int sde_wb_parse_dt(struct device_node *np, struct sde_mdss_cfg *sde_cfg) goto end; } - prop_value = kzalloc(WB_PROP_MAX * - sizeof(struct sde_prop_value), GFP_KERNEL); + prop_value = kcalloc(WB_PROP_MAX, sizeof(struct sde_prop_value), + GFP_KERNEL); if (!prop_value) { rc = -ENOMEM; goto end; @@ -2260,8 +2261,8 @@ static int sde_dspp_top_parse_dt(struct device_node *np, goto end; } - prop_value = kzalloc(DSPP_TOP_PROP_MAX * - sizeof(struct sde_prop_value), GFP_KERNEL); + prop_value = kcalloc(DSPP_TOP_PROP_MAX, sizeof(struct sde_prop_value), + GFP_KERNEL); if (!prop_value) { rc = -ENOMEM; goto end; @@ -2315,8 +2316,8 @@ static int sde_dspp_parse_dt(struct device_node *np, goto end; } - prop_value = kzalloc(DSPP_PROP_MAX * - sizeof(struct sde_prop_value), GFP_KERNEL); + prop_value = kcalloc(DSPP_PROP_MAX, sizeof(struct sde_prop_value), + GFP_KERNEL); if (!prop_value) { rc = -ENOMEM; goto end; @@ -2353,9 +2354,9 @@ static int sde_dspp_parse_dt(struct device_node *np, /* get DSPP feature dt properties if they exist */ snp = of_get_child_by_name(np, dspp_prop[DSPP_BLOCKS].prop_name); if (snp) { - blocks_prop_value = kzalloc(DSPP_BLOCKS_PROP_MAX * - MAX_SDE_HW_BLK * sizeof(struct sde_prop_value), - GFP_KERNEL); + blocks_prop_value = kcalloc(DSPP_BLOCKS_PROP_MAX * MAX_SDE_HW_BLK, + sizeof(struct sde_prop_value), + GFP_KERNEL); if (!blocks_prop_value) { rc = -ENOMEM; goto end; @@ -2433,8 +2434,9 @@ static int sde_ds_parse_dt(struct device_node *np, } /* Parse the dest scaler top register offset and capabilities */ - top_prop_value = kzalloc(DS_TOP_PROP_MAX * - sizeof(struct sde_prop_value), GFP_KERNEL); + top_prop_value = kcalloc(DS_TOP_PROP_MAX, + sizeof(struct sde_prop_value), + GFP_KERNEL); if (!top_prop_value) { rc = -ENOMEM; goto end; @@ -2538,8 +2540,8 @@ static int sde_dsc_parse_dt(struct device_node *np, goto end; } - prop_value = kzalloc(DSC_PROP_MAX * - sizeof(struct sde_prop_value), GFP_KERNEL); + prop_value = kcalloc(DSC_PROP_MAX, sizeof(struct sde_prop_value), + GFP_KERNEL); if (!prop_value) { rc = -ENOMEM; goto end; @@ -2592,8 +2594,8 @@ static int sde_cdm_parse_dt(struct device_node *np, goto end; } - prop_value = kzalloc(HW_PROP_MAX * - sizeof(struct sde_prop_value), GFP_KERNEL); + prop_value = kcalloc(HW_PROP_MAX, sizeof(struct sde_prop_value), + GFP_KERNEL); if (!prop_value) { rc = -ENOMEM; goto end; @@ -2648,8 +2650,8 @@ static int sde_vbif_parse_dt(struct device_node *np, goto end; } - prop_value = kzalloc(VBIF_PROP_MAX * - sizeof(struct sde_prop_value), GFP_KERNEL); + prop_value = kcalloc(VBIF_PROP_MAX, sizeof(struct sde_prop_value), + GFP_KERNEL); if (!prop_value) { rc = -ENOMEM; goto end; @@ -2861,8 +2863,8 @@ static int sde_pp_parse_dt(struct device_node *np, struct sde_mdss_cfg *sde_cfg) goto end; } - prop_value = kzalloc(PP_PROP_MAX * - sizeof(struct sde_prop_value), GFP_KERNEL); + prop_value = kcalloc(PP_PROP_MAX, sizeof(struct sde_prop_value), + GFP_KERNEL); if (!prop_value) { rc = -ENOMEM; goto end; @@ -3067,8 +3069,9 @@ static int sde_limit_parse_dt(struct device_node *np, struct sde_mdss_cfg *cfg) goto end; } - sde_limit_value = kzalloc(cfg->limit_count * LIMIT_PROP_MAX * - sizeof(struct sde_prop_value), GFP_KERNEL); + sde_limit_value = kcalloc(cfg->limit_count * LIMIT_PROP_MAX, + sizeof(struct sde_prop_value), + GFP_KERNEL); if (!sde_limit_value) { rc = -ENOMEM; goto end; @@ -3103,8 +3106,8 @@ static int sde_parse_dt(struct device_node *np, struct sde_mdss_cfg *cfg) goto end; } - prop_value = kzalloc(SDE_PROP_MAX * - sizeof(struct sde_prop_value), GFP_KERNEL); + prop_value = kcalloc(SDE_PROP_MAX, sizeof(struct sde_prop_value), + GFP_KERNEL); if (!prop_value) { rc = -ENOMEM; goto end; @@ -3329,8 +3332,8 @@ static int sde_perf_parse_dt(struct device_node *np, struct sde_mdss_cfg *cfg) goto end; } - prop_value = kzalloc(PERF_PROP_MAX * - sizeof(struct sde_prop_value), GFP_KERNEL); + prop_value = kcalloc(PERF_PROP_MAX, sizeof(struct sde_prop_value), + GFP_KERNEL); if (!prop_value) { rc = -ENOMEM; goto end; @@ -3695,8 +3698,8 @@ static int sde_qdss_parse_dt(struct device_node *np, goto end; } - prop_value = kzalloc(HW_PROP_MAX * - sizeof(struct sde_prop_value), GFP_KERNEL); + prop_value = kcalloc(HW_PROP_MAX, sizeof(struct sde_prop_value), + GFP_KERNEL); if (!prop_value) { rc = -ENOMEM; goto end; diff --git a/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c b/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c index e76943052102..b7a48e08508d 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c +++ b/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c @@ -1944,7 +1944,7 @@ static int reg_dmav1_setup_vig_igc_common(struct sde_hw_reg_dma_ops *dma_ops, hw_cfg->len, sizeof(struct drm_msm_igc_lut)); } - data = kzalloc(VIG_1D_LUT_IGC_LEN * sizeof(u32), GFP_KERNEL); + data = kcalloc(VIG_1D_LUT_IGC_LEN, sizeof(u32), GFP_KERNEL); if (!data) return -ENOMEM; @@ -2205,7 +2205,7 @@ void reg_dmav1_setup_dma_igcv5(struct sde_hw_pipe *ctx, void *cfg, return; } - data = kzalloc(DMA_1D_LUT_IGC_LEN * sizeof(u32), GFP_KERNEL); + data = kcalloc(DMA_1D_LUT_IGC_LEN, sizeof(u32), GFP_KERNEL); if (!data) { DRM_ERROR("failed to allocate memory for igc\n"); return; diff --git a/drivers/gpu/drm/msm/sde/sde_hw_rot.c b/drivers/gpu/drm/msm/sde/sde_hw_rot.c index 24c6a3a15141..f627d2d5822b 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_rot.c +++ b/drivers/gpu/drm/msm/sde/sde_hw_rot.c @@ -749,8 +749,8 @@ static const struct sde_format_extended *sde_hw_rot_get_format_caps( sde_rotator_inline_get_pixfmt_caps(pdev, true, v4l_pixfmts, len); /* allocate one more to indicate termination */ - drm_pixfmts = kzalloc((len + 1) * sizeof(struct sde_format_extended), - GFP_KERNEL); + drm_pixfmts = kcalloc(len + 1, sizeof(struct sde_format_extended), + GFP_KERNEL); if (!drm_pixfmts) goto done; diff --git a/drivers/gpu/drm/nouveau/nvif/object.c b/drivers/gpu/drm/nouveau/nvif/object.c index c3fb6a20f567..cd399bcdc3b3 100644 --- a/drivers/gpu/drm/nouveau/nvif/object.c +++ b/drivers/gpu/drm/nouveau/nvif/object.c @@ -83,7 +83,7 @@ nvif_object_sclass_get(struct nvif_object *object, struct nvif_sclass **psclass) return ret; } - *psclass = kzalloc(sizeof(**psclass) * args->sclass.count, GFP_KERNEL); + *psclass = kcalloc(args->sclass.count, sizeof(**psclass), GFP_KERNEL); if (*psclass) { for (i = 0; i < args->sclass.count; i++) { (*psclass)[i].oclass = args->sclass.oclass[i].oclass; diff --git a/drivers/gpu/drm/nouveau/nvkm/core/event.c b/drivers/gpu/drm/nouveau/nvkm/core/event.c index 4e8d3fa042df..5e44bbb74177 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/event.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/event.c @@ -84,7 +84,7 @@ int nvkm_event_init(const struct nvkm_event_func *func, int types_nr, int index_nr, struct nvkm_event *event) { - event->refs = kzalloc(sizeof(*event->refs) * index_nr * types_nr, + event->refs = kzalloc(array3_size(index_nr, types_nr, sizeof(*event->refs)), GFP_KERNEL); if (!event->refs) return -ENOMEM; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c index 0b632dc0cf7d..c1919901ad5a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c @@ -781,7 +781,7 @@ gk104_fifo_oneinit(struct nvkm_fifo *base) nvkm_debug(subdev, "%d PBDMA(s)\n", fifo->pbdma_nr); /* Read PBDMA->runlist(s) mapping from HW. */ - if (!(map = kzalloc(sizeof(*map) * fifo->pbdma_nr, GFP_KERNEL))) + if (!(map = kcalloc(fifo->pbdma_nr, sizeof(*map), GFP_KERNEL))) return -ENOMEM; for (i = 0; i < fifo->pbdma_nr; i++) diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c index ef55fcaa4e50..45252fe1cb05 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem.c +++ b/drivers/gpu/drm/omapdrm/omap_gem.c @@ -270,7 +270,7 @@ static int omap_gem_attach_pages(struct drm_gem_object *obj) } } } else { - addrs = kzalloc(npages * sizeof(*addrs), GFP_KERNEL); + addrs = kcalloc(npages, sizeof(*addrs), GFP_KERNEL); if (!addrs) { ret = -ENOMEM; goto free_pages; diff --git a/drivers/gpu/drm/radeon/atom.c b/drivers/gpu/drm/radeon/atom.c index 6a2e091aa7b6..e55cbeee7a53 100644 --- a/drivers/gpu/drm/radeon/atom.c +++ b/drivers/gpu/drm/radeon/atom.c @@ -1176,7 +1176,7 @@ static int atom_execute_table_locked(struct atom_context *ctx, int index, uint32 ectx.abort = false; ectx.last_jump = 0; if (ws) - ectx.ws = kzalloc(4 * ws, GFP_KERNEL); + ectx.ws = kcalloc(4, ws, GFP_KERNEL); else ectx.ws = NULL; diff --git a/drivers/gpu/drm/radeon/btc_dpm.c b/drivers/gpu/drm/radeon/btc_dpm.c index 95652e643da1..0aef4937c901 100644 --- a/drivers/gpu/drm/radeon/btc_dpm.c +++ b/drivers/gpu/drm/radeon/btc_dpm.c @@ -2581,7 +2581,9 @@ int btc_dpm_init(struct radeon_device *rdev) return ret; rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries = - kzalloc(4 * sizeof(struct radeon_clock_voltage_dependency_entry), GFP_KERNEL); + kcalloc(4, + sizeof(struct radeon_clock_voltage_dependency_entry), + GFP_KERNEL); if (!rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries) { r600_free_extended_power_table(rdev); return -ENOMEM; diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c index 6e607cc7b6e5..cfbf0fa36a21 100644 --- a/drivers/gpu/drm/radeon/ci_dpm.c +++ b/drivers/gpu/drm/radeon/ci_dpm.c @@ -5546,8 +5546,9 @@ static int ci_parse_power_table(struct radeon_device *rdev) (mode_info->atom_context->bios + data_offset + le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset)); - rdev->pm.dpm.ps = kzalloc(sizeof(struct radeon_ps) * - state_array->ucNumEntries, GFP_KERNEL); + rdev->pm.dpm.ps = kcalloc(state_array->ucNumEntries, + sizeof(struct radeon_ps), + GFP_KERNEL); if (!rdev->pm.dpm.ps) return -ENOMEM; power_state_offset = (u8 *)state_array->states; @@ -5747,7 +5748,9 @@ int ci_dpm_init(struct radeon_device *rdev) ci_set_private_data_variables_based_on_pptable(rdev); rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries = - kzalloc(4 * sizeof(struct radeon_clock_voltage_dependency_entry), GFP_KERNEL); + kcalloc(4, + sizeof(struct radeon_clock_voltage_dependency_entry), + GFP_KERNEL); if (!rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries) { ci_dpm_fini(rdev); return -ENOMEM; diff --git a/drivers/gpu/drm/radeon/kv_dpm.c b/drivers/gpu/drm/radeon/kv_dpm.c index ae1529b0ef6f..f055d6ea3522 100644 --- a/drivers/gpu/drm/radeon/kv_dpm.c +++ b/drivers/gpu/drm/radeon/kv_dpm.c @@ -2660,8 +2660,9 @@ static int kv_parse_power_table(struct radeon_device *rdev) (mode_info->atom_context->bios + data_offset + le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset)); - rdev->pm.dpm.ps = kzalloc(sizeof(struct radeon_ps) * - state_array->ucNumEntries, GFP_KERNEL); + rdev->pm.dpm.ps = kcalloc(state_array->ucNumEntries, + sizeof(struct radeon_ps), + GFP_KERNEL); if (!rdev->pm.dpm.ps) return -ENOMEM; power_state_offset = (u8 *)state_array->states; diff --git a/drivers/gpu/drm/radeon/ni_dpm.c b/drivers/gpu/drm/radeon/ni_dpm.c index d491b3aa124f..f86ca163dcf3 100644 --- a/drivers/gpu/drm/radeon/ni_dpm.c +++ b/drivers/gpu/drm/radeon/ni_dpm.c @@ -3998,8 +3998,9 @@ static int ni_parse_power_table(struct radeon_device *rdev) return -EINVAL; power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); - rdev->pm.dpm.ps = kzalloc(sizeof(struct radeon_ps) * - power_info->pplib.ucNumStates, GFP_KERNEL); + rdev->pm.dpm.ps = kcalloc(power_info->pplib.ucNumStates, + sizeof(struct radeon_ps), + GFP_KERNEL); if (!rdev->pm.dpm.ps) return -ENOMEM; @@ -4075,7 +4076,9 @@ int ni_dpm_init(struct radeon_device *rdev) return ret; rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries = - kzalloc(4 * sizeof(struct radeon_clock_voltage_dependency_entry), GFP_KERNEL); + kcalloc(4, + sizeof(struct radeon_clock_voltage_dependency_entry), + GFP_KERNEL); if (!rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries) { r600_free_extended_power_table(rdev); return -ENOMEM; diff --git a/drivers/gpu/drm/radeon/r600_dpm.c b/drivers/gpu/drm/radeon/r600_dpm.c index 31d1b4710844..73d4c5348116 100644 --- a/drivers/gpu/drm/radeon/r600_dpm.c +++ b/drivers/gpu/drm/radeon/r600_dpm.c @@ -991,7 +991,7 @@ int r600_parse_extended_power_table(struct radeon_device *rdev) ATOM_PPLIB_PhaseSheddingLimits_Record *entry; rdev->pm.dpm.dyn_state.phase_shedding_limits_table.entries = - kzalloc(psl->ucNumEntries * + kcalloc(psl->ucNumEntries, sizeof(struct radeon_phase_shedding_limits_entry), GFP_KERNEL); if (!rdev->pm.dpm.dyn_state.phase_shedding_limits_table.entries) { diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 4134759a6823..a4c47d31147e 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -2126,13 +2126,16 @@ static int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev) num_modes = ATOM_MAX_NUMBEROF_POWER_BLOCK; if (num_modes == 0) return state_index; - rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state) * num_modes, GFP_KERNEL); + rdev->pm.power_state = kcalloc(num_modes, + sizeof(struct radeon_power_state), + GFP_KERNEL); if (!rdev->pm.power_state) return state_index; /* last mode is usually default, array is low to high */ for (i = 0; i < num_modes; i++) { rdev->pm.power_state[state_index].clock_info = - kzalloc(sizeof(struct radeon_pm_clock_info) * 1, GFP_KERNEL); + kcalloc(1, sizeof(struct radeon_pm_clock_info), + GFP_KERNEL); if (!rdev->pm.power_state[state_index].clock_info) return state_index; rdev->pm.power_state[state_index].num_clock_modes = 1; @@ -2587,8 +2590,9 @@ static int radeon_atombios_parse_power_table_4_5(struct radeon_device *rdev) radeon_atombios_add_pplib_thermal_controller(rdev, &power_info->pplib.sThermalController); if (power_info->pplib.ucNumStates == 0) return state_index; - rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state) * - power_info->pplib.ucNumStates, GFP_KERNEL); + rdev->pm.power_state = kcalloc(power_info->pplib.ucNumStates, + sizeof(struct radeon_power_state), + GFP_KERNEL); if (!rdev->pm.power_state) return state_index; /* first mode is usually default, followed by low to high */ @@ -2603,9 +2607,8 @@ static int radeon_atombios_parse_power_table_4_5(struct radeon_device *rdev) le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset) + (power_state->v1.ucNonClockStateIndex * power_info->pplib.ucNonClockSize)); - rdev->pm.power_state[i].clock_info = kzalloc(sizeof(struct radeon_pm_clock_info) * - ((power_info->pplib.ucStateEntrySize - 1) ? - (power_info->pplib.ucStateEntrySize - 1) : 1), + rdev->pm.power_state[i].clock_info = kcalloc((power_info->pplib.ucStateEntrySize - 1) ? (power_info->pplib.ucStateEntrySize - 1) : 1, + sizeof(struct radeon_pm_clock_info), GFP_KERNEL); if (!rdev->pm.power_state[i].clock_info) return state_index; @@ -2688,8 +2691,9 @@ static int radeon_atombios_parse_power_table_6(struct radeon_device *rdev) le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset)); if (state_array->ucNumEntries == 0) return state_index; - rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state) * - state_array->ucNumEntries, GFP_KERNEL); + rdev->pm.power_state = kcalloc(state_array->ucNumEntries, + sizeof(struct radeon_power_state), + GFP_KERNEL); if (!rdev->pm.power_state) return state_index; power_state_offset = (u8 *)state_array->states; @@ -2699,9 +2703,8 @@ static int radeon_atombios_parse_power_table_6(struct radeon_device *rdev) non_clock_array_index = power_state->v2.nonClockInfoIndex; non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *) &non_clock_info_array->nonClockInfo[non_clock_array_index]; - rdev->pm.power_state[i].clock_info = kzalloc(sizeof(struct radeon_pm_clock_info) * - (power_state->v2.ucNumDPMLevels ? - power_state->v2.ucNumDPMLevels : 1), + rdev->pm.power_state[i].clock_info = kcalloc(power_state->v2.ucNumDPMLevels ? power_state->v2.ucNumDPMLevels : 1, + sizeof(struct radeon_pm_clock_info), GFP_KERNEL); if (!rdev->pm.power_state[i].clock_info) return state_index; @@ -2782,7 +2785,9 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev) rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state), GFP_KERNEL); if (rdev->pm.power_state) { rdev->pm.power_state[0].clock_info = - kzalloc(sizeof(struct radeon_pm_clock_info) * 1, GFP_KERNEL); + kcalloc(1, + sizeof(struct radeon_pm_clock_info), + GFP_KERNEL); if (rdev->pm.power_state[0].clock_info) { /* add the default mode */ rdev->pm.power_state[state_index].type = diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index 3178ba0c537c..60a61d33f607 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -2642,13 +2642,16 @@ void radeon_combios_get_power_modes(struct radeon_device *rdev) rdev->pm.default_power_state_index = -1; /* allocate 2 power states */ - rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state) * 2, GFP_KERNEL); + rdev->pm.power_state = kcalloc(2, sizeof(struct radeon_power_state), + GFP_KERNEL); if (rdev->pm.power_state) { /* allocate 1 clock mode per state */ rdev->pm.power_state[0].clock_info = - kzalloc(sizeof(struct radeon_pm_clock_info) * 1, GFP_KERNEL); + kcalloc(1, sizeof(struct radeon_pm_clock_info), + GFP_KERNEL); rdev->pm.power_state[1].clock_info = - kzalloc(sizeof(struct radeon_pm_clock_info) * 1, GFP_KERNEL); + kcalloc(1, sizeof(struct radeon_pm_clock_info), + GFP_KERNEL); if (!rdev->pm.power_state[0].clock_info || !rdev->pm.power_state[1].clock_info) goto pm_failed; diff --git a/drivers/gpu/drm/radeon/radeon_test.c b/drivers/gpu/drm/radeon/radeon_test.c index f5e9abfadb56..48f4b273e316 100644 --- a/drivers/gpu/drm/radeon/radeon_test.c +++ b/drivers/gpu/drm/radeon/radeon_test.c @@ -59,7 +59,7 @@ static void radeon_do_test_moves(struct radeon_device *rdev, int flag) n = rdev->mc.gtt_size - rdev->gart_pin_size; n /= size; - gtt_obj = kzalloc(n * sizeof(*gtt_obj), GFP_KERNEL); + gtt_obj = kcalloc(n, sizeof(*gtt_obj), GFP_KERNEL); if (!gtt_obj) { DRM_ERROR("Failed to allocate %d pointers\n", n); r = 1; diff --git a/drivers/gpu/drm/radeon/rs780_dpm.c b/drivers/gpu/drm/radeon/rs780_dpm.c index b5e4e09a8996..694b7b3e9799 100644 --- a/drivers/gpu/drm/radeon/rs780_dpm.c +++ b/drivers/gpu/drm/radeon/rs780_dpm.c @@ -804,8 +804,9 @@ static int rs780_parse_power_table(struct radeon_device *rdev) return -EINVAL; power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); - rdev->pm.dpm.ps = kzalloc(sizeof(struct radeon_ps) * - power_info->pplib.ucNumStates, GFP_KERNEL); + rdev->pm.dpm.ps = kcalloc(power_info->pplib.ucNumStates, + sizeof(struct radeon_ps), + GFP_KERNEL); if (!rdev->pm.dpm.ps) return -ENOMEM; diff --git a/drivers/gpu/drm/radeon/rv6xx_dpm.c b/drivers/gpu/drm/radeon/rv6xx_dpm.c index d91aa3944593..6986051fbb89 100644 --- a/drivers/gpu/drm/radeon/rv6xx_dpm.c +++ b/drivers/gpu/drm/radeon/rv6xx_dpm.c @@ -1888,8 +1888,9 @@ static int rv6xx_parse_power_table(struct radeon_device *rdev) return -EINVAL; power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); - rdev->pm.dpm.ps = kzalloc(sizeof(struct radeon_ps) * - power_info->pplib.ucNumStates, GFP_KERNEL); + rdev->pm.dpm.ps = kcalloc(power_info->pplib.ucNumStates, + sizeof(struct radeon_ps), + GFP_KERNEL); if (!rdev->pm.dpm.ps) return -ENOMEM; diff --git a/drivers/gpu/drm/radeon/rv770_dpm.c b/drivers/gpu/drm/radeon/rv770_dpm.c index cb2a7ec4e217..c765ae7ea806 100644 --- a/drivers/gpu/drm/radeon/rv770_dpm.c +++ b/drivers/gpu/drm/radeon/rv770_dpm.c @@ -2282,8 +2282,9 @@ int rv7xx_parse_power_table(struct radeon_device *rdev) return -EINVAL; power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); - rdev->pm.dpm.ps = kzalloc(sizeof(struct radeon_ps) * - power_info->pplib.ucNumStates, GFP_KERNEL); + rdev->pm.dpm.ps = kcalloc(power_info->pplib.ucNumStates, + sizeof(struct radeon_ps), + GFP_KERNEL); if (!rdev->pm.dpm.ps) return -ENOMEM; diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c index 9e5645e4cb55..46031fc33c19 100644 --- a/drivers/gpu/drm/radeon/si_dpm.c +++ b/drivers/gpu/drm/radeon/si_dpm.c @@ -6833,8 +6833,9 @@ static int si_parse_power_table(struct radeon_device *rdev) (mode_info->atom_context->bios + data_offset + le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset)); - rdev->pm.dpm.ps = kzalloc(sizeof(struct radeon_ps) * - state_array->ucNumEntries, GFP_KERNEL); + rdev->pm.dpm.ps = kcalloc(state_array->ucNumEntries, + sizeof(struct radeon_ps), + GFP_KERNEL); if (!rdev->pm.dpm.ps) return -ENOMEM; power_state_offset = (u8 *)state_array->states; @@ -6942,7 +6943,9 @@ int si_dpm_init(struct radeon_device *rdev) return ret; rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries = - kzalloc(4 * sizeof(struct radeon_clock_voltage_dependency_entry), GFP_KERNEL); + kcalloc(4, + sizeof(struct radeon_clock_voltage_dependency_entry), + GFP_KERNEL); if (!rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries) { r600_free_extended_power_table(rdev); return -ENOMEM; diff --git a/drivers/gpu/drm/radeon/sumo_dpm.c b/drivers/gpu/drm/radeon/sumo_dpm.c index fd4804829e46..1e4975f3374c 100644 --- a/drivers/gpu/drm/radeon/sumo_dpm.c +++ b/drivers/gpu/drm/radeon/sumo_dpm.c @@ -1482,8 +1482,9 @@ static int sumo_parse_power_table(struct radeon_device *rdev) (mode_info->atom_context->bios + data_offset + le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset)); - rdev->pm.dpm.ps = kzalloc(sizeof(struct radeon_ps) * - state_array->ucNumEntries, GFP_KERNEL); + rdev->pm.dpm.ps = kcalloc(state_array->ucNumEntries, + sizeof(struct radeon_ps), + GFP_KERNEL); if (!rdev->pm.dpm.ps) return -ENOMEM; power_state_offset = (u8 *)state_array->states; diff --git a/drivers/gpu/drm/radeon/trinity_dpm.c b/drivers/gpu/drm/radeon/trinity_dpm.c index 2ef7c4e5e495..5d317f763eea 100644 --- a/drivers/gpu/drm/radeon/trinity_dpm.c +++ b/drivers/gpu/drm/radeon/trinity_dpm.c @@ -1757,8 +1757,9 @@ static int trinity_parse_power_table(struct radeon_device *rdev) (mode_info->atom_context->bios + data_offset + le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset)); - rdev->pm.dpm.ps = kzalloc(sizeof(struct radeon_ps) * - state_array->ucNumEntries, GFP_KERNEL); + rdev->pm.dpm.ps = kcalloc(state_array->ucNumEntries, + sizeof(struct radeon_ps), + GFP_KERNEL); if (!rdev->pm.dpm.ps) return -ENOMEM; power_state_offset = (u8 *)state_array->states; diff --git a/drivers/gpu/drm/selftests/test-drm_mm.c b/drivers/gpu/drm/selftests/test-drm_mm.c index 86eb4c185a28..63a02c68a2c5 100644 --- a/drivers/gpu/drm/selftests/test-drm_mm.c +++ b/drivers/gpu/drm/selftests/test-drm_mm.c @@ -1626,7 +1626,7 @@ static int igt_topdown(void *ignored) if (!nodes) goto err; - bitmap = kzalloc(count / BITS_PER_LONG * sizeof(unsigned long), + bitmap = kcalloc(count / BITS_PER_LONG, sizeof(unsigned long), GFP_KERNEL); if (!bitmap) goto err_nodes; @@ -1740,7 +1740,7 @@ static int igt_bottomup(void *ignored) if (!nodes) goto err; - bitmap = kzalloc(count / BITS_PER_LONG * sizeof(unsigned long), + bitmap = kcalloc(count / BITS_PER_LONG, sizeof(unsigned long), GFP_KERNEL); if (!bitmap) goto err_nodes; diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c index 80540c1c66dc..2da9f8a971a3 100644 --- a/drivers/gpu/drm/tegra/fb.c +++ b/drivers/gpu/drm/tegra/fb.c @@ -123,7 +123,7 @@ static struct tegra_fb *tegra_fb_alloc(struct drm_device *drm, if (!fb) return ERR_PTR(-ENOMEM); - fb->planes = kzalloc(num_planes * sizeof(*planes), GFP_KERNEL); + fb->planes = kcalloc(num_planes, sizeof(*planes), GFP_KERNEL); if (!fb->planes) { kfree(fb); return ERR_PTR(-ENOMEM); diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c index 857467022cf0..118840f87ce3 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.c +++ b/drivers/gpu/msm/kgsl_pwrctrl.c @@ -2386,8 +2386,9 @@ int kgsl_pwrctrl_init(struct kgsl_device *device) } } - pwr->bus_ib = kzalloc(bus_scale_table->num_usecases * - sizeof(*pwr->bus_ib), GFP_KERNEL); + pwr->bus_ib = kcalloc(bus_scale_table->num_usecases, + sizeof(*pwr->bus_ib), + GFP_KERNEL); if (pwr->bus_ib == NULL) { result = -ENOMEM; goto error_cleanup_pcl; diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index 23f312b4c6aa..daf1a9891f83 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c @@ -160,7 +160,7 @@ int hv_synic_alloc(void) memset(hv_cpu, 0, sizeof(*hv_cpu)); } - hv_context.hv_numa_map = kzalloc(sizeof(struct cpumask) * nr_node_ids, + hv_context.hv_numa_map = kcalloc(nr_node_ids, sizeof(struct cpumask), GFP_ATOMIC); if (hv_context.hv_numa_map == NULL) { pr_err("Unable to allocate NUMA map\n"); diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c index 74c1dfb8183b..69d6737f4fe7 100644 --- a/drivers/hv/ring_buffer.c +++ b/drivers/hv/ring_buffer.c @@ -178,7 +178,7 @@ int hv_ringbuffer_init(struct hv_ring_buffer_info *ring_info, * First page holds struct hv_ring_buffer, do wraparound mapping for * the rest. */ - pages_wraparound = kzalloc(sizeof(struct page *) * (page_cnt * 2 - 1), + pages_wraparound = kcalloc(page_cnt * 2 - 1, sizeof(struct page *), GFP_KERNEL); if (!pages_wraparound) return -ENOMEM; diff --git a/drivers/hwmon/acpi_power_meter.c b/drivers/hwmon/acpi_power_meter.c index e40d8907853b..2f40da04a944 100644 --- a/drivers/hwmon/acpi_power_meter.c +++ b/drivers/hwmon/acpi_power_meter.c @@ -575,8 +575,9 @@ static int read_domain_devices(struct acpi_power_meter_resource *resource) if (!pss->package.count) goto end; - resource->domain_devices = kzalloc(sizeof(struct acpi_device *) * - pss->package.count, GFP_KERNEL); + resource->domain_devices = kcalloc(pss->package.count, + sizeof(struct acpi_device *), + GFP_KERNEL); if (!resource->domain_devices) { res = -ENOMEM; goto end; @@ -796,7 +797,7 @@ static int read_capabilities(struct acpi_power_meter_resource *resource) goto error; } - *str = kzalloc(sizeof(u8) * (element->string.length + 1), + *str = kcalloc(element->string.length + 1, sizeof(u8), GFP_KERNEL); if (!*str) { res = -ENOMEM; diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index a42744c7665b..8991f1babf48 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c @@ -741,7 +741,7 @@ static int __init coretemp_init(void) return -ENODEV; max_packages = topology_max_packages(); - pkg_devices = kzalloc(max_packages * sizeof(struct platform_device *), + pkg_devices = kcalloc(max_packages, sizeof(struct platform_device *), GFP_KERNEL); if (!pkg_devices) return -ENOMEM; diff --git a/drivers/hwmon/i5k_amb.c b/drivers/hwmon/i5k_amb.c index 9397d2f0e79a..4f657ce8f951 100644 --- a/drivers/hwmon/i5k_amb.c +++ b/drivers/hwmon/i5k_amb.c @@ -274,7 +274,7 @@ static int i5k_amb_hwmon_init(struct platform_device *pdev) num_ambs += hweight16(data->amb_present[i] & 0x7fff); /* Set up sysfs stuff */ - data->attrs = kzalloc(sizeof(*data->attrs) * num_ambs * KNOBS_PER_AMB, + data->attrs = kzalloc(array3_size(num_ambs, KNOBS_PER_AMB, sizeof(*data->attrs)), GFP_KERNEL); if (!data->attrs) return -ENOMEM; diff --git a/drivers/hwmon/ibmpex.c b/drivers/hwmon/ibmpex.c index 21b9c72f16bd..ab72cabf5a95 100644 --- a/drivers/hwmon/ibmpex.c +++ b/drivers/hwmon/ibmpex.c @@ -387,7 +387,7 @@ static int ibmpex_find_sensors(struct ibmpex_bmc_data *data) return -ENOENT; data->num_sensors = err; - data->sensors = kzalloc(data->num_sensors * sizeof(*data->sensors), + data->sensors = kcalloc(data->num_sensors, sizeof(*data->sensors), GFP_KERNEL); if (!data->sensors) return -ENOMEM; diff --git a/drivers/i2c/busses/i2c-amd756-s4882.c b/drivers/i2c/busses/i2c-amd756-s4882.c index 65e324054970..a2f5f992af7a 100644 --- a/drivers/i2c/busses/i2c-amd756-s4882.c +++ b/drivers/i2c/busses/i2c-amd756-s4882.c @@ -169,12 +169,12 @@ static int __init amd756_s4882_init(void) printk(KERN_INFO "Enabling SMBus multiplexing for Tyan S4882\n"); /* Define the 5 virtual adapters and algorithms structures */ - if (!(s4882_adapter = kzalloc(5 * sizeof(struct i2c_adapter), + if (!(s4882_adapter = kcalloc(5, sizeof(struct i2c_adapter), GFP_KERNEL))) { error = -ENOMEM; goto ERROR1; } - if (!(s4882_algo = kzalloc(5 * sizeof(struct i2c_algorithm), + if (!(s4882_algo = kcalloc(5, sizeof(struct i2c_algorithm), GFP_KERNEL))) { error = -ENOMEM; goto ERROR2; diff --git a/drivers/i2c/busses/i2c-nforce2-s4985.c b/drivers/i2c/busses/i2c-nforce2-s4985.c index 88eda09e73c0..58a0fbf0e074 100644 --- a/drivers/i2c/busses/i2c-nforce2-s4985.c +++ b/drivers/i2c/busses/i2c-nforce2-s4985.c @@ -164,12 +164,12 @@ static int __init nforce2_s4985_init(void) printk(KERN_INFO "Enabling SMBus multiplexing for Tyan S4985\n"); /* Define the 5 virtual adapters and algorithms structures */ - s4985_adapter = kzalloc(5 * sizeof(struct i2c_adapter), GFP_KERNEL); + s4985_adapter = kcalloc(5, sizeof(struct i2c_adapter), GFP_KERNEL); if (!s4985_adapter) { error = -ENOMEM; goto ERROR1; } - s4985_algo = kzalloc(5 * sizeof(struct i2c_algorithm), GFP_KERNEL); + s4985_algo = kcalloc(5, sizeof(struct i2c_algorithm), GFP_KERNEL); if (!s4985_algo) { error = -ENOMEM; goto ERROR2; diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c index 3241bb9d6c18..f6a1272c5854 100644 --- a/drivers/i2c/busses/i2c-nforce2.c +++ b/drivers/i2c/busses/i2c-nforce2.c @@ -381,7 +381,7 @@ static int nforce2_probe(struct pci_dev *dev, const struct pci_device_id *id) int res1, res2; /* we support 2 SMBus adapters */ - smbuses = kzalloc(2 * sizeof(struct nforce2_smbus), GFP_KERNEL); + smbuses = kcalloc(2, sizeof(struct nforce2_smbus), GFP_KERNEL); if (!smbuses) return -ENOMEM; pci_set_drvdata(dev, smbuses); diff --git a/drivers/i2c/i2c-stub.c b/drivers/i2c/i2c-stub.c index 4a9ad91c5ba3..f31ec0861979 100644 --- a/drivers/i2c/i2c-stub.c +++ b/drivers/i2c/i2c-stub.c @@ -338,8 +338,9 @@ static int __init i2c_stub_allocate_banks(int i) chip->bank_mask >>= 1; } - chip->bank_words = kzalloc(chip->bank_mask * chip->bank_size * - sizeof(u16), GFP_KERNEL); + chip->bank_words = kcalloc(chip->bank_mask * chip->bank_size, + sizeof(u16), + GFP_KERNEL); if (!chip->bank_words) return -ENOMEM; diff --git a/drivers/ide/hpt366.c b/drivers/ide/hpt366.c index 4b5dc0162e67..e52c58c29d9a 100644 --- a/drivers/ide/hpt366.c +++ b/drivers/ide/hpt366.c @@ -1455,7 +1455,7 @@ static int hpt366_init_one(struct pci_dev *dev, const struct pci_device_id *id) if (info == &hpt36x || info == &hpt374) dev2 = pci_get_slot(dev->bus, dev->devfn + 1); - dyn_info = kzalloc(sizeof(*dyn_info) * (dev2 ? 2 : 1), GFP_KERNEL); + dyn_info = kcalloc(dev2 ? 2 : 1, sizeof(*dyn_info), GFP_KERNEL); if (dyn_info == NULL) { printk(KERN_ERR "%s %s: out of memory!\n", d.name, pci_name(dev)); diff --git a/drivers/ide/it821x.c b/drivers/ide/it821x.c index 04029d18a696..36a64c8ea575 100644 --- a/drivers/ide/it821x.c +++ b/drivers/ide/it821x.c @@ -652,7 +652,7 @@ static int it821x_init_one(struct pci_dev *dev, const struct pci_device_id *id) struct it821x_dev *itdevs; int rc; - itdevs = kzalloc(2 * sizeof(*itdevs), GFP_KERNEL); + itdevs = kcalloc(2, sizeof(*itdevs), GFP_KERNEL); if (itdevs == NULL) { printk(KERN_ERR DRV_NAME " %s: out of memory\n", pci_name(dev)); return -ENOMEM; diff --git a/drivers/iio/imu/adis_buffer.c b/drivers/iio/imu/adis_buffer.c index 36607d52fee0..76643c5571aa 100644 --- a/drivers/iio/imu/adis_buffer.c +++ b/drivers/iio/imu/adis_buffer.c @@ -38,7 +38,7 @@ int adis_update_scan_mode(struct iio_dev *indio_dev, if (!adis->xfer) return -ENOMEM; - adis->buffer = kzalloc(indio_dev->scan_bytes * 2, GFP_KERNEL); + adis->buffer = kcalloc(indio_dev->scan_bytes, 2, GFP_KERNEL); if (!adis->buffer) return -ENOMEM; diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c index 85dae32e9c4e..ba1b0f40df46 100644 --- a/drivers/iio/inkern.c +++ b/drivers/iio/inkern.c @@ -436,7 +436,7 @@ struct iio_channel *iio_channel_get_all(struct device *dev) } /* NULL terminated array to save passing size */ - chans = kzalloc(sizeof(*chans)*(nummaps + 1), GFP_KERNEL); + chans = kcalloc(nummaps + 1, sizeof(*chans), GFP_KERNEL); if (chans == NULL) { ret = -ENOMEM; goto error_ret; diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c index 7a32af7fee30..afbcbbe98464 100644 --- a/drivers/infiniband/core/cache.c +++ b/drivers/infiniband/core/cache.c @@ -1197,8 +1197,9 @@ int ib_cache_setup_one(struct ib_device *device) rwlock_init(&device->cache.lock); device->cache.ports = - kzalloc(sizeof(*device->cache.ports) * - (rdma_end_port(device) - rdma_start_port(device) + 1), GFP_KERNEL); + kcalloc(rdma_end_port(device) - rdma_start_port(device) + 1, + sizeof(*device->cache.ports), + GFP_KERNEL); if (!device->cache.ports) return -ENOMEM; diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c index 6b0d1d8609ca..848b5115def0 100644 --- a/drivers/infiniband/core/device.c +++ b/drivers/infiniband/core/device.c @@ -335,8 +335,8 @@ static int read_port_immutable(struct ib_device *device) * Therefore port_immutable is declared as a 1 based array with * potential empty slots at the beginning. */ - device->port_immutable = kzalloc(sizeof(*device->port_immutable) - * (end_port + 1), + device->port_immutable = kcalloc(end_port + 1, + sizeof(*device->port_immutable), GFP_KERNEL); if (!device->port_immutable) return -ENOMEM; diff --git a/drivers/infiniband/core/iwpm_util.c b/drivers/infiniband/core/iwpm_util.c index cb0fecc958b5..242d23ebba7d 100644 --- a/drivers/infiniband/core/iwpm_util.c +++ b/drivers/infiniband/core/iwpm_util.c @@ -56,14 +56,16 @@ int iwpm_init(u8 nl_client) int ret = 0; mutex_lock(&iwpm_admin_lock); if (atomic_read(&iwpm_admin.refcount) == 0) { - iwpm_hash_bucket = kzalloc(IWPM_MAPINFO_HASH_SIZE * - sizeof(struct hlist_head), GFP_KERNEL); + iwpm_hash_bucket = kcalloc(IWPM_MAPINFO_HASH_SIZE, + sizeof(struct hlist_head), + GFP_KERNEL); if (!iwpm_hash_bucket) { ret = -ENOMEM; goto init_exit; } - iwpm_reminfo_bucket = kzalloc(IWPM_REMINFO_HASH_SIZE * - sizeof(struct hlist_head), GFP_KERNEL); + iwpm_reminfo_bucket = kcalloc(IWPM_REMINFO_HASH_SIZE, + sizeof(struct hlist_head), + GFP_KERNEL); if (!iwpm_reminfo_bucket) { kfree(iwpm_hash_bucket); ret = -ENOMEM; diff --git a/drivers/infiniband/hw/cxgb3/cxio_hal.c b/drivers/infiniband/hw/cxgb3/cxio_hal.c index 3eff6541bd6f..7da0d365ebd2 100644 --- a/drivers/infiniband/hw/cxgb3/cxio_hal.c +++ b/drivers/infiniband/hw/cxgb3/cxio_hal.c @@ -279,7 +279,7 @@ int cxio_create_qp(struct cxio_rdev *rdev_p, u32 kernel_domain, if (!wq->qpid) return -ENOMEM; - wq->rq = kzalloc(depth * sizeof(struct t3_swrq), GFP_KERNEL); + wq->rq = kcalloc(depth, sizeof(struct t3_swrq), GFP_KERNEL); if (!wq->rq) goto err1; @@ -287,7 +287,7 @@ int cxio_create_qp(struct cxio_rdev *rdev_p, u32 kernel_domain, if (!wq->rq_addr) goto err2; - wq->sq = kzalloc(depth * sizeof(struct t3_swsq), GFP_KERNEL); + wq->sq = kcalloc(depth, sizeof(struct t3_swsq), GFP_KERNEL); if (!wq->sq) goto err3; diff --git a/drivers/infiniband/hw/cxgb4/device.c b/drivers/infiniband/hw/cxgb4/device.c index 99f232e3ea93..ef64a8f5f412 100644 --- a/drivers/infiniband/hw/cxgb4/device.c +++ b/drivers/infiniband/hw/cxgb4/device.c @@ -868,8 +868,9 @@ static int c4iw_rdev_open(struct c4iw_rdev *rdev) rdev->status_page->cq_size = rdev->lldi.vr->cq.size; if (c4iw_wr_log) { - rdev->wr_log = kzalloc((1 << c4iw_wr_log_size_order) * - sizeof(*rdev->wr_log), GFP_KERNEL); + rdev->wr_log = kcalloc(1 << c4iw_wr_log_size_order, + sizeof(*rdev->wr_log), + GFP_KERNEL); if (rdev->wr_log) { rdev->wr_log_size = 1 << c4iw_wr_log_size_order; atomic_set(&rdev->wr_log_idx, 0); @@ -1458,7 +1459,7 @@ static void recover_queues(struct uld_ctx *ctx) ctx->dev->db_state = RECOVERY; idr_for_each(&ctx->dev->qpidr, count_qps, &count); - qp_list.qps = kzalloc(count * sizeof *qp_list.qps, GFP_ATOMIC); + qp_list.qps = kcalloc(count, sizeof(*qp_list.qps), GFP_ATOMIC); if (!qp_list.qps) { spin_unlock_irq(&ctx->dev->lock); return; diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c index 24952af51a54..96cde77717c9 100644 --- a/drivers/infiniband/hw/cxgb4/qp.c +++ b/drivers/infiniband/hw/cxgb4/qp.c @@ -216,15 +216,15 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq, } if (!user) { - wq->sq.sw_sq = kzalloc(wq->sq.size * sizeof *wq->sq.sw_sq, - GFP_KERNEL); + wq->sq.sw_sq = kcalloc(wq->sq.size, sizeof(*wq->sq.sw_sq), + GFP_KERNEL); if (!wq->sq.sw_sq) { ret = -ENOMEM; goto free_rq_qid; } - wq->rq.sw_rq = kzalloc(wq->rq.size * sizeof *wq->rq.sw_rq, - GFP_KERNEL); + wq->rq.sw_rq = kcalloc(wq->rq.size, sizeof(*wq->rq.sw_rq), + GFP_KERNEL); if (!wq->rq.sw_rq) { ret = -ENOMEM; goto free_sw_sq; diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c index c69158ccab82..9e30791f7dcf 100644 --- a/drivers/infiniband/hw/mlx4/mad.c +++ b/drivers/infiniband/hw/mlx4/mad.c @@ -1613,7 +1613,8 @@ static int mlx4_ib_alloc_pv_bufs(struct mlx4_ib_demux_pv_ctx *ctx, tun_qp = &ctx->qp[qp_type]; - tun_qp->ring = kzalloc(sizeof (struct mlx4_ib_buf) * MLX4_NUM_TUNNEL_BUFS, + tun_qp->ring = kcalloc(MLX4_NUM_TUNNEL_BUFS, + sizeof(struct mlx4_ib_buf), GFP_KERNEL); if (!tun_qp->ring) return -ENOMEM; diff --git a/drivers/infiniband/hw/mthca/mthca_mr.c b/drivers/infiniband/hw/mthca/mthca_mr.c index dc3c2346045c..6686042aafb4 100644 --- a/drivers/infiniband/hw/mthca/mthca_mr.c +++ b/drivers/infiniband/hw/mthca/mthca_mr.c @@ -144,7 +144,7 @@ static int mthca_buddy_init(struct mthca_buddy *buddy, int max_order) buddy->max_order = max_order; spin_lock_init(&buddy->lock); - buddy->bits = kzalloc((buddy->max_order + 1) * sizeof (long *), + buddy->bits = kcalloc(buddy->max_order + 1, sizeof(long *), GFP_KERNEL); buddy->num_free = kcalloc((buddy->max_order + 1), sizeof *buddy->num_free, GFP_KERNEL); diff --git a/drivers/infiniband/hw/mthca/mthca_profile.c b/drivers/infiniband/hw/mthca/mthca_profile.c index 15d064479ef6..7ea970774839 100644 --- a/drivers/infiniband/hw/mthca/mthca_profile.c +++ b/drivers/infiniband/hw/mthca/mthca_profile.c @@ -79,7 +79,7 @@ s64 mthca_make_profile(struct mthca_dev *dev, struct mthca_resource *profile; int i, j; - profile = kzalloc(MTHCA_RES_NUM * sizeof *profile, GFP_KERNEL); + profile = kcalloc(MTHCA_RES_NUM, sizeof(*profile), GFP_KERNEL); if (!profile) return -ENOMEM; diff --git a/drivers/infiniband/hw/nes/nes_mgt.c b/drivers/infiniband/hw/nes/nes_mgt.c index 77226cf4ea02..d4afee7860d8 100644 --- a/drivers/infiniband/hw/nes/nes_mgt.c +++ b/drivers/infiniband/hw/nes/nes_mgt.c @@ -877,7 +877,8 @@ int nes_init_mgt_qp(struct nes_device *nesdev, struct net_device *netdev, struct int ret; /* Allocate space the all mgt QPs once */ - mgtvnic = kzalloc(NES_MGT_QP_COUNT * sizeof(struct nes_vnic_mgt), GFP_KERNEL); + mgtvnic = kcalloc(NES_MGT_QP_COUNT, sizeof(struct nes_vnic_mgt), + GFP_KERNEL); if (!mgtvnic) return -ENOMEM; diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c index 442b9bdc0f03..6b6ee9b692d2 100644 --- a/drivers/infiniband/hw/nes/nes_verbs.c +++ b/drivers/infiniband/hw/nes/nes_verbs.c @@ -2255,8 +2255,9 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, ibmr = ERR_PTR(-ENOMEM); goto reg_user_mr_err; } - root_vpbl.leaf_vpbl = kzalloc(sizeof(*root_vpbl.leaf_vpbl)*1024, - GFP_KERNEL); + root_vpbl.leaf_vpbl = kcalloc(1024, + sizeof(*root_vpbl.leaf_vpbl), + GFP_KERNEL); if (!root_vpbl.leaf_vpbl) { ib_umem_release(region); pci_free_consistent(nesdev->pcidev, 8192, root_vpbl.pbl_vbase, diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_hw.c b/drivers/infiniband/hw/ocrdma/ocrdma_hw.c index 1ba296aeabca..cb042baaf235 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_hw.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_hw.c @@ -3108,7 +3108,7 @@ static int ocrdma_create_eqs(struct ocrdma_dev *dev) if (!num_eq) return -EINVAL; - dev->eq_tbl = kzalloc(sizeof(struct ocrdma_eq) * num_eq, GFP_KERNEL); + dev->eq_tbl = kcalloc(num_eq, sizeof(struct ocrdma_eq), GFP_KERNEL); if (!dev->eq_tbl) return -ENOMEM; diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_main.c b/drivers/infiniband/hw/ocrdma/ocrdma_main.c index fbfbd9e96147..4682597fe016 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_main.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_main.c @@ -223,19 +223,20 @@ static int ocrdma_register_device(struct ocrdma_dev *dev) static int ocrdma_alloc_resources(struct ocrdma_dev *dev) { mutex_init(&dev->dev_lock); - dev->cq_tbl = kzalloc(sizeof(struct ocrdma_cq *) * - OCRDMA_MAX_CQ, GFP_KERNEL); + dev->cq_tbl = kcalloc(OCRDMA_MAX_CQ, sizeof(struct ocrdma_cq *), + GFP_KERNEL); if (!dev->cq_tbl) goto alloc_err; if (dev->attr.max_qp) { - dev->qp_tbl = kzalloc(sizeof(struct ocrdma_qp *) * - OCRDMA_MAX_QP, GFP_KERNEL); + dev->qp_tbl = kcalloc(OCRDMA_MAX_QP, + sizeof(struct ocrdma_qp *), + GFP_KERNEL); if (!dev->qp_tbl) goto alloc_err; } - dev->stag_arr = kzalloc(sizeof(u64) * OCRDMA_MAX_STAG, GFP_KERNEL); + dev->stag_arr = kcalloc(OCRDMA_MAX_STAG, sizeof(u64), GFP_KERNEL); if (dev->stag_arr == NULL) goto alloc_err; diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c index 1847696c17a6..df195904b2e6 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c @@ -880,8 +880,8 @@ static int ocrdma_build_pbl_tbl(struct ocrdma_dev *dev, struct ocrdma_hw_mr *mr) void *va; dma_addr_t pa; - mr->pbl_table = kzalloc(sizeof(struct ocrdma_pbl) * - mr->num_pbls, GFP_KERNEL); + mr->pbl_table = kcalloc(mr->num_pbls, sizeof(struct ocrdma_pbl), + GFP_KERNEL); if (!mr->pbl_table) return -ENOMEM; @@ -1361,12 +1361,12 @@ static void ocrdma_set_qp_db(struct ocrdma_dev *dev, struct ocrdma_qp *qp, static int ocrdma_alloc_wr_id_tbl(struct ocrdma_qp *qp) { qp->wqe_wr_id_tbl = - kzalloc(sizeof(*(qp->wqe_wr_id_tbl)) * qp->sq.max_cnt, + kcalloc(qp->sq.max_cnt, sizeof(*(qp->wqe_wr_id_tbl)), GFP_KERNEL); if (qp->wqe_wr_id_tbl == NULL) return -ENOMEM; qp->rqe_wr_id_tbl = - kzalloc(sizeof(u64) * qp->rq.max_cnt, GFP_KERNEL); + kcalloc(qp->rq.max_cnt, sizeof(u64), GFP_KERNEL); if (qp->rqe_wr_id_tbl == NULL) return -ENOMEM; @@ -1903,8 +1903,8 @@ struct ib_srq *ocrdma_create_srq(struct ib_pd *ibpd, if (udata == NULL) { status = -ENOMEM; - srq->rqe_wr_id_tbl = kzalloc(sizeof(u64) * srq->rq.max_cnt, - GFP_KERNEL); + srq->rqe_wr_id_tbl = kcalloc(srq->rq.max_cnt, sizeof(u64), + GFP_KERNEL); if (srq->rqe_wr_id_tbl == NULL) goto arm_err; diff --git a/drivers/infiniband/hw/qedr/main.c b/drivers/infiniband/hw/qedr/main.c index 3e48ed64760b..bf9875f85a1b 100644 --- a/drivers/infiniband/hw/qedr/main.c +++ b/drivers/infiniband/hw/qedr/main.c @@ -234,8 +234,8 @@ static int qedr_alloc_resources(struct qedr_dev *dev) u16 n_entries; int i, rc; - dev->sgid_tbl = kzalloc(sizeof(union ib_gid) * - QEDR_MAX_SGID, GFP_KERNEL); + dev->sgid_tbl = kcalloc(QEDR_MAX_SGID, sizeof(union ib_gid), + GFP_KERNEL); if (!dev->sgid_tbl) return -ENOMEM; diff --git a/drivers/infiniband/hw/qedr/verbs.c b/drivers/infiniband/hw/qedr/verbs.c index 6ae72accae3d..cc8f95b038f8 100644 --- a/drivers/infiniband/hw/qedr/verbs.c +++ b/drivers/infiniband/hw/qedr/verbs.c @@ -1506,7 +1506,7 @@ static int qedr_create_kernel_qp(struct qedr_dev *dev, qp->sq.max_wr = min_t(u32, attrs->cap.max_send_wr * dev->wq_multiplier, dev->attr.max_sqe); - qp->wqe_wr_id = kzalloc(qp->sq.max_wr * sizeof(*qp->wqe_wr_id), + qp->wqe_wr_id = kcalloc(qp->sq.max_wr, sizeof(*qp->wqe_wr_id), GFP_KERNEL); if (!qp->wqe_wr_id) { DP_ERR(dev, "create qp: failed SQ shadow memory allocation\n"); @@ -1524,7 +1524,7 @@ static int qedr_create_kernel_qp(struct qedr_dev *dev, qp->rq.max_wr = (u16) max_t(u32, attrs->cap.max_recv_wr, 1); /* Allocate driver internal RQ array */ - qp->rqe_wr_id = kzalloc(qp->rq.max_wr * sizeof(*qp->rqe_wr_id), + qp->rqe_wr_id = kcalloc(qp->rq.max_wr, sizeof(*qp->rqe_wr_id), GFP_KERNEL); if (!qp->rqe_wr_id) { DP_ERR(dev, diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c index 10d675a1991c..e393585f9ef1 100644 --- a/drivers/infiniband/hw/qib/qib_iba7322.c +++ b/drivers/infiniband/hw/qib/qib_iba7322.c @@ -7330,8 +7330,9 @@ struct qib_devdata *qib_init_iba7322_funcs(struct pci_dev *pdev, actual_cnt -= dd->num_pports; tabsize = actual_cnt; - dd->cspec->msix_entries = kzalloc(tabsize * - sizeof(struct qib_msix_entry), GFP_KERNEL); + dd->cspec->msix_entries = kcalloc(tabsize, + sizeof(struct qib_msix_entry), + GFP_KERNEL); if (!dd->cspec->msix_entries) tabsize = 0; diff --git a/drivers/infiniband/hw/qib/qib_init.c b/drivers/infiniband/hw/qib/qib_init.c index 3157408c6df2..adfd6852a870 100644 --- a/drivers/infiniband/hw/qib/qib_init.c +++ b/drivers/infiniband/hw/qib/qib_init.c @@ -1141,8 +1141,8 @@ struct qib_devdata *qib_alloc_devdata(struct pci_dev *pdev, size_t extra) if (!qib_cpulist_count) { u32 count = num_online_cpus(); - qib_cpulist = kzalloc(BITS_TO_LONGS(count) * - sizeof(long), GFP_KERNEL); + qib_cpulist = kcalloc(BITS_TO_LONGS(count), sizeof(long), + GFP_KERNEL); if (qib_cpulist) qib_cpulist_count = count; } diff --git a/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c b/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c index 092d4e11a633..2e596d09074f 100644 --- a/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c +++ b/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c @@ -545,7 +545,7 @@ alloc_res_chunk_list(struct usnic_vnic *vnic, /* Do Nothing */ } - res_chunk_list = kzalloc(sizeof(*res_chunk_list)*(res_lst_sz+1), + res_chunk_list = kcalloc(res_lst_sz + 1, sizeof(*res_chunk_list), GFP_ATOMIC); if (!res_chunk_list) return ERR_PTR(-ENOMEM); diff --git a/drivers/infiniband/hw/usnic/usnic_vnic.c b/drivers/infiniband/hw/usnic/usnic_vnic.c index e7b0030254da..ebe08f348453 100644 --- a/drivers/infiniband/hw/usnic/usnic_vnic.c +++ b/drivers/infiniband/hw/usnic/usnic_vnic.c @@ -312,7 +312,7 @@ static int usnic_vnic_alloc_res_chunk(struct usnic_vnic *vnic, } chunk->cnt = chunk->free_cnt = cnt; - chunk->res = kzalloc(sizeof(*(chunk->res))*cnt, GFP_KERNEL); + chunk->res = kcalloc(cnt, sizeof(*(chunk->res)), GFP_KERNEL); if (!chunk->res) return -ENOMEM; diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index caae4bfab950..9fbecfd96785 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -1507,7 +1507,7 @@ static int ipoib_neigh_hash_init(struct ipoib_dev_priv *priv) return -ENOMEM; set_bit(IPOIB_STOP_NEIGH_GC, &priv->flags); size = roundup_pow_of_two(arp_tbl.gc_thresh3); - buckets = kzalloc(size * sizeof(*buckets), GFP_KERNEL); + buckets = kcalloc(size, sizeof(*buckets), GFP_KERNEL); if (!buckets) { kfree(htbl); return -ENOMEM; @@ -1669,8 +1669,9 @@ static int ipoib_dev_init_default(struct net_device *dev) netif_napi_add(dev, &priv->napi, ipoib_poll, NAPI_POLL_WEIGHT); /* Allocate RX/TX "rings" to hold queued skbs */ - priv->rx_ring = kzalloc(ipoib_recvq_size * sizeof *priv->rx_ring, - GFP_KERNEL); + priv->rx_ring = kcalloc(ipoib_recvq_size, + sizeof(*priv->rx_ring), + GFP_KERNEL); if (!priv->rx_ring) goto out; diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index ee3f630c9217..907aec3520ec 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c @@ -181,8 +181,9 @@ isert_alloc_rx_descriptors(struct isert_conn *isert_conn) u64 dma_addr; int i, j; - isert_conn->rx_descs = kzalloc(ISERT_QP_MAX_RECV_DTOS * - sizeof(struct iser_rx_desc), GFP_KERNEL); + isert_conn->rx_descs = kcalloc(ISERT_QP_MAX_RECV_DTOS, + sizeof(struct iser_rx_desc), + GFP_KERNEL); if (!isert_conn->rx_descs) return -ENOMEM; diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c index 616fdd94b069..840e53732753 100644 --- a/drivers/input/keyboard/omap4-keypad.c +++ b/drivers/input/keyboard/omap4-keypad.c @@ -339,7 +339,8 @@ static int omap4_keypad_probe(struct platform_device *pdev) keypad_data->row_shift = get_count_order(keypad_data->cols); max_keys = keypad_data->rows << keypad_data->row_shift; - keypad_data->keymap = kzalloc(max_keys * sizeof(keypad_data->keymap[0]), + keypad_data->keymap = kcalloc(max_keys, + sizeof(keypad_data->keymap[0]), GFP_KERNEL); if (!keypad_data->keymap) { dev_err(&pdev->dev, "Not enough memory for keymap\n"); diff --git a/drivers/input/touchscreen/hxchipset/himax_common.c b/drivers/input/touchscreen/hxchipset/himax_common.c index 1667d823ac71..f9398babb5ab 100644 --- a/drivers/input/touchscreen/hxchipset/himax_common.c +++ b/drivers/input/touchscreen/hxchipset/himax_common.c @@ -885,7 +885,9 @@ int himax_report_data_init(void) D("%s: g_hx_rawdata_size:%d, hx_touch_data->touch_info_size:%d\n", __func__, hx_touch_data->rawdata_size, hx_touch_data->touch_info_size); - hx_touch_data->hx_coord_buf = kzalloc(sizeof(uint8_t) * (hx_touch_data->touch_info_size), GFP_KERNEL); + hx_touch_data->hx_coord_buf = kcalloc(hx_touch_data->touch_info_size, + sizeof(uint8_t), + GFP_KERNEL); if (hx_touch_data->hx_coord_buf == NULL) goto mem_alloc_fail; @@ -893,29 +895,38 @@ int himax_report_data_init(void) g_target_report_data = kzalloc(sizeof(struct himax_target_report_data), GFP_KERNEL); if (g_target_report_data == NULL) goto mem_alloc_fail; - g_target_report_data->x = kzalloc(sizeof(int)*(ic_data->HX_MAX_PT), GFP_KERNEL); + g_target_report_data->x = kcalloc(ic_data->HX_MAX_PT, sizeof(int), + GFP_KERNEL); if (g_target_report_data->x == NULL) goto mem_alloc_fail; - g_target_report_data->y = kzalloc(sizeof(int)*(ic_data->HX_MAX_PT), GFP_KERNEL); + g_target_report_data->y = kcalloc(ic_data->HX_MAX_PT, sizeof(int), + GFP_KERNEL); if (g_target_report_data->y == NULL) goto mem_alloc_fail; - g_target_report_data->w = kzalloc(sizeof(int)*(ic_data->HX_MAX_PT), GFP_KERNEL); + g_target_report_data->w = kcalloc(ic_data->HX_MAX_PT, sizeof(int), + GFP_KERNEL); if (g_target_report_data->w == NULL) goto mem_alloc_fail; - g_target_report_data->finger_id = kzalloc(sizeof(int)*(ic_data->HX_MAX_PT), GFP_KERNEL); + g_target_report_data->finger_id = kcalloc(ic_data->HX_MAX_PT, + sizeof(int), + GFP_KERNEL); if (g_target_report_data->finger_id == NULL) goto mem_alloc_fail; #ifdef HX_SMART_WAKEUP g_target_report_data->SMWP_event_chk = 0; #endif - hx_touch_data->hx_rawdata_buf = kzalloc(sizeof(uint8_t) * (hx_touch_data->touch_all_size - hx_touch_data->touch_info_size), GFP_KERNEL); + hx_touch_data->hx_rawdata_buf = kcalloc(hx_touch_data->touch_all_size - hx_touch_data->touch_info_size, + sizeof(uint8_t), + GFP_KERNEL); if (hx_touch_data->hx_rawdata_buf == NULL) goto mem_alloc_fail; #if defined(HX_SMART_WAKEUP) - hx_touch_data->hx_event_buf = kzalloc(sizeof(uint8_t) * (hx_touch_data->event_size), GFP_KERNEL); + hx_touch_data->hx_event_buf = kcalloc(hx_touch_data->event_size, + sizeof(uint8_t), + GFP_KERNEL); if (hx_touch_data->hx_event_buf == NULL) goto mem_alloc_fail; diff --git a/drivers/input/touchscreen/hxchipset/himax_debug.c b/drivers/input/touchscreen/hxchipset/himax_debug.c index 9d7f5b99a4cb..a38dde9dc245 100644 --- a/drivers/input/touchscreen/hxchipset/himax_debug.c +++ b/drivers/input/touchscreen/hxchipset/himax_debug.c @@ -853,19 +853,22 @@ void setYChannel(uint8_t y) } void setMutualBuffer(void) { - diag_mutual = kzalloc(x_channel * y_channel * sizeof(int32_t), GFP_KERNEL); + diag_mutual = kcalloc(x_channel * y_channel, sizeof(int32_t), + GFP_KERNEL); if (!diag_mutual) E("%s: allocate memory failed!\n", __func__); } void setMutualNewBuffer(void) { - diag_mutual_new = kzalloc(x_channel * y_channel * sizeof(int32_t), GFP_KERNEL); + diag_mutual_new = kcalloc(x_channel * y_channel, sizeof(int32_t), + GFP_KERNEL); if (!diag_mutual_new) E("%s: allocate memory failed!\n", __func__); } void setMutualOldBuffer(void) { - diag_mutual_old = kzalloc(x_channel * y_channel * sizeof(int32_t), GFP_KERNEL); + diag_mutual_old = kcalloc(x_channel * y_channel, sizeof(int32_t), + GFP_KERNEL); if (!diag_mutual_old) E("%s: allocate memory failed!\n", __func__); } @@ -898,7 +901,8 @@ void setYChannel_2(uint8_t y) void setMutualBuffer_2(void) { - diag_mutual_2 = kzalloc(x_channel_2 * y_channel_2 * sizeof(int32_t), GFP_KERNEL); + diag_mutual_2 = kcalloc(x_channel_2 * y_channel_2, sizeof(int32_t), + GFP_KERNEL); } #endif diff --git a/drivers/input/touchscreen/st/fts.c b/drivers/input/touchscreen/st/fts.c index a10a2afbb50b..910dfed9cddd 100644 --- a/drivers/input/touchscreen/st/fts.c +++ b/drivers/input/touchscreen/st/fts.c @@ -3470,8 +3470,9 @@ static int fts_interrupt_install(struct fts_ts_info *info) { int i, error = 0; - info->event_dispatch_table = kzalloc(sizeof(event_dispatch_handler_t) - * EVENTID_LAST, GFP_KERNEL); + info->event_dispatch_table = kcalloc(EVENTID_LAST, + sizeof(event_dispatch_handler_t), + GFP_KERNEL); if (!info->event_dispatch_table) { logError(1, "%s OOM allocating event dispatch table\n", tag); diff --git a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.c b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.c index 5fa4cf353b14..3194a9b23df5 100644 --- a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.c +++ b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.c @@ -2724,7 +2724,7 @@ static int synaptics_rmi4_f1a_alloc_mem(struct synaptics_rmi4_data *rmi4_data, f1a->max_count = f1a->button_query.max_button_count + 1; - f1a->button_control.txrx_map = kzalloc(f1a->max_count * 2, GFP_KERNEL); + f1a->button_control.txrx_map = kcalloc(f1a->max_count, 2, GFP_KERNEL); if (!f1a->button_control.txrx_map) { dev_err(rmi4_data->pdev->dev.parent, "%s: Failed to alloc mem for tx rx mapping\n", diff --git a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_gesture.c b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_gesture.c index 1820abe6ce3b..b04af90d8f7b 100644 --- a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_gesture.c +++ b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_gesture.c @@ -2011,9 +2011,9 @@ static int synaptics_rmi4_udg_init(struct synaptics_rmi4_data *rmi4_data) } #ifdef STORE_GESTURES - udg->storage_buf = kzalloc( - udg->template_data_size * udg->gestures_to_store, - GFP_KERNEL); + udg->storage_buf = kcalloc(udg->template_data_size, + udg->gestures_to_store, + GFP_KERNEL); if (!udg->storage_buf) { dev_err(rmi4_data->pdev->dev.parent, "%s: Failed to alloc mem for storage_buf\n", diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index 1f527ca60955..e3b3aa16cf1b 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -1464,7 +1464,7 @@ int dmar_enable_qi(struct intel_iommu *iommu) qi->desc = page_address(desc_page); - qi->desc_status = kzalloc(QI_LENGTH * sizeof(int), GFP_ATOMIC); + qi->desc_status = kcalloc(QI_LENGTH, sizeof(int), GFP_ATOMIC); if (!qi->desc_status) { free_page((unsigned long) qi->desc); kfree(qi); diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index db1b546134f5..e2bfb8795816 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -3197,7 +3197,7 @@ static int copy_translation_tables(struct intel_iommu *iommu) /* This is too big for the stack - allocate it from slab */ ctxt_table_entries = ext ? 512 : 256; ret = -ENOMEM; - ctxt_tbls = kzalloc(ctxt_table_entries * sizeof(void *), GFP_KERNEL); + ctxt_tbls = kcalloc(ctxt_table_entries, sizeof(void *), GFP_KERNEL); if (!ctxt_tbls) goto out_unmap; @@ -4086,7 +4086,7 @@ static int iommu_suspend(void) unsigned long flag; for_each_active_iommu(iommu, drhd) { - iommu->iommu_state = kzalloc(sizeof(u32) * MAX_SR_DMAR_REGS, + iommu->iommu_state = kcalloc(MAX_SR_DMAR_REGS, sizeof(u32), GFP_ATOMIC); if (!iommu->iommu_state) goto nomem; diff --git a/drivers/ipack/carriers/tpci200.c b/drivers/ipack/carriers/tpci200.c index 9b23843dcad4..a16b320739b4 100644 --- a/drivers/ipack/carriers/tpci200.c +++ b/drivers/ipack/carriers/tpci200.c @@ -457,8 +457,8 @@ static int tpci200_install(struct tpci200_board *tpci200) { int res; - tpci200->slots = kzalloc( - TPCI200_NB_SLOT * sizeof(struct tpci200_slot), GFP_KERNEL); + tpci200->slots = kcalloc(TPCI200_NB_SLOT, sizeof(struct tpci200_slot), + GFP_KERNEL); if (tpci200->slots == NULL) return -ENOMEM; diff --git a/drivers/irqchip/irq-alpine-msi.c b/drivers/irqchip/irq-alpine-msi.c index 63d980995d17..23a3b877f7f1 100644 --- a/drivers/irqchip/irq-alpine-msi.c +++ b/drivers/irqchip/irq-alpine-msi.c @@ -268,7 +268,8 @@ static int alpine_msix_init(struct device_node *node, goto err_priv; } - priv->msi_map = kzalloc(sizeof(*priv->msi_map) * BITS_TO_LONGS(priv->num_spis), + priv->msi_map = kcalloc(BITS_TO_LONGS(priv->num_spis), + sizeof(*priv->msi_map), GFP_KERNEL); if (!priv->msi_map) { ret = -ENOMEM; diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c index 993a8426a453..87bb60063f8b 100644 --- a/drivers/irqchip/irq-gic-v2m.c +++ b/drivers/irqchip/irq-gic-v2m.c @@ -363,7 +363,7 @@ static int __init gicv2m_init_one(struct fwnode_handle *fwnode, break; } - v2m->bm = kzalloc(sizeof(long) * BITS_TO_LONGS(v2m->nr_spis), + v2m->bm = kcalloc(BITS_TO_LONGS(v2m->nr_spis), sizeof(long), GFP_KERNEL); if (!v2m->bm) { ret = -ENOMEM; diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 71e5e6c5e8da..a2d5c4744c0b 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -1153,7 +1153,7 @@ static int its_vlpi_map(struct irq_data *d, struct its_cmd_info *info) if (!its_dev->event_map.vm) { struct its_vlpi_map *maps; - maps = kzalloc(sizeof(*maps) * its_dev->event_map.nr_lpis, + maps = kcalloc(its_dev->event_map.nr_lpis, sizeof(*maps), GFP_KERNEL); if (!maps) { ret = -ENOMEM; @@ -1337,7 +1337,7 @@ static int __init its_lpi_init(u32 id_bits) { lpi_chunks = its_lpi_to_chunk(1UL << id_bits); - lpi_bitmap = kzalloc(BITS_TO_LONGS(lpi_chunks) * sizeof(long), + lpi_bitmap = kcalloc(BITS_TO_LONGS(lpi_chunks), sizeof(long), GFP_KERNEL); if (!lpi_bitmap) { lpi_chunks = 0; @@ -1371,7 +1371,8 @@ static unsigned long *its_lpi_alloc_chunks(int nr_irqs, int *base, int *nr_ids) if (!nr_chunks) goto out; - bitmap = kzalloc(BITS_TO_LONGS(nr_chunks * IRQS_PER_CHUNK) * sizeof (long), + bitmap = kcalloc(BITS_TO_LONGS(nr_chunks * IRQS_PER_CHUNK), + sizeof(long), GFP_ATOMIC); if (!bitmap) goto out; @@ -1734,7 +1735,7 @@ static int its_alloc_tables(struct its_node *its) static int its_alloc_collections(struct its_node *its) { - its->collections = kzalloc(nr_cpu_ids * sizeof(*its->collections), + its->collections = kcalloc(nr_cpu_ids, sizeof(*its->collections), GFP_KERNEL); if (!its->collections) return -ENOMEM; @@ -2044,10 +2045,10 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id, if (alloc_lpis) { lpi_map = its_lpi_alloc_chunks(nvecs, &lpi_base, &nr_lpis); if (lpi_map) - col_map = kzalloc(sizeof(*col_map) * nr_lpis, + col_map = kcalloc(nr_lpis, sizeof(*col_map), GFP_KERNEL); } else { - col_map = kzalloc(sizeof(*col_map) * nr_ites, GFP_KERNEL); + col_map = kcalloc(nr_ites, sizeof(*col_map), GFP_KERNEL); nr_lpis = 0; lpi_base = 0; } @@ -2893,7 +2894,7 @@ static int its_init_vpe_domain(void) its = list_first_entry(&its_nodes, struct its_node, entry); entries = roundup_pow_of_two(nr_cpu_ids); - vpe_proxy.vpes = kzalloc(sizeof(*vpe_proxy.vpes) * entries, + vpe_proxy.vpes = kcalloc(entries, sizeof(*vpe_proxy.vpes), GFP_KERNEL); if (!vpe_proxy.vpes) { pr_err("ITS: Can't allocate GICv4 proxy device array\n"); diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index fb16d671bfa8..755418aab90b 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -1273,7 +1273,7 @@ static void __init gic_populate_ppi_partitions(struct device_node *gic_node) if (!nr_parts) goto out_put_node; - parts = kzalloc(sizeof(*parts) * nr_parts, GFP_KERNEL); + parts = kcalloc(nr_parts, sizeof(*parts), GFP_KERNEL); if (WARN_ON(!parts)) goto out_put_node; @@ -1395,7 +1395,8 @@ static int __init gicv3_of_init(struct device_node *node, struct device_node *pa if (of_property_read_u32(node, "#redistributor-regions", &nr_redist_regions)) nr_redist_regions = 1; - rdist_regs = kzalloc(sizeof(*rdist_regs) * nr_redist_regions, GFP_KERNEL); + rdist_regs = kcalloc(nr_redist_regions, sizeof(*rdist_regs), + GFP_KERNEL); if (!rdist_regs) { err = -ENOMEM; goto out_unmap_dist; diff --git a/drivers/irqchip/irq-partition-percpu.c b/drivers/irqchip/irq-partition-percpu.c index ccd72c2cbc23..1f7cc5933cd5 100644 --- a/drivers/irqchip/irq-partition-percpu.c +++ b/drivers/irqchip/irq-partition-percpu.c @@ -229,7 +229,7 @@ struct partition_desc *partition_create_desc(struct fwnode_handle *fwnode, goto out; desc->domain = d; - desc->bitmap = kzalloc(sizeof(long) * BITS_TO_LONGS(nr_parts), + desc->bitmap = kcalloc(BITS_TO_LONGS(nr_parts), sizeof(long), GFP_KERNEL); if (WARN_ON(!desc->bitmap)) goto out; diff --git a/drivers/irqchip/irq-s3c24xx.c b/drivers/irqchip/irq-s3c24xx.c index c25ce5af091a..e1eb8eeac4b4 100644 --- a/drivers/irqchip/irq-s3c24xx.c +++ b/drivers/irqchip/irq-s3c24xx.c @@ -1261,7 +1261,7 @@ static int __init s3c_init_intc_of(struct device_node *np, return -ENOMEM; intc->domain = domain; - intc->irqs = kzalloc(sizeof(struct s3c_irq_data) * 32, + intc->irqs = kcalloc(32, sizeof(struct s3c_irq_data), GFP_KERNEL); if (!intc->irqs) { kfree(intc); diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index da45049de97e..5919baa3828a 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -1268,7 +1268,7 @@ static int __init capinc_tty_init(void) if (capi_ttyminors <= 0) capi_ttyminors = CAPINC_NR_PORTS; - capiminors = kzalloc(sizeof(struct capiminor *) * capi_ttyminors, + capiminors = kcalloc(capi_ttyminors, sizeof(struct capiminor *), GFP_KERNEL); if (!capiminors) return -ENOMEM; diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c index 632002a95cb3..fcf34fe704fe 100644 --- a/drivers/isdn/gigaset/capi.c +++ b/drivers/isdn/gigaset/capi.c @@ -1370,7 +1370,7 @@ static void do_connect_req(struct gigaset_capi_ctr *iif, cmsg->adr.adrPLCI |= (bcs->channel + 1) << 8; /* build command table */ - commands = kzalloc(AT_NUM * (sizeof *commands), GFP_KERNEL); + commands = kcalloc(AT_NUM, sizeof(*commands), GFP_KERNEL); if (!commands) goto oom; diff --git a/drivers/isdn/gigaset/i4l.c b/drivers/isdn/gigaset/i4l.c index 2d75329007f1..b5b389e95edd 100644 --- a/drivers/isdn/gigaset/i4l.c +++ b/drivers/isdn/gigaset/i4l.c @@ -243,7 +243,7 @@ static int command_from_LL(isdn_ctrl *cntrl) dev_kfree_skb(bcs->rx_skb); gigaset_new_rx_skb(bcs); - commands = kzalloc(AT_NUM * (sizeof *commands), GFP_ATOMIC); + commands = kcalloc(AT_NUM, sizeof(*commands), GFP_ATOMIC); if (!commands) { gigaset_free_channel(bcs); dev_err(cs->dev, "ISDN_CMD_DIAL: out of memory\n"); diff --git a/drivers/isdn/hardware/avm/b1.c b/drivers/isdn/hardware/avm/b1.c index 40a099f33bfc..45985170af7c 100644 --- a/drivers/isdn/hardware/avm/b1.c +++ b/drivers/isdn/hardware/avm/b1.c @@ -72,7 +72,7 @@ avmcard *b1_alloc_card(int nr_controllers) if (!card) return NULL; - cinfo = kzalloc(sizeof(*cinfo) * nr_controllers, GFP_KERNEL); + cinfo = kcalloc(nr_controllers, sizeof(*cinfo), GFP_KERNEL); if (!cinfo) { kfree(card); return NULL; diff --git a/drivers/isdn/hisax/fsm.c b/drivers/isdn/hisax/fsm.c index d63266fa8cbd..36555e666e98 100644 --- a/drivers/isdn/hisax/fsm.c +++ b/drivers/isdn/hisax/fsm.c @@ -27,7 +27,8 @@ FsmNew(struct Fsm *fsm, struct FsmNode *fnlist, int fncount) int i; fsm->jumpmatrix = - kzalloc(sizeof(FSMFNPTR) * fsm->state_count * fsm->event_count, GFP_KERNEL); + kzalloc(array3_size(sizeof(FSMFNPTR), fsm->state_count, fsm->event_count), + GFP_KERNEL); if (!fsm->jumpmatrix) return -ENOMEM; diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c index a5cd3f310091..4fce7264e380 100644 --- a/drivers/isdn/i4l/isdn_common.c +++ b/drivers/isdn/i4l/isdn_common.c @@ -2064,14 +2064,14 @@ isdn_add_channels(isdn_driver_t *d, int drvidx, int n, int adding) if ((adding) && (d->rcverr)) kfree(d->rcverr); - if (!(d->rcverr = kzalloc(sizeof(int) * m, GFP_ATOMIC))) { + if (!(d->rcverr = kcalloc(m, sizeof(int), GFP_ATOMIC))) { printk(KERN_WARNING "register_isdn: Could not alloc rcverr\n"); return -1; } if ((adding) && (d->rcvcount)) kfree(d->rcvcount); - if (!(d->rcvcount = kzalloc(sizeof(int) * m, GFP_ATOMIC))) { + if (!(d->rcvcount = kcalloc(m, sizeof(int), GFP_ATOMIC))) { printk(KERN_WARNING "register_isdn: Could not alloc rcvcount\n"); if (!adding) kfree(d->rcverr); diff --git a/drivers/isdn/mISDN/fsm.c b/drivers/isdn/mISDN/fsm.c index 92e6570b1143..153b7b6d2be4 100644 --- a/drivers/isdn/mISDN/fsm.c +++ b/drivers/isdn/mISDN/fsm.c @@ -32,8 +32,8 @@ mISDN_FsmNew(struct Fsm *fsm, { int i; - fsm->jumpmatrix = kzalloc(sizeof(FSMFNPTR) * fsm->state_count * - fsm->event_count, GFP_KERNEL); + fsm->jumpmatrix = kzalloc(array3_size(sizeof(FSMFNPTR), fsm->state_count, fsm->event_count), + GFP_KERNEL); if (fsm->jumpmatrix == NULL) return -ENOMEM; diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c index 27c2294be51a..ae965af5b0e6 100644 --- a/drivers/mailbox/pcc.c +++ b/drivers/mailbox/pcc.c @@ -477,8 +477,8 @@ static int __init acpi_pcc_probe(void) return -EINVAL; } - pcc_mbox_channels = kzalloc(sizeof(struct mbox_chan) * - sum, GFP_KERNEL); + pcc_mbox_channels = kcalloc(sum, sizeof(struct mbox_chan), + GFP_KERNEL); if (!pcc_mbox_channels) { pr_err("Could not allocate space for PCC mbox channels\n"); return -ENOMEM; diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c index 690aeb09bbf5..a0dcfc7a83ab 100644 --- a/drivers/md/bcache/super.c +++ b/drivers/md/bcache/super.c @@ -1534,7 +1534,7 @@ struct cache_set *bch_cache_set_alloc(struct cache_sb *sb) iter_size = (sb->bucket_size / sb->block_size + 1) * sizeof(struct btree_iter_set); - if (!(c->devices = kzalloc(c->nr_uuids * sizeof(void *), GFP_KERNEL)) || + if (!(c->devices = kcalloc(c->nr_uuids, sizeof(void *), GFP_KERNEL)) || !(c->bio_meta = mempool_create_kmalloc_pool(2, sizeof(struct bbio) + sizeof(struct bio_vec) * bucket_pages(c))) || @@ -1868,8 +1868,7 @@ static int cache_alloc(struct cache *ca) !init_heap(&ca->heap, free << 3, GFP_KERNEL) || !(ca->buckets = vzalloc(sizeof(struct bucket) * ca->sb.nbuckets)) || - !(ca->prio_buckets = kzalloc(sizeof(uint64_t) * prio_buckets(ca) * - 2, GFP_KERNEL)) || + !(ca->prio_buckets = kzalloc(array3_size(sizeof(uint64_t), prio_buckets(ca), 2), GFP_KERNEL)) || !(ca->disk_buckets = alloc_bucket_pages(GFP_KERNEL, ca))) return -ENOMEM; diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 63090ec7d430..2ae26d42576d 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -2113,7 +2113,7 @@ int bitmap_resize(struct bitmap *bitmap, sector_t blocks, pages = DIV_ROUND_UP(chunks, PAGE_COUNTER_RATIO); - new_bp = kzalloc(pages * sizeof(*new_bp), GFP_KERNEL); + new_bp = kcalloc(pages, sizeof(*new_bp), GFP_KERNEL); ret = -ENOMEM; if (!new_bp) { bitmap_file_unmap(&store); diff --git a/drivers/md/dm-android-verity.c b/drivers/md/dm-android-verity.c index 20e05936551f..dd10e58155ac 100644 --- a/drivers/md/dm-android-verity.c +++ b/drivers/md/dm-android-verity.c @@ -141,8 +141,9 @@ static int read_block_dev(struct bio_read *payload, struct block_device *bdev, bio->bi_iter.bi_sector = offset; bio_set_op_attrs(bio, REQ_OP_READ, 0); - payload->page_io = kzalloc(sizeof(struct page *) * - payload->number_of_pages, GFP_KERNEL); + payload->page_io = kcalloc(payload->number_of_pages, + sizeof(struct page *), + GFP_KERNEL); if (!payload->page_io) { DMERR("page_io array alloc failed"); err = -ENOMEM; diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 87e8a2b0b999..a8db67fc9787 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -1886,8 +1886,9 @@ static int crypt_alloc_tfms_skcipher(struct crypt_config *cc, char *ciphermode) unsigned i; int err; - cc->cipher_tfm.tfms = kzalloc(cc->tfms_count * - sizeof(struct crypto_skcipher *), GFP_KERNEL); + cc->cipher_tfm.tfms = kcalloc(cc->tfms_count, + sizeof(struct crypto_skcipher *), + GFP_KERNEL); if (!cc->cipher_tfm.tfms) return -ENOMEM; diff --git a/drivers/md/md-cluster.c b/drivers/md/md-cluster.c index 10057ac85476..a9e7f23a739a 100644 --- a/drivers/md/md-cluster.c +++ b/drivers/md/md-cluster.c @@ -1381,9 +1381,9 @@ static int lock_all_bitmaps(struct mddev *mddev) char str[64]; struct md_cluster_info *cinfo = mddev->cluster_info; - cinfo->other_bitmap_lockres = kzalloc((mddev->bitmap_info.nodes - 1) * - sizeof(struct dlm_lock_resource *), - GFP_KERNEL); + cinfo->other_bitmap_lockres = kcalloc(mddev->bitmap_info.nodes - 1, + sizeof(struct dlm_lock_resource *), + GFP_KERNEL); if (!cinfo->other_bitmap_lockres) { pr_err("md: can't alloc mem for other bitmap locks\n"); return 0; diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index b68e0666b9b0..23a6bf8bad90 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c @@ -400,7 +400,8 @@ static int multipath_run (struct mddev *mddev) if (!conf) goto out; - conf->multipaths = kzalloc(sizeof(struct multipath_info)*mddev->raid_disks, + conf->multipaths = kcalloc(mddev->raid_disks, + sizeof(struct multipath_info), GFP_KERNEL); if (!conf->multipaths) goto out_free_conf; diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index e179c121c030..4814b45631c8 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -178,12 +178,12 @@ static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf) } err = -ENOMEM; - conf->strip_zone = kzalloc(sizeof(struct strip_zone)* - conf->nr_strip_zones, GFP_KERNEL); + conf->strip_zone = kcalloc(conf->nr_strip_zones, + sizeof(struct strip_zone), + GFP_KERNEL); if (!conf->strip_zone) goto abort; - conf->devlist = kzalloc(sizeof(struct md_rdev*)* - conf->nr_strip_zones*mddev->raid_disks, + conf->devlist = kzalloc(array3_size(sizeof(struct md_rdev *), conf->nr_strip_zones, mddev->raid_disks), GFP_KERNEL); if (!conf->devlist) goto abort; diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 0a0deb340b0a..57506ba2c335 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -2936,8 +2936,7 @@ static struct r1conf *setup_conf(struct mddev *mddev) if (!conf->barrier) goto abort; - conf->mirrors = kzalloc(sizeof(struct raid1_info) - * mddev->raid_disks * 2, + conf->mirrors = kzalloc(array3_size(sizeof(struct raid1_info), mddev->raid_disks, 2), GFP_KERNEL); if (!conf->mirrors) goto abort; @@ -3251,7 +3250,7 @@ static int raid1_reshape(struct mddev *mddev) kfree(newpoolinfo); return -ENOMEM; } - newmirrors = kzalloc(sizeof(struct raid1_info) * raid_disks * 2, + newmirrors = kzalloc(array3_size(sizeof(struct raid1_info), raid_disks, 2), GFP_KERNEL); if (!newmirrors) { kfree(newpoolinfo); diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index b910124c9b13..02518d022bdf 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -3566,8 +3566,8 @@ static struct r10conf *setup_conf(struct mddev *mddev) goto out; /* FIXME calc properly */ - conf->mirrors = kzalloc(sizeof(struct raid10_info)*(mddev->raid_disks + - max(0,-mddev->delta_disks)), + conf->mirrors = kcalloc(mddev->raid_disks + max(0, -mddev->delta_disks), + sizeof(struct raid10_info), GFP_KERNEL); if (!conf->mirrors) goto out; @@ -4005,11 +4005,9 @@ static int raid10_check_reshape(struct mddev *mddev) conf->mirrors_new = NULL; if (mddev->delta_disks > 0) { /* allocate new 'mirrors' list */ - conf->mirrors_new = kzalloc( - sizeof(struct raid10_info) - *(mddev->raid_disks + - mddev->delta_disks), - GFP_KERNEL); + conf->mirrors_new = kcalloc(mddev->raid_disks + mddev->delta_disks, + sizeof(struct raid10_info), + GFP_KERNEL); if (!conf->mirrors_new) return -ENOMEM; } diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index d5c14d56a714..5791066dd511 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -2392,7 +2392,7 @@ static int resize_stripes(struct r5conf *conf, int newsize) * is completely stalled, so now is a good time to resize * conf->disks and the scribble region */ - ndisks = kzalloc(newsize * sizeof(struct disk_info), GFP_NOIO); + ndisks = kcalloc(newsize, sizeof(struct disk_info), GFP_NOIO); if (ndisks) { for (i = 0; i < conf->pool_size; i++) ndisks[i] = conf->disks[i]; @@ -6663,9 +6663,9 @@ static int alloc_thread_groups(struct r5conf *conf, int cnt, } *group_cnt = num_possible_nodes(); size = sizeof(struct r5worker) * cnt; - workers = kzalloc(size * *group_cnt, GFP_NOIO); - *worker_groups = kzalloc(sizeof(struct r5worker_group) * - *group_cnt, GFP_NOIO); + workers = kcalloc(size, *group_cnt, GFP_NOIO); + *worker_groups = kcalloc(*group_cnt, sizeof(struct r5worker_group), + GFP_NOIO); if (!*worker_groups || !workers) { kfree(workers); kfree(*worker_groups); @@ -6895,8 +6895,9 @@ static struct r5conf *setup_conf(struct mddev *mddev) goto abort; INIT_LIST_HEAD(&conf->free_list); INIT_LIST_HEAD(&conf->pending_list); - conf->pending_data = kzalloc(sizeof(struct r5pending_data) * - PENDING_IO_MAX, GFP_KERNEL); + conf->pending_data = kcalloc(PENDING_IO_MAX, + sizeof(struct r5pending_data), + GFP_KERNEL); if (!conf->pending_data) goto abort; for (i = 0; i < PENDING_IO_MAX; i++) @@ -6945,7 +6946,7 @@ static struct r5conf *setup_conf(struct mddev *mddev) conf->previous_raid_disks = mddev->raid_disks - mddev->delta_disks; max_disks = max(conf->raid_disks, conf->previous_raid_disks); - conf->disks = kzalloc(max_disks * sizeof(struct disk_info), + conf->disks = kcalloc(max_disks, sizeof(struct disk_info), GFP_KERNEL); if (!conf->disks) diff --git a/drivers/media/dvb-frontends/dib7000p.c b/drivers/media/dvb-frontends/dib7000p.c index 0fbaabe43682..e52d839bc9ae 100644 --- a/drivers/media/dvb-frontends/dib7000p.c +++ b/drivers/media/dvb-frontends/dib7000p.c @@ -2018,10 +2018,10 @@ static int dib7000pc_detection(struct i2c_adapter *i2c_adap) }; int ret = 0; - tx = kzalloc(2*sizeof(u8), GFP_KERNEL); + tx = kzalloc(2, GFP_KERNEL); if (!tx) return -ENOMEM; - rx = kzalloc(2*sizeof(u8), GFP_KERNEL); + rx = kzalloc(2, GFP_KERNEL); if (!rx) { ret = -ENOMEM; goto rx_memory_error; diff --git a/drivers/media/dvb-frontends/dib8000.c b/drivers/media/dvb-frontends/dib8000.c index 5d9381509b07..83ca74f9d5d3 100644 --- a/drivers/media/dvb-frontends/dib8000.c +++ b/drivers/media/dvb-frontends/dib8000.c @@ -4271,12 +4271,12 @@ static int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 new_addr = 0; struct i2c_device client = {.adap = host }; - client.i2c_write_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL); + client.i2c_write_buffer = kzalloc(4, GFP_KERNEL); if (!client.i2c_write_buffer) { dprintk("%s: not enough memory\n", __func__); return -ENOMEM; } - client.i2c_read_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL); + client.i2c_read_buffer = kzalloc(4, GFP_KERNEL); if (!client.i2c_read_buffer) { dprintk("%s: not enough memory\n", __func__); ret = -ENOMEM; diff --git a/drivers/media/dvb-frontends/dib9000.c b/drivers/media/dvb-frontends/dib9000.c index 1b7a4331af05..03b047fdc14c 100644 --- a/drivers/media/dvb-frontends/dib9000.c +++ b/drivers/media/dvb-frontends/dib9000.c @@ -2381,12 +2381,12 @@ int dib9000_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 defaul u8 new_addr = 0; struct i2c_device client = {.i2c_adap = i2c }; - client.i2c_write_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL); + client.i2c_write_buffer = kzalloc(4, GFP_KERNEL); if (!client.i2c_write_buffer) { dprintk("%s: not enough memory\n", __func__); return -ENOMEM; } - client.i2c_read_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL); + client.i2c_read_buffer = kzalloc(4, GFP_KERNEL); if (!client.i2c_read_buffer) { dprintk("%s: not enough memory\n", __func__); ret = -ENOMEM; diff --git a/drivers/media/platform/msm/ais/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/media/platform/msm/ais/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index c6f0b746729c..f7db88c15a04 100644 --- a/drivers/media/platform/msm/ais/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/media/platform/msm/ais/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -5071,8 +5071,9 @@ static int cam_icp_mgr_alloc_devs(struct device_node *of_node) goto num_a5_failed; } - icp_hw_mgr.devices[CAM_ICP_DEV_A5] = kzalloc( - sizeof(struct cam_hw_intf *) * num_dev, GFP_KERNEL); + icp_hw_mgr.devices[CAM_ICP_DEV_A5] = kcalloc(num_dev, + sizeof(struct cam_hw_intf *), + GFP_KERNEL); if (!icp_hw_mgr.devices[CAM_ICP_DEV_A5]) { rc = -ENOMEM; goto num_a5_failed; @@ -5227,20 +5228,20 @@ static int cam_icp_mgr_create_wq(void) } icp_hw_mgr.cmd_work_data = (struct hfi_cmd_work_data *) - kzalloc(sizeof(struct hfi_cmd_work_data) * ICP_WORKQ_NUM_TASK, - GFP_KERNEL); + kcalloc(ICP_WORKQ_NUM_TASK, sizeof(struct hfi_cmd_work_data), + GFP_KERNEL); if (!icp_hw_mgr.cmd_work_data) goto cmd_work_data_failed; icp_hw_mgr.msg_work_data = (struct hfi_msg_work_data *) - kzalloc(sizeof(struct hfi_msg_work_data) * ICP_WORKQ_NUM_TASK, - GFP_KERNEL); + kcalloc(ICP_WORKQ_NUM_TASK, sizeof(struct hfi_msg_work_data), + GFP_KERNEL); if (!icp_hw_mgr.msg_work_data) goto msg_work_data_failed; icp_hw_mgr.timer_work_data = (struct hfi_msg_work_data *) - kzalloc(sizeof(struct hfi_msg_work_data) * ICP_WORKQ_NUM_TASK, - GFP_KERNEL); + kcalloc(ICP_WORKQ_NUM_TASK, sizeof(struct hfi_msg_work_data), + GFP_KERNEL); if (!icp_hw_mgr.timer_work_data) goto timer_work_data_failed; diff --git a/drivers/media/platform/msm/ais/cam_isp/cam_isp_context.c b/drivers/media/platform/msm/ais/cam_isp/cam_isp_context.c index 6cfbf7b89a30..699829135ec5 100644 --- a/drivers/media/platform/msm/ais/cam_isp/cam_isp_context.c +++ b/drivers/media/platform/msm/ais/cam_isp/cam_isp_context.c @@ -3431,8 +3431,7 @@ static int __cam_isp_ctx_acquire_dev_in_available(struct cam_context *ctx, goto end; } - isp_res = kzalloc( - sizeof(*isp_res)*cmd->num_resources, GFP_KERNEL); + isp_res = kcalloc(cmd->num_resources, sizeof(*isp_res), GFP_KERNEL); if (!isp_res) { rc = -ENOMEM; goto end; diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c index 02344d790423..8b0e61e77ad7 100644 --- a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c +++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c @@ -152,16 +152,18 @@ int cam_irq_controller_init(const char *name, return -ENOMEM; } - controller->irq_register_arr = kzalloc(register_info->num_registers * - sizeof(struct cam_irq_register_obj), GFP_KERNEL); + controller->irq_register_arr = kcalloc(register_info->num_registers, + sizeof(struct cam_irq_register_obj), + GFP_KERNEL); if (!controller->irq_register_arr) { CAM_DBG(CAM_IRQ_CTRL, "Failed to allocate IRQ register Arr"); rc = -ENOMEM; goto reg_alloc_error; } - controller->irq_status_arr = kzalloc(register_info->num_registers * - sizeof(uint32_t), GFP_KERNEL); + controller->irq_status_arr = kcalloc(register_info->num_registers, + sizeof(uint32_t), + GFP_KERNEL); if (!controller->irq_status_arr) { CAM_DBG(CAM_IRQ_CTRL, "Failed to allocate IRQ status Arr"); rc = -ENOMEM; @@ -169,8 +171,8 @@ int cam_irq_controller_init(const char *name, } controller->th_payload.evt_status_arr = - kzalloc(register_info->num_registers * sizeof(uint32_t), - GFP_KERNEL); + kcalloc(register_info->num_registers, sizeof(uint32_t), + GFP_KERNEL); if (!controller->th_payload.evt_status_arr) { CAM_DBG(CAM_IRQ_CTRL, "Failed to allocate BH payload bit mask Arr"); @@ -293,8 +295,9 @@ int cam_irq_controller_subscribe_irq(void *irq_controller, return -ENOMEM; } - evt_handler->evt_bit_mask_arr = kzalloc(sizeof(uint32_t) * - controller->num_registers, GFP_KERNEL); + evt_handler->evt_bit_mask_arr = kcalloc(controller->num_registers, + sizeof(uint32_t), + GFP_KERNEL); if (!evt_handler->evt_bit_mask_arr) { CAM_DBG(CAM_IRQ_CTRL, "Error allocating hlist_node"); rc = -ENOMEM; diff --git a/drivers/media/platform/msm/ais/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c b/drivers/media/platform/msm/ais/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c index 1a995646a947..8f2de3ce498b 100644 --- a/drivers/media/platform/msm/ais/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c +++ b/drivers/media/platform/msm/ais/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c @@ -1443,8 +1443,9 @@ static int cam_jpeg_setup_workqs(void) g_jpeg_hw_mgr.process_frame_work_data = (struct cam_jpeg_process_frame_work_data_t *) - kzalloc(sizeof(struct cam_jpeg_process_frame_work_data_t) * - CAM_JPEG_WORKQ_NUM_TASK, GFP_KERNEL); + kcalloc(CAM_JPEG_WORKQ_NUM_TASK, + sizeof(struct cam_jpeg_process_frame_work_data_t), + GFP_KERNEL); if (!g_jpeg_hw_mgr.process_frame_work_data) { rc = -ENOMEM; goto work_process_frame_data_failed; @@ -1452,8 +1453,9 @@ static int cam_jpeg_setup_workqs(void) g_jpeg_hw_mgr.process_irq_cb_work_data = (struct cam_jpeg_process_irq_work_data_t *) - kzalloc(sizeof(struct cam_jpeg_process_irq_work_data_t) * - CAM_JPEG_WORKQ_NUM_TASK, GFP_KERNEL); + kcalloc(CAM_JPEG_WORKQ_NUM_TASK, + sizeof(struct cam_jpeg_process_irq_work_data_t), + GFP_KERNEL); if (!g_jpeg_hw_mgr.process_irq_cb_work_data) { rc = -ENOMEM; goto work_process_irq_cb_data_failed; @@ -1522,8 +1524,9 @@ static int cam_jpeg_init_devices(struct device_node *of_node, CAM_ERR(CAM_JPEG, "read num enc devices failed %d", rc); goto num_enc_failed; } - g_jpeg_hw_mgr.devices[CAM_JPEG_DEV_ENC] = kzalloc( - sizeof(struct cam_hw_intf *) * num_dev, GFP_KERNEL); + g_jpeg_hw_mgr.devices[CAM_JPEG_DEV_ENC] = kcalloc(num_dev, + sizeof(struct cam_hw_intf *), + GFP_KERNEL); if (!g_jpeg_hw_mgr.devices[CAM_JPEG_DEV_ENC]) { rc = -ENOMEM; CAM_ERR(CAM_JPEG, "getting number of dma dev nodes failed"); @@ -1536,8 +1539,9 @@ static int cam_jpeg_init_devices(struct device_node *of_node, goto num_dma_failed; } - g_jpeg_hw_mgr.devices[CAM_JPEG_DEV_DMA] = kzalloc( - sizeof(struct cam_hw_intf *) * num_dma_dev, GFP_KERNEL); + g_jpeg_hw_mgr.devices[CAM_JPEG_DEV_DMA] = kcalloc(num_dma_dev, + sizeof(struct cam_hw_intf *), + GFP_KERNEL); if (!g_jpeg_hw_mgr.devices[CAM_JPEG_DEV_DMA]) { rc = -ENOMEM; goto num_dma_failed; diff --git a/drivers/media/platform/msm/ais/cam_req_mgr/cam_req_mgr_core.c b/drivers/media/platform/msm/ais/cam_req_mgr/cam_req_mgr_core.c index c3c9428924ce..5fe4a1314cef 100644 --- a/drivers/media/platform/msm/ais/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/media/platform/msm/ais/cam_req_mgr/cam_req_mgr_core.c @@ -1594,8 +1594,8 @@ static int __cam_req_mgr_create_subdevs( { int rc = 0; *l_dev = (struct cam_req_mgr_connected_device *) - kzalloc(sizeof(struct cam_req_mgr_connected_device) * num_dev, - GFP_KERNEL); + kcalloc(num_dev, sizeof(struct cam_req_mgr_connected_device), + GFP_KERNEL); if (!*l_dev) rc = -ENOMEM; diff --git a/drivers/media/platform/msm/ais/cam_sensor_module/cam_actuator/cam_actuator_dev.c b/drivers/media/platform/msm/ais/cam_sensor_module/cam_actuator/cam_actuator_dev.c index 228ccb8a39b3..756688699bcf 100644 --- a/drivers/media/platform/msm/ais/cam_sensor_module/cam_actuator/cam_actuator_dev.c +++ b/drivers/media/platform/msm/ais/cam_sensor_module/cam_actuator/cam_actuator_dev.c @@ -196,8 +196,9 @@ static int32_t cam_actuator_driver_i2c_probe(struct i2c_client *client, a_ctrl->i2c_data.per_frame = (struct i2c_settings_array *) - kzalloc(sizeof(struct i2c_settings_array) * - MAX_PER_FRAME_ARRAY, GFP_KERNEL); + kcalloc(MAX_PER_FRAME_ARRAY, + sizeof(struct i2c_settings_array), + GFP_KERNEL); if (a_ctrl->i2c_data.per_frame == NULL) { rc = -ENOMEM; goto unreg_subdev; @@ -342,8 +343,9 @@ static int32_t cam_actuator_driver_platform_probe( a_ctrl->i2c_data.per_frame = (struct i2c_settings_array *) - kzalloc(sizeof(struct i2c_settings_array) * - MAX_PER_FRAME_ARRAY, GFP_KERNEL); + kcalloc(MAX_PER_FRAME_ARRAY, + sizeof(struct i2c_settings_array), + GFP_KERNEL); if (a_ctrl->i2c_data.per_frame == NULL) { rc = -ENOMEM; goto free_soc; diff --git a/drivers/media/platform/msm/ais/cam_sensor_module/cam_cci/cam_cci_core.c b/drivers/media/platform/msm/ais/cam_sensor_module/cam_cci/cam_cci_core.c index 45eb1f449d35..d2096599a158 100755 --- a/drivers/media/platform/msm/ais/cam_sensor_module/cam_cci/cam_cci_core.c +++ b/drivers/media/platform/msm/ais/cam_sensor_module/cam_cci/cam_cci_core.c @@ -1797,8 +1797,9 @@ static int32_t cam_cci_i2c_write_async(struct v4l2_subdev *sd, } cci_i2c_write_cfg_w->reg_setting = - kzalloc(sizeof(struct cam_sensor_i2c_reg_array)* - cci_i2c_write_cfg->size, GFP_KERNEL); + kcalloc(cci_i2c_write_cfg->size, + sizeof(struct cam_sensor_i2c_reg_array), + GFP_KERNEL); if (!cci_i2c_write_cfg_w->reg_setting) { CAM_ERR(CAM_CCI, "Couldn't allocate memory"); kfree(write_async); diff --git a/drivers/media/platform/msm/ais/cam_sensor_module/cam_flash/cam_flash_dev.c b/drivers/media/platform/msm/ais/cam_sensor_module/cam_flash/cam_flash_dev.c index f4c9d254df7c..12407e305102 100644 --- a/drivers/media/platform/msm/ais/cam_sensor_module/cam_flash/cam_flash_dev.c +++ b/drivers/media/platform/msm/ais/cam_sensor_module/cam_flash/cam_flash_dev.c @@ -456,8 +456,9 @@ static int32_t cam_flash_platform_probe(struct platform_device *pdev) } fctrl->i2c_data.per_frame = (struct i2c_settings_array *) - kzalloc(sizeof(struct i2c_settings_array) * - MAX_PER_FRAME_ARRAY, GFP_KERNEL); + kcalloc(MAX_PER_FRAME_ARRAY, + sizeof(struct i2c_settings_array), + GFP_KERNEL); if (fctrl->i2c_data.per_frame == NULL) { CAM_ERR(CAM_FLASH, "No Memory"); rc = -ENOMEM; @@ -560,8 +561,9 @@ static int32_t cam_flash_i2c_driver_probe(struct i2c_client *client, fctrl->i2c_data.per_frame = (struct i2c_settings_array *) - kzalloc(sizeof(struct i2c_settings_array) * - MAX_PER_FRAME_ARRAY, GFP_KERNEL); + kcalloc(MAX_PER_FRAME_ARRAY, + sizeof(struct i2c_settings_array), + GFP_KERNEL); if (fctrl->i2c_data.per_frame == NULL) { rc = -ENOMEM; goto unreg_subdev; diff --git a/drivers/media/platform/msm/ais/cam_sensor_module/cam_sensor/cam_sensor_dev.c b/drivers/media/platform/msm/ais/cam_sensor_module/cam_sensor/cam_sensor_dev.c index d29a58f65a47..ff051f857ddd 100644 --- a/drivers/media/platform/msm/ais/cam_sensor_module/cam_sensor/cam_sensor_dev.c +++ b/drivers/media/platform/msm/ais/cam_sensor_module/cam_sensor/cam_sensor_dev.c @@ -193,8 +193,9 @@ static int32_t cam_sensor_driver_i2c_probe(struct i2c_client *client, s_ctrl->i2c_data.per_frame = (struct i2c_settings_array *) - kzalloc(sizeof(struct i2c_settings_array) * - MAX_PER_FRAME_ARRAY, GFP_KERNEL); + kcalloc(MAX_PER_FRAME_ARRAY, + sizeof(struct i2c_settings_array), + GFP_KERNEL); if (s_ctrl->i2c_data.per_frame == NULL) { rc = -ENOMEM; goto unreg_subdev; @@ -329,8 +330,9 @@ static int32_t cam_sensor_driver_platform_probe( s_ctrl->i2c_data.per_frame = (struct i2c_settings_array *) - kzalloc(sizeof(struct i2c_settings_array) * - MAX_PER_FRAME_ARRAY, GFP_KERNEL); + kcalloc(MAX_PER_FRAME_ARRAY, + sizeof(struct i2c_settings_array), + GFP_KERNEL); if (s_ctrl->i2c_data.per_frame == NULL) { rc = -ENOMEM; goto unreg_subdev; diff --git a/drivers/media/platform/msm/ais/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c b/drivers/media/platform/msm/ais/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c index b3a74d6c80bf..031cb4b87046 100644 --- a/drivers/media/platform/msm/ais/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c +++ b/drivers/media/platform/msm/ais/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c @@ -944,16 +944,18 @@ int32_t cam_sensor_update_power_settings(void *cmd_buf, power_info->power_setting_size = 0; power_info->power_setting = (struct cam_sensor_power_setting *) - kzalloc(sizeof(struct cam_sensor_power_setting) * - MAX_POWER_CONFIG, GFP_KERNEL); + kcalloc(MAX_POWER_CONFIG, + sizeof(struct cam_sensor_power_setting), + GFP_KERNEL); if (!power_info->power_setting) return -ENOMEM; power_info->power_down_setting_size = 0; power_info->power_down_setting = (struct cam_sensor_power_setting *) - kzalloc(sizeof(struct cam_sensor_power_setting) * - MAX_POWER_CONFIG, GFP_KERNEL); + kcalloc(MAX_POWER_CONFIG, + sizeof(struct cam_sensor_power_setting), + GFP_KERNEL); if (!power_info->power_down_setting) { kfree(power_info->power_setting); power_info->power_setting = NULL; diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index ee0e29405335..aedbc1a42470 100644 --- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -5213,8 +5213,9 @@ static int cam_icp_mgr_alloc_devs(struct device_node *of_node) goto num_a5_failed; } - icp_hw_mgr.devices[CAM_ICP_DEV_A5] = kzalloc( - sizeof(struct cam_hw_intf *) * num_dev, GFP_KERNEL); + icp_hw_mgr.devices[CAM_ICP_DEV_A5] = kcalloc(num_dev, + sizeof(struct cam_hw_intf *), + GFP_KERNEL); if (!icp_hw_mgr.devices[CAM_ICP_DEV_A5]) { rc = -ENOMEM; goto num_a5_failed; @@ -5369,20 +5370,20 @@ static int cam_icp_mgr_create_wq(void) } icp_hw_mgr.cmd_work_data = (struct hfi_cmd_work_data *) - kzalloc(sizeof(struct hfi_cmd_work_data) * ICP_WORKQ_NUM_TASK, - GFP_KERNEL); + kcalloc(ICP_WORKQ_NUM_TASK, sizeof(struct hfi_cmd_work_data), + GFP_KERNEL); if (!icp_hw_mgr.cmd_work_data) goto cmd_work_data_failed; icp_hw_mgr.msg_work_data = (struct hfi_msg_work_data *) - kzalloc(sizeof(struct hfi_msg_work_data) * ICP_WORKQ_NUM_TASK, - GFP_KERNEL); + kcalloc(ICP_WORKQ_NUM_TASK, sizeof(struct hfi_msg_work_data), + GFP_KERNEL); if (!icp_hw_mgr.msg_work_data) goto msg_work_data_failed; icp_hw_mgr.timer_work_data = (struct hfi_msg_work_data *) - kzalloc(sizeof(struct hfi_msg_work_data) * ICP_WORKQ_NUM_TASK, - GFP_KERNEL); + kcalloc(ICP_WORKQ_NUM_TASK, sizeof(struct hfi_msg_work_data), + GFP_KERNEL); if (!icp_hw_mgr.timer_work_data) goto timer_work_data_failed; diff --git a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c index 82216d50bbe8..6bc114c5949b 100644 --- a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c +++ b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c @@ -3546,8 +3546,7 @@ static int __cam_isp_ctx_acquire_dev_in_available(struct cam_context *ctx, goto end; } - isp_res = kzalloc( - sizeof(*isp_res)*cmd->num_resources, GFP_KERNEL); + isp_res = kcalloc(cmd->num_resources, sizeof(*isp_res), GFP_KERNEL); if (!isp_res) { rc = -ENOMEM; goto end; diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c index e6a0e015963c..b91fae3cabf7 100644 --- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c +++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c @@ -152,16 +152,18 @@ int cam_irq_controller_init(const char *name, return -ENOMEM; } - controller->irq_register_arr = kzalloc(register_info->num_registers * - sizeof(struct cam_irq_register_obj), GFP_KERNEL); + controller->irq_register_arr = kcalloc(register_info->num_registers, + sizeof(struct cam_irq_register_obj), + GFP_KERNEL); if (!controller->irq_register_arr) { CAM_DBG(CAM_IRQ_CTRL, "Failed to allocate IRQ register Arr"); rc = -ENOMEM; goto reg_alloc_error; } - controller->irq_status_arr = kzalloc(register_info->num_registers * - sizeof(uint32_t), GFP_KERNEL); + controller->irq_status_arr = kcalloc(register_info->num_registers, + sizeof(uint32_t), + GFP_KERNEL); if (!controller->irq_status_arr) { CAM_DBG(CAM_IRQ_CTRL, "Failed to allocate IRQ status Arr"); rc = -ENOMEM; @@ -169,8 +171,8 @@ int cam_irq_controller_init(const char *name, } controller->th_payload.evt_status_arr = - kzalloc(register_info->num_registers * sizeof(uint32_t), - GFP_KERNEL); + kcalloc(register_info->num_registers, sizeof(uint32_t), + GFP_KERNEL); if (!controller->th_payload.evt_status_arr) { CAM_DBG(CAM_IRQ_CTRL, "Failed to allocate BH payload bit mask Arr"); @@ -293,8 +295,9 @@ int cam_irq_controller_subscribe_irq(void *irq_controller, return -ENOMEM; } - evt_handler->evt_bit_mask_arr = kzalloc(sizeof(uint32_t) * - controller->num_registers, GFP_KERNEL); + evt_handler->evt_bit_mask_arr = kcalloc(controller->num_registers, + sizeof(uint32_t), + GFP_KERNEL); if (!evt_handler->evt_bit_mask_arr) { CAM_DBG(CAM_IRQ_CTRL, "Error allocating hlist_node"); rc = -ENOMEM; diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c index 2a1704e6ca7e..b100a14a83b9 100644 --- a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c +++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c @@ -1510,8 +1510,9 @@ static int cam_jpeg_setup_workqs(void) g_jpeg_hw_mgr.process_frame_work_data = (struct cam_jpeg_process_frame_work_data_t *) - kzalloc(sizeof(struct cam_jpeg_process_frame_work_data_t) * - CAM_JPEG_WORKQ_NUM_TASK, GFP_KERNEL); + kcalloc(CAM_JPEG_WORKQ_NUM_TASK, + sizeof(struct cam_jpeg_process_frame_work_data_t), + GFP_KERNEL); if (!g_jpeg_hw_mgr.process_frame_work_data) { rc = -ENOMEM; goto work_process_frame_data_failed; @@ -1519,8 +1520,9 @@ static int cam_jpeg_setup_workqs(void) g_jpeg_hw_mgr.process_irq_cb_work_data = (struct cam_jpeg_process_irq_work_data_t *) - kzalloc(sizeof(struct cam_jpeg_process_irq_work_data_t) * - CAM_JPEG_WORKQ_NUM_TASK, GFP_KERNEL); + kcalloc(CAM_JPEG_WORKQ_NUM_TASK, + sizeof(struct cam_jpeg_process_irq_work_data_t), + GFP_KERNEL); if (!g_jpeg_hw_mgr.process_irq_cb_work_data) { rc = -ENOMEM; goto work_process_irq_cb_data_failed; @@ -1589,8 +1591,9 @@ static int cam_jpeg_init_devices(struct device_node *of_node, CAM_ERR(CAM_JPEG, "read num enc devices failed %d", rc); goto num_enc_failed; } - g_jpeg_hw_mgr.devices[CAM_JPEG_DEV_ENC] = kzalloc( - sizeof(struct cam_hw_intf *) * num_dev, GFP_KERNEL); + g_jpeg_hw_mgr.devices[CAM_JPEG_DEV_ENC] = kcalloc(num_dev, + sizeof(struct cam_hw_intf *), + GFP_KERNEL); if (!g_jpeg_hw_mgr.devices[CAM_JPEG_DEV_ENC]) { rc = -ENOMEM; CAM_ERR(CAM_JPEG, "getting number of dma dev nodes failed"); @@ -1603,8 +1606,9 @@ static int cam_jpeg_init_devices(struct device_node *of_node, goto num_dma_failed; } - g_jpeg_hw_mgr.devices[CAM_JPEG_DEV_DMA] = kzalloc( - sizeof(struct cam_hw_intf *) * num_dma_dev, GFP_KERNEL); + g_jpeg_hw_mgr.devices[CAM_JPEG_DEV_DMA] = kcalloc(num_dma_dev, + sizeof(struct cam_hw_intf *), + GFP_KERNEL); if (!g_jpeg_hw_mgr.devices[CAM_JPEG_DEV_DMA]) { rc = -ENOMEM; goto num_dma_failed; diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c index d0be103419a8..1ffa918d50c1 100644 --- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c @@ -1640,8 +1640,8 @@ static int __cam_req_mgr_create_subdevs( { int rc = 0; *l_dev = (struct cam_req_mgr_connected_device *) - kzalloc(sizeof(struct cam_req_mgr_connected_device) * num_dev, - GFP_KERNEL); + kcalloc(num_dev, sizeof(struct cam_req_mgr_connected_device), + GFP_KERNEL); if (!*l_dev) rc = -ENOMEM; diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_dev.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_dev.c index 2c66491a944b..8c80c5e4e9e9 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_dev.c +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_dev.c @@ -196,8 +196,9 @@ static int32_t cam_actuator_driver_i2c_probe(struct i2c_client *client, a_ctrl->i2c_data.per_frame = (struct i2c_settings_array *) - kzalloc(sizeof(struct i2c_settings_array) * - MAX_PER_FRAME_ARRAY, GFP_KERNEL); + kcalloc(MAX_PER_FRAME_ARRAY, + sizeof(struct i2c_settings_array), + GFP_KERNEL); if (a_ctrl->i2c_data.per_frame == NULL) { rc = -ENOMEM; goto unreg_subdev; @@ -342,8 +343,9 @@ static int32_t cam_actuator_driver_platform_probe( a_ctrl->i2c_data.per_frame = (struct i2c_settings_array *) - kzalloc(sizeof(struct i2c_settings_array) * - MAX_PER_FRAME_ARRAY, GFP_KERNEL); + kcalloc(MAX_PER_FRAME_ARRAY, + sizeof(struct i2c_settings_array), + GFP_KERNEL); if (a_ctrl->i2c_data.per_frame == NULL) { rc = -ENOMEM; goto free_soc; diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_core.c index a06a4c6c6339..d0328929548e 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_core.c +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_core.c @@ -1482,8 +1482,9 @@ static int32_t cam_cci_i2c_write_async(struct v4l2_subdev *sd, } cci_i2c_write_cfg_w->reg_setting = - kzalloc(sizeof(struct cam_sensor_i2c_reg_array)* - cci_i2c_write_cfg->size, GFP_KERNEL); + kcalloc(cci_i2c_write_cfg->size, + sizeof(struct cam_sensor_i2c_reg_array), + GFP_KERNEL); if (!cci_i2c_write_cfg_w->reg_setting) { CAM_ERR(CAM_CCI, "Couldn't allocate memory"); kfree(write_async); diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.c index f4c9d254df7c..12407e305102 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.c +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.c @@ -456,8 +456,9 @@ static int32_t cam_flash_platform_probe(struct platform_device *pdev) } fctrl->i2c_data.per_frame = (struct i2c_settings_array *) - kzalloc(sizeof(struct i2c_settings_array) * - MAX_PER_FRAME_ARRAY, GFP_KERNEL); + kcalloc(MAX_PER_FRAME_ARRAY, + sizeof(struct i2c_settings_array), + GFP_KERNEL); if (fctrl->i2c_data.per_frame == NULL) { CAM_ERR(CAM_FLASH, "No Memory"); rc = -ENOMEM; @@ -560,8 +561,9 @@ static int32_t cam_flash_i2c_driver_probe(struct i2c_client *client, fctrl->i2c_data.per_frame = (struct i2c_settings_array *) - kzalloc(sizeof(struct i2c_settings_array) * - MAX_PER_FRAME_ARRAY, GFP_KERNEL); + kcalloc(MAX_PER_FRAME_ARRAY, + sizeof(struct i2c_settings_array), + GFP_KERNEL); if (fctrl->i2c_data.per_frame == NULL) { rc = -ENOMEM; goto unreg_subdev; diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_dev.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_dev.c index 5207eee15f05..a170fa9e4724 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_dev.c +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_dev.c @@ -176,8 +176,9 @@ static int32_t cam_sensor_driver_i2c_probe(struct i2c_client *client, s_ctrl->i2c_data.per_frame = (struct i2c_settings_array *) - kzalloc(sizeof(struct i2c_settings_array) * - MAX_PER_FRAME_ARRAY, GFP_KERNEL); + kcalloc(MAX_PER_FRAME_ARRAY, + sizeof(struct i2c_settings_array), + GFP_KERNEL); if (s_ctrl->i2c_data.per_frame == NULL) { rc = -ENOMEM; goto unreg_subdev; @@ -312,8 +313,9 @@ static int32_t cam_sensor_driver_platform_probe( s_ctrl->i2c_data.per_frame = (struct i2c_settings_array *) - kzalloc(sizeof(struct i2c_settings_array) * - MAX_PER_FRAME_ARRAY, GFP_KERNEL); + kcalloc(MAX_PER_FRAME_ARRAY, + sizeof(struct i2c_settings_array), + GFP_KERNEL); if (s_ctrl->i2c_data.per_frame == NULL) { rc = -ENOMEM; goto unreg_subdev; diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c index 5f503d8dc78a..98f9f121f4e9 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c @@ -878,16 +878,18 @@ int32_t cam_sensor_update_power_settings(void *cmd_buf, power_info->power_setting_size = 0; power_info->power_setting = (struct cam_sensor_power_setting *) - kzalloc(sizeof(struct cam_sensor_power_setting) * - MAX_POWER_CONFIG, GFP_KERNEL); + kcalloc(MAX_POWER_CONFIG, + sizeof(struct cam_sensor_power_setting), + GFP_KERNEL); if (!power_info->power_setting) return -ENOMEM; power_info->power_down_setting_size = 0; power_info->power_down_setting = (struct cam_sensor_power_setting *) - kzalloc(sizeof(struct cam_sensor_power_setting) * - MAX_POWER_CONFIG, GFP_KERNEL); + kcalloc(MAX_POWER_CONFIG, + sizeof(struct cam_sensor_power_setting), + GFP_KERNEL); if (!power_info->power_down_setting) { kfree(power_info->power_setting); power_info->power_setting = NULL; diff --git a/drivers/media/platform/msm/camera_v2/common/cam_smmu_api.c b/drivers/media/platform/msm/camera_v2/common/cam_smmu_api.c index 7bdf389e1c96..8ae6f4d35d68 100644 --- a/drivers/media/platform/msm/camera_v2/common/cam_smmu_api.c +++ b/drivers/media/platform/msm/camera_v2/common/cam_smmu_api.c @@ -820,7 +820,7 @@ static int cam_smmu_send_syscall_pix_intf(int vmid, int idx) uint32_t *sid_info = NULL; struct cam_context_bank_info *cb = &iommu_cb_set.cb_info[idx]; - sid_info = kzalloc(sizeof(uint32_t) * 2, GFP_KERNEL); + sid_info = kcalloc(2, sizeof(uint32_t), GFP_KERNEL); if (!sid_info) return -ENOMEM; diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c index d53c81016e1c..b885b24da88d 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c @@ -1075,8 +1075,9 @@ static int msm_isp_request_bufq(struct msm_isp_buf_mgr *buf_mgr, return -EINVAL; } - bufq->bufs = kzalloc(sizeof(struct msm_isp_buffer) * - buf_request->num_buf, GFP_KERNEL); + bufq->bufs = kcalloc(buf_request->num_buf, + sizeof(struct msm_isp_buffer), + GFP_KERNEL); if (!bufq->bufs) { msm_isp_free_bufq_handle(buf_mgr, buf_request->handle); return -ENOMEM; diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util_32.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util_32.c index 41a293660be8..6036c51e5c11 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util_32.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util_32.c @@ -1223,8 +1223,9 @@ int msm_isp_proc_cmd(struct vfe_device *vfe_dev, void *arg) return -EINVAL; } - reg_cfg_cmd = kzalloc(sizeof(struct msm_vfe_reg_cfg_cmd)* - proc_cmd->num_cfg, GFP_KERNEL); + reg_cfg_cmd = kcalloc(proc_cmd->num_cfg, + sizeof(struct msm_vfe_reg_cfg_cmd), + GFP_KERNEL); if (!reg_cfg_cmd) { rc = -ENOMEM; goto reg_cfg_failed; diff --git a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c index fe15782812d2..e4dd91768ea8 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c +++ b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c @@ -1174,8 +1174,9 @@ static int32_t msm_cci_i2c_write_async(struct v4l2_subdev *sd, } cci_i2c_write_cfg_w->reg_setting = - kzalloc(sizeof(struct msm_camera_i2c_reg_array)* - cci_i2c_write_cfg->size, GFP_KERNEL); + kcalloc(cci_i2c_write_cfg->size, + sizeof(struct msm_camera_i2c_reg_array), + GFP_KERNEL); if (!cci_i2c_write_cfg_w->reg_setting) { pr_err("%s: %d Couldn't allocate memory\n", __func__, __LINE__); kfree(write_async); @@ -1904,7 +1905,7 @@ static int32_t msm_cci_init_gpio_params(struct cci_device *cci_dev) } gpio_tbl = cci_dev->cci_gpio_tbl = - kzalloc(sizeof(struct gpio) * tbl_size, GFP_KERNEL); + kcalloc(tbl_size, sizeof(struct gpio), GFP_KERNEL); if (!gpio_tbl) { pr_err("%s failed %d\n", __func__, __LINE__); return 0; diff --git a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c index fa875cbb80a0..b1c7a3f1d6d4 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c +++ b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c @@ -256,8 +256,9 @@ static int32_t msm_flash_i2c_init( } flash_ctrl->power_setting_array.power_setting = - kzalloc(sizeof(struct msm_sensor_power_setting)* - flash_ctrl->power_setting_array.size, GFP_KERNEL); + kcalloc(flash_ctrl->power_setting_array.size, + sizeof(struct msm_sensor_power_setting), + GFP_KERNEL); if (!flash_ctrl->power_setting_array.power_setting) { kfree(power_setting_array32); return -ENOMEM; diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c index ae75ca981dda..d0aad5835bcd 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c +++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c @@ -160,8 +160,9 @@ int32_t msm_camera_cci_i2c_write_seq(struct msm_camera_i2c_client *client, S_I2C_DBG("%s reg addr = 0x%x num bytes: %d\n", __func__, addr, num_byte); - reg_conf_tbl = kzalloc(num_byte * - (sizeof(struct msm_camera_i2c_reg_array)), GFP_KERNEL); + reg_conf_tbl = kcalloc(num_byte, + sizeof(struct msm_camera_i2c_reg_array), + GFP_KERNEL); if (!reg_conf_tbl) return -ENOMEM; diff --git a/drivers/media/platform/msm/camera_v2/sensor/laser_led/msm_laser_led.c b/drivers/media/platform/msm/camera_v2/sensor/laser_led/msm_laser_led.c index fb8a11685693..c5d986cead50 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/laser_led/msm_laser_led.c +++ b/drivers/media/platform/msm/camera_v2/sensor/laser_led/msm_laser_led.c @@ -212,8 +212,9 @@ static int32_t msm_laser_led_control32( return -EFAULT; } - conf_array.reg_setting = kzalloc(conf_array.size * - (sizeof(struct msm_camera_i2c_reg_array)), GFP_KERNEL); + conf_array.reg_setting = kcalloc(conf_array.size, + sizeof(struct msm_camera_i2c_reg_array), + GFP_KERNEL); if (!conf_array.reg_setting) return -ENOMEM; @@ -226,8 +227,9 @@ static int32_t msm_laser_led_control32( return -EFAULT; } if (laser_led_data.debug_reg_size <= sizeof(uint32_t)) { - debug_reg = kzalloc(laser_led_data.debug_reg_size * - (sizeof(uint32_t)), GFP_KERNEL); + debug_reg = kcalloc(laser_led_data.debug_reg_size, + sizeof(uint32_t), + GFP_KERNEL); if (!debug_reg) { kfree(conf_array.reg_setting); return -ENOMEM; @@ -350,8 +352,9 @@ static int32_t msm_laser_led_control( return -EFAULT; } - conf_array.reg_setting = kzalloc(conf_array.size * - (sizeof(struct msm_camera_i2c_reg_array)), GFP_KERNEL); + conf_array.reg_setting = kcalloc(conf_array.size, + sizeof(struct msm_camera_i2c_reg_array), + GFP_KERNEL); if (!conf_array.reg_setting) return -ENOMEM; @@ -364,8 +367,9 @@ static int32_t msm_laser_led_control( return -EFAULT; } if (laser_led_data.debug_reg_size <= sizeof(uint32_t)) { - debug_reg = kzalloc(laser_led_data.debug_reg_size * - (sizeof(uint32_t)), GFP_KERNEL); + debug_reg = kcalloc(laser_led_data.debug_reg_size, + sizeof(uint32_t), + GFP_KERNEL); if (!debug_reg) { kfree(conf_array.reg_setting); return -ENOMEM; diff --git a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c index 349e2b08e45c..ec983f451085 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c +++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c @@ -492,8 +492,9 @@ static int msm_sensor_config32(struct msm_sensor_ctrl_t *s_ctrl, break; } - reg_setting = kzalloc(conf_array.size * - (sizeof(struct msm_camera_i2c_reg_array)), GFP_KERNEL); + reg_setting = kcalloc(conf_array.size, + sizeof(struct msm_camera_i2c_reg_array), + GFP_KERNEL); if (!reg_setting) { rc = -ENOMEM; break; @@ -653,8 +654,9 @@ static int msm_sensor_config32(struct msm_sensor_ctrl_t *s_ctrl, break; } - reg_setting = kzalloc(write_config.conf_array.size * - (sizeof(struct msm_camera_i2c_reg_array)), GFP_KERNEL); + reg_setting = kcalloc(write_config.conf_array.size, + sizeof(struct msm_camera_i2c_reg_array), + GFP_KERNEL); if (!reg_setting) { rc = -ENOMEM; break; @@ -751,9 +753,9 @@ static int msm_sensor_config32(struct msm_sensor_ctrl_t *s_ctrl, break; } - reg_setting = kzalloc(conf_array.size * - (sizeof(struct msm_camera_i2c_seq_reg_array)), - GFP_KERNEL); + reg_setting = kcalloc(conf_array.size, + sizeof(struct msm_camera_i2c_seq_reg_array), + GFP_KERNEL); if (!reg_setting) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -ENOMEM; @@ -862,9 +864,9 @@ static int msm_sensor_config32(struct msm_sensor_ctrl_t *s_ctrl, } if (stop_setting->size <= sizeof(struct msm_camera_i2c_reg_array)) { - stop_setting->reg_setting = kzalloc(stop_setting->size * - (sizeof(struct msm_camera_i2c_reg_array)), - GFP_KERNEL); + stop_setting->reg_setting = kcalloc(stop_setting->size, + sizeof(struct msm_camera_i2c_reg_array), + GFP_KERNEL); if (!stop_setting->reg_setting) { rc = -ENOMEM; break; @@ -1023,8 +1025,9 @@ int msm_sensor_config(struct msm_sensor_ctrl_t *s_ctrl, void *argp) break; } - reg_setting = kzalloc(conf_array.size * - (sizeof(struct msm_camera_i2c_reg_array)), GFP_KERNEL); + reg_setting = kcalloc(conf_array.size, + sizeof(struct msm_camera_i2c_reg_array), + GFP_KERNEL); if (!reg_setting) { rc = -ENOMEM; break; @@ -1163,8 +1166,9 @@ int msm_sensor_config(struct msm_sensor_ctrl_t *s_ctrl, void *argp) break; } - reg_setting = kzalloc(write_config.conf_array.size * - (sizeof(struct msm_camera_i2c_reg_array)), GFP_KERNEL); + reg_setting = kcalloc(write_config.conf_array.size, + sizeof(struct msm_camera_i2c_reg_array), + GFP_KERNEL); if (!reg_setting) { rc = -ENOMEM; break; @@ -1250,9 +1254,9 @@ int msm_sensor_config(struct msm_sensor_ctrl_t *s_ctrl, void *argp) break; } - reg_setting = kzalloc(conf_array.size * - (sizeof(struct msm_camera_i2c_seq_reg_array)), - GFP_KERNEL); + reg_setting = kcalloc(conf_array.size, + sizeof(struct msm_camera_i2c_seq_reg_array), + GFP_KERNEL); if (!reg_setting) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -ENOMEM; @@ -1359,9 +1363,9 @@ int msm_sensor_config(struct msm_sensor_ctrl_t *s_ctrl, void *argp) } if (stop_setting->size <= sizeof(struct msm_camera_i2c_reg_array)) { - stop_setting->reg_setting = kzalloc(stop_setting->size * - (sizeof(struct msm_camera_i2c_reg_array)), - GFP_KERNEL); + stop_setting->reg_setting = kcalloc(stop_setting->size, + sizeof(struct msm_camera_i2c_reg_array), + GFP_KERNEL); if (!stop_setting->reg_setting) { rc = -ENOMEM; break; diff --git a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c index 7d7b5cde2f66..0c0e011451ae 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c +++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c @@ -483,7 +483,7 @@ static int32_t msm_sensor_get_pw_settings_compat( { int32_t rc = 0, i = 0; struct msm_sensor_power_setting32 *ps32 = - kzalloc(sizeof(*ps32) * size, GFP_KERNEL); + kcalloc(size, sizeof(*ps32), GFP_KERNEL); if (!ps32) { pr_err("failed: no memory ps32"); @@ -832,9 +832,8 @@ int32_t msm_sensor_driver_probe(void *setting, } else { id_info = &(slave_info->sensor_id_info); reg_setting = - kzalloc(id_info->setting.size * - (sizeof - (struct msm_camera_i2c_reg_array)), + kcalloc(id_info->setting.size, + sizeof(struct msm_camera_i2c_reg_array), GFP_KERNEL); if (!reg_setting) { kfree(slave_info32); @@ -901,9 +900,8 @@ int32_t msm_sensor_driver_probe(void *setting, } else { id_info = &(slave_info->sensor_id_info); reg_setting = - kzalloc(id_info->setting.size * - (sizeof - (struct msm_camera_i2c_reg_array)), + kcalloc(id_info->setting.size, + sizeof(struct msm_camera_i2c_reg_array), GFP_KERNEL); if (!reg_setting) { rc = -ENOMEM; diff --git a/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c b/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c index 3d28660558f0..335f6e54318a 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c +++ b/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c @@ -544,9 +544,9 @@ static int32_t msm_ois_config(struct msm_ois_ctrl_t *o_ctrl, rc = -EFAULT; break; } - reg_setting = kzalloc(conf_array.size * - (sizeof(struct msm_camera_i2c_seq_reg_array)), - GFP_KERNEL); + reg_setting = kcalloc(conf_array.size, + sizeof(struct msm_camera_i2c_seq_reg_array), + GFP_KERNEL); if (!reg_setting) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -ENOMEM; diff --git a/drivers/media/platform/msm/npu/npu_mgr.c b/drivers/media/platform/msm/npu/npu_mgr.c index 6a22540d88c1..d36836402781 100644 --- a/drivers/media/platform/msm/npu/npu_mgr.c +++ b/drivers/media/platform/msm/npu/npu_mgr.c @@ -1013,7 +1013,7 @@ static void host_session_msg_hdlr(struct npu_device *npu_dev) uint32_t *msg; struct npu_host_ctx *host_ctx = &npu_dev->host_ctx; - msg = kzalloc(sizeof(uint32_t) * NPU_IPC_BUF_LENGTH, GFP_KERNEL); + msg = kcalloc(NPU_IPC_BUF_LENGTH, sizeof(uint32_t), GFP_KERNEL); if (!msg) return; @@ -1059,7 +1059,7 @@ static void host_session_log_hdlr(struct npu_device *npu_dev) uint32_t *msg; struct npu_host_ctx *host_ctx = &npu_dev->host_ctx; - msg = kzalloc(sizeof(uint32_t) * NPU_IPC_BUF_LENGTH, GFP_KERNEL); + msg = kcalloc(NPU_IPC_BUF_LENGTH, sizeof(uint32_t), GFP_KERNEL); if (!msg) return; diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c index 341d2d92af9f..4deed7f6b8ed 100644 --- a/drivers/media/platform/msm/vidc/venus_hfi.c +++ b/drivers/media/platform/msm/vidc/venus_hfi.c @@ -4303,8 +4303,8 @@ static int __init_resources(struct venus_hfi_device *device, dprintk(VIDC_WARN, "Failed to init subcaches: %d\n", rc); device->sys_init_capabilities = - kzalloc(sizeof(struct msm_vidc_capability) - * VIDC_MAX_SESSIONS, GFP_KERNEL); + kcalloc(VIDC_MAX_SESSIONS, sizeof(struct msm_vidc_capability), + GFP_KERNEL); return rc; diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c index 067f46c4f61a..8c0acec48e5e 100644 --- a/drivers/media/usb/au0828/au0828-video.c +++ b/drivers/media/usb/au0828/au0828-video.c @@ -217,14 +217,14 @@ static int au0828_init_isoc(struct au0828_dev *dev, int max_packets, dev->isoc_ctl.isoc_copy = isoc_copy; dev->isoc_ctl.num_bufs = num_bufs; - dev->isoc_ctl.urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL); + dev->isoc_ctl.urb = kcalloc(num_bufs, sizeof(void *), GFP_KERNEL); if (!dev->isoc_ctl.urb) { au0828_isocdbg("cannot alloc memory for usb buffers\n"); return -ENOMEM; } - dev->isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs, - GFP_KERNEL); + dev->isoc_ctl.transfer_buffer = kcalloc(num_bufs, sizeof(void *), + GFP_KERNEL); if (!dev->isoc_ctl.transfer_buffer) { au0828_isocdbg("cannot allocate memory for usb transfer\n"); kfree(dev->isoc_ctl.urb); diff --git a/drivers/media/usb/cx231xx/cx231xx-core.c b/drivers/media/usb/cx231xx/cx231xx-core.c index f372ad3917a8..d10c2c5367d8 100644 --- a/drivers/media/usb/cx231xx/cx231xx-core.c +++ b/drivers/media/usb/cx231xx/cx231xx-core.c @@ -1034,7 +1034,7 @@ int cx231xx_init_isoc(struct cx231xx *dev, int max_packets, dma_q->partial_buf[i] = 0; dev->video_mode.isoc_ctl.urb = - kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL); + kcalloc(num_bufs, sizeof(void *), GFP_KERNEL); if (!dev->video_mode.isoc_ctl.urb) { dev_err(dev->dev, "cannot alloc memory for usb buffers\n"); @@ -1042,7 +1042,7 @@ int cx231xx_init_isoc(struct cx231xx *dev, int max_packets, } dev->video_mode.isoc_ctl.transfer_buffer = - kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL); + kcalloc(num_bufs, sizeof(void *), GFP_KERNEL); if (!dev->video_mode.isoc_ctl.transfer_buffer) { dev_err(dev->dev, "cannot allocate memory for usbtransfer\n"); @@ -1169,7 +1169,7 @@ int cx231xx_init_bulk(struct cx231xx *dev, int max_packets, dma_q->partial_buf[i] = 0; dev->video_mode.bulk_ctl.urb = - kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL); + kcalloc(num_bufs, sizeof(void *), GFP_KERNEL); if (!dev->video_mode.bulk_ctl.urb) { dev_err(dev->dev, "cannot alloc memory for usb buffers\n"); @@ -1177,7 +1177,7 @@ int cx231xx_init_bulk(struct cx231xx *dev, int max_packets, } dev->video_mode.bulk_ctl.transfer_buffer = - kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL); + kcalloc(num_bufs, sizeof(void *), GFP_KERNEL); if (!dev->video_mode.bulk_ctl.transfer_buffer) { dev_err(dev->dev, "cannot allocate memory for usbtransfer\n"); diff --git a/drivers/media/usb/cx231xx/cx231xx-vbi.c b/drivers/media/usb/cx231xx/cx231xx-vbi.c index 76e901920f6f..ccc42b693064 100644 --- a/drivers/media/usb/cx231xx/cx231xx-vbi.c +++ b/drivers/media/usb/cx231xx/cx231xx-vbi.c @@ -415,7 +415,7 @@ int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets, for (i = 0; i < 8; i++) dma_q->partial_buf[i] = 0; - dev->vbi_mode.bulk_ctl.urb = kzalloc(sizeof(void *) * num_bufs, + dev->vbi_mode.bulk_ctl.urb = kcalloc(num_bufs, sizeof(void *), GFP_KERNEL); if (!dev->vbi_mode.bulk_ctl.urb) { dev_err(dev->dev, @@ -424,7 +424,7 @@ int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets, } dev->vbi_mode.bulk_ctl.transfer_buffer = - kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL); + kcalloc(num_bufs, sizeof(void *), GFP_KERNEL); if (!dev->vbi_mode.bulk_ctl.transfer_buffer) { dev_err(dev->dev, "cannot allocate memory for usbtransfer\n"); diff --git a/drivers/media/usb/em28xx/em28xx-core.c b/drivers/media/usb/em28xx/em28xx-core.c index 1d0d8cc06103..476666ffab96 100644 --- a/drivers/media/usb/em28xx/em28xx-core.c +++ b/drivers/media/usb/em28xx/em28xx-core.c @@ -912,11 +912,11 @@ int em28xx_alloc_urbs(struct em28xx *dev, enum em28xx_mode mode, int xfer_bulk, usb_bufs->num_bufs = num_bufs; - usb_bufs->urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL); + usb_bufs->urb = kcalloc(num_bufs, sizeof(void *), GFP_KERNEL); if (!usb_bufs->urb) return -ENOMEM; - usb_bufs->transfer_buffer = kzalloc(sizeof(void *)*num_bufs, + usb_bufs->transfer_buffer = kcalloc(num_bufs, sizeof(void *), GFP_KERNEL); if (!usb_bufs->transfer_buffer) { kfree(usb_bufs->urb); diff --git a/drivers/media/usb/go7007/go7007-fw.c b/drivers/media/usb/go7007/go7007-fw.c index a5efcd4f7b4f..e4b318fe8fc8 100644 --- a/drivers/media/usb/go7007/go7007-fw.c +++ b/drivers/media/usb/go7007/go7007-fw.c @@ -1576,7 +1576,7 @@ int go7007_construct_fw_image(struct go7007 *go, u8 **fw, int *fwlen) GO7007_FW_NAME); return -1; } - code = kzalloc(codespace * 2, GFP_KERNEL); + code = kcalloc(codespace, 2, GFP_KERNEL); if (code == NULL) goto fw_failed; diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c index 18db7aaafcd6..38bf44edafc4 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c @@ -2417,7 +2417,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, hdw->control_cnt = CTRLDEF_COUNT; hdw->control_cnt += MPEGDEF_COUNT; - hdw->controls = kzalloc(sizeof(struct pvr2_ctrl) * hdw->control_cnt, + hdw->controls = kcalloc(hdw->control_cnt, sizeof(struct pvr2_ctrl), GFP_KERNEL); if (!hdw->controls) goto fail; hdw->hdw_desc = hdw_desc; diff --git a/drivers/media/usb/pvrusb2/pvrusb2-std.c b/drivers/media/usb/pvrusb2/pvrusb2-std.c index 243e2704ce3a..37dc299a1ca2 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-std.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-std.c @@ -361,7 +361,7 @@ struct v4l2_standard *pvr2_std_create_enum(unsigned int *countptr, std_cnt); if (!std_cnt) return NULL; // paranoia - stddefs = kzalloc(sizeof(struct v4l2_standard) * std_cnt, + stddefs = kcalloc(std_cnt, sizeof(struct v4l2_standard), GFP_KERNEL); if (!stddefs) return NULL; diff --git a/drivers/media/usb/stk1160/stk1160-video.c b/drivers/media/usb/stk1160/stk1160-video.c index ce8ebbe395a6..0c8378739593 100644 --- a/drivers/media/usb/stk1160/stk1160-video.c +++ b/drivers/media/usb/stk1160/stk1160-video.c @@ -439,14 +439,14 @@ int stk1160_alloc_isoc(struct stk1160 *dev) dev->isoc_ctl.buf = NULL; dev->isoc_ctl.max_pkt_size = dev->max_pkt_size; - dev->isoc_ctl.urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL); + dev->isoc_ctl.urb = kcalloc(num_bufs, sizeof(void *), GFP_KERNEL); if (!dev->isoc_ctl.urb) { stk1160_err("out of memory for urb array\n"); return -ENOMEM; } - dev->isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs, - GFP_KERNEL); + dev->isoc_ctl.transfer_buffer = kcalloc(num_bufs, sizeof(void *), + GFP_KERNEL); if (!dev->isoc_ctl.transfer_buffer) { stk1160_err("out of memory for usb transfers\n"); kfree(dev->isoc_ctl.urb); diff --git a/drivers/media/usb/stkwebcam/stk-webcam.c b/drivers/media/usb/stkwebcam/stk-webcam.c index 6992e84f8a8b..c4238f5ffc29 100644 --- a/drivers/media/usb/stkwebcam/stk-webcam.c +++ b/drivers/media/usb/stkwebcam/stk-webcam.c @@ -571,8 +571,9 @@ static int stk_prepare_sio_buffers(struct stk_camera *dev, unsigned n_sbufs) if (dev->sio_bufs != NULL) pr_err("sio_bufs already allocated\n"); else { - dev->sio_bufs = kzalloc(n_sbufs * sizeof(struct stk_sio_buffer), - GFP_KERNEL); + dev->sio_bufs = kcalloc(n_sbufs, + sizeof(struct stk_sio_buffer), + GFP_KERNEL); if (dev->sio_bufs == NULL) return -ENOMEM; for (i = 0; i < n_sbufs; i++) { diff --git a/drivers/media/usb/usbtv/usbtv-video.c b/drivers/media/usb/usbtv/usbtv-video.c index 7c23d82313a8..3c5960c24f1b 100644 --- a/drivers/media/usb/usbtv/usbtv-video.c +++ b/drivers/media/usb/usbtv/usbtv-video.c @@ -424,7 +424,7 @@ static struct urb *usbtv_setup_iso_transfer(struct usbtv *usbtv) ip->pipe = usb_rcvisocpipe(usbtv->udev, USBTV_VIDEO_ENDP); ip->interval = 1; ip->transfer_flags = URB_ISO_ASAP; - ip->transfer_buffer = kzalloc(size * USBTV_ISOC_PACKETS, + ip->transfer_buffer = kcalloc(USBTV_ISOC_PACKETS, size, GFP_KERNEL); if (!ip->transfer_buffer) { usb_free_urb(ip); diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index 5c8ed2150c8b..182973df1aed 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c @@ -158,7 +158,7 @@ static int mfd_add_device(struct device *parent, int id, if (!pdev) goto fail_alloc; - res = kzalloc(sizeof(*res) * cell->num_resources, GFP_KERNEL); + res = kcalloc(cell->num_resources, sizeof(*res), GFP_KERNEL); if (!res) goto fail_device; diff --git a/drivers/mfd/timberdale.c b/drivers/mfd/timberdale.c index cd4a6d7d6750..07579fc0d93c 100644 --- a/drivers/mfd/timberdale.c +++ b/drivers/mfd/timberdale.c @@ -707,8 +707,8 @@ static int timb_probe(struct pci_dev *dev, goto err_config; } - msix_entries = kzalloc(TIMBERDALE_NR_IRQS * sizeof(*msix_entries), - GFP_KERNEL); + msix_entries = kcalloc(TIMBERDALE_NR_IRQS, sizeof(*msix_entries), + GFP_KERNEL); if (!msix_entries) goto err_config; diff --git a/drivers/misc/altera-stapl/altera.c b/drivers/misc/altera-stapl/altera.c index b7ee8043a133..94bde09d9323 100644 --- a/drivers/misc/altera-stapl/altera.c +++ b/drivers/misc/altera-stapl/altera.c @@ -304,13 +304,13 @@ static int altera_execute(struct altera_state *astate, if (sym_count <= 0) goto exit_done; - vars = kzalloc(sym_count * sizeof(long), GFP_KERNEL); + vars = kcalloc(sym_count, sizeof(long), GFP_KERNEL); if (vars == NULL) status = -ENOMEM; if (status == 0) { - var_size = kzalloc(sym_count * sizeof(s32), GFP_KERNEL); + var_size = kcalloc(sym_count, sizeof(s32), GFP_KERNEL); if (var_size == NULL) status = -ENOMEM; @@ -1136,7 +1136,7 @@ exit_done: /* Allocate a writable buffer for this array */ count = var_size[variable_id]; long_tmp = vars[variable_id]; - longptr_tmp = kzalloc(count * sizeof(long), + longptr_tmp = kcalloc(count, sizeof(long), GFP_KERNEL); vars[variable_id] = (long)longptr_tmp; diff --git a/drivers/misc/cxl/guest.c b/drivers/misc/cxl/guest.c index de2ce5539545..73cbd1544a7b 100644 --- a/drivers/misc/cxl/guest.c +++ b/drivers/misc/cxl/guest.c @@ -89,7 +89,7 @@ static ssize_t guest_collect_vpd(struct cxl *adapter, struct cxl_afu *afu, mod = 0; } - vpd_buf = kzalloc(entries * sizeof(unsigned long *), GFP_KERNEL); + vpd_buf = kcalloc(entries, sizeof(unsigned long *), GFP_KERNEL); if (!vpd_buf) return -ENOMEM; diff --git a/drivers/misc/cxl/of.c b/drivers/misc/cxl/of.c index ec175ea5dfba..aff181cd0bf2 100644 --- a/drivers/misc/cxl/of.c +++ b/drivers/misc/cxl/of.c @@ -302,7 +302,7 @@ static int read_adapter_irq_config(struct cxl *adapter, struct device_node *np) if (nranges == 0 || (nranges * 2 * sizeof(int)) != len) return -EINVAL; - adapter->guest->irq_avail = kzalloc(nranges * sizeof(struct irq_avail), + adapter->guest->irq_avail = kcalloc(nranges, sizeof(struct irq_avail), GFP_KERNEL); if (adapter->guest->irq_avail == NULL) return -ENOMEM; diff --git a/drivers/misc/genwqe/card_ddcb.c b/drivers/misc/genwqe/card_ddcb.c index ddfeefe39540..9af976db90a0 100644 --- a/drivers/misc/genwqe/card_ddcb.c +++ b/drivers/misc/genwqe/card_ddcb.c @@ -1048,15 +1048,16 @@ static int setup_ddcb_queue(struct genwqe_dev *cd, struct ddcb_queue *queue) "[%s] **err: could not allocate DDCB **\n", __func__); return -ENOMEM; } - queue->ddcb_req = kzalloc(sizeof(struct ddcb_requ *) * - queue->ddcb_max, GFP_KERNEL); + queue->ddcb_req = kcalloc(queue->ddcb_max, sizeof(struct ddcb_requ *), + GFP_KERNEL); if (!queue->ddcb_req) { rc = -ENOMEM; goto free_ddcbs; } - queue->ddcb_waitqs = kzalloc(sizeof(wait_queue_head_t) * - queue->ddcb_max, GFP_KERNEL); + queue->ddcb_waitqs = kcalloc(queue->ddcb_max, + sizeof(wait_queue_head_t), + GFP_KERNEL); if (!queue->ddcb_waitqs) { rc = -ENOMEM; goto free_requs; diff --git a/drivers/misc/sgi-xp/xpc_main.c b/drivers/misc/sgi-xp/xpc_main.c index 7f327121e6d7..f1bce8335575 100644 --- a/drivers/misc/sgi-xp/xpc_main.c +++ b/drivers/misc/sgi-xp/xpc_main.c @@ -417,7 +417,8 @@ xpc_setup_ch_structures(struct xpc_partition *part) * memory. */ DBUG_ON(part->channels != NULL); - part->channels = kzalloc(sizeof(struct xpc_channel) * XPC_MAX_NCHANNELS, + part->channels = kcalloc(XPC_MAX_NCHANNELS, + sizeof(struct xpc_channel), GFP_KERNEL); if (part->channels == NULL) { dev_err(xpc_chan, "can't get memory for channels\n"); @@ -906,8 +907,9 @@ xpc_setup_partitions(void) short partid; struct xpc_partition *part; - xpc_partitions = kzalloc(sizeof(struct xpc_partition) * - xp_max_npartitions, GFP_KERNEL); + xpc_partitions = kcalloc(xp_max_npartitions, + sizeof(struct xpc_partition), + GFP_KERNEL); if (xpc_partitions == NULL) { dev_err(xpc_part, "can't get memory for partition structure\n"); return -ENOMEM; diff --git a/drivers/misc/sgi-xp/xpc_partition.c b/drivers/misc/sgi-xp/xpc_partition.c index ca5f0102daef..b6da4fe6c7bf 100644 --- a/drivers/misc/sgi-xp/xpc_partition.c +++ b/drivers/misc/sgi-xp/xpc_partition.c @@ -425,7 +425,7 @@ xpc_discovery(void) if (remote_rp == NULL) return; - discovered_nasids = kzalloc(sizeof(long) * xpc_nasid_mask_nlongs, + discovered_nasids = kcalloc(xpc_nasid_mask_nlongs, sizeof(long), GFP_KERNEL); if (discovered_nasids == NULL) { kfree(remote_rp_base); diff --git a/drivers/misc/sgi-xp/xpnet.c b/drivers/misc/sgi-xp/xpnet.c index 0c26eaf5f62b..1704fd426ad7 100644 --- a/drivers/misc/sgi-xp/xpnet.c +++ b/drivers/misc/sgi-xp/xpnet.c @@ -520,8 +520,9 @@ xpnet_init(void) dev_info(xpnet, "registering network device %s\n", XPNET_DEVICE_NAME); - xpnet_broadcast_partitions = kzalloc(BITS_TO_LONGS(xp_max_npartitions) * - sizeof(long), GFP_KERNEL); + xpnet_broadcast_partitions = kcalloc(BITS_TO_LONGS(xp_max_npartitions), + sizeof(long), + GFP_KERNEL); if (xpnet_broadcast_partitions == NULL) return -ENOMEM; diff --git a/drivers/misc/sram.c b/drivers/misc/sram.c index 8daefb81ba29..b856b7ede260 100644 --- a/drivers/misc/sram.c +++ b/drivers/misc/sram.c @@ -185,7 +185,7 @@ static int sram_reserve_regions(struct sram_dev *sram, struct resource *res) * after the reserved blocks from the dt are processed. */ nblocks = (np) ? of_get_available_child_count(np) + 1 : 1; - rblocks = kzalloc((nblocks) * sizeof(*rblocks), GFP_KERNEL); + rblocks = kcalloc(nblocks, sizeof(*rblocks), GFP_KERNEL); if (!rblocks) return -ENOMEM; diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 4ef30120be4d..d57942521149 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -678,10 +678,9 @@ out: * freq_table in clk_scaling is un32. Here allocates an individual * memory space for it and release it when exit clock scaling. */ - clk_scaling->devfreq_profile.freq_table = kzalloc( - clk_scaling->freq_table_sz * - sizeof(*(clk_scaling->devfreq_profile.freq_table)), - GFP_KERNEL); + clk_scaling->devfreq_profile.freq_table = kcalloc(clk_scaling->freq_table_sz, + sizeof(*(clk_scaling->devfreq_profile.freq_table)), + GFP_KERNEL); if (!clk_scaling->devfreq_profile.freq_table) return -ENOMEM; clk_scaling->devfreq_profile.max_state = clk_scaling->freq_table_sz; diff --git a/drivers/mtd/ar7part.c b/drivers/mtd/ar7part.c index 90575deff0ae..fc15ec58230a 100644 --- a/drivers/mtd/ar7part.c +++ b/drivers/mtd/ar7part.c @@ -55,7 +55,7 @@ static int create_mtd_partitions(struct mtd_info *master, int retries = 10; struct mtd_partition *ar7_parts; - ar7_parts = kzalloc(sizeof(*ar7_parts) * AR7_PARTS, GFP_KERNEL); + ar7_parts = kcalloc(AR7_PARTS, sizeof(*ar7_parts), GFP_KERNEL); if (!ar7_parts) return -ENOMEM; ar7_parts[0].name = "loader"; diff --git a/drivers/mtd/bcm47xxpart.c b/drivers/mtd/bcm47xxpart.c index fe2581d9d882..2848514b1e70 100644 --- a/drivers/mtd/bcm47xxpart.c +++ b/drivers/mtd/bcm47xxpart.c @@ -110,7 +110,7 @@ static int bcm47xxpart_parse(struct mtd_info *master, blocksize = 0x1000; /* Alloc */ - parts = kzalloc(sizeof(struct mtd_partition) * BCM47XXPART_MAX_PARTS, + parts = kcalloc(BCM47XXPART_MAX_PARTS, sizeof(struct mtd_partition), GFP_KERNEL); if (!parts) return -ENOMEM; diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index c311fa2d010e..2f194a8cfb8e 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c @@ -608,8 +608,9 @@ static struct mtd_info *cfi_intelext_setup(struct mtd_info *mtd) mtd->size = devsize * cfi->numchips; mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips; - mtd->eraseregions = kzalloc(sizeof(struct mtd_erase_region_info) - * mtd->numeraseregions, GFP_KERNEL); + mtd->eraseregions = kcalloc(mtd->numeraseregions, + sizeof(struct mtd_erase_region_info), + GFP_KERNEL); if (!mtd->eraseregions) goto setup_err; diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index e99de6beee7c..287e5d1d021e 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -2669,7 +2669,7 @@ static int __maybe_unused cfi_ppb_unlock(struct mtd_info *mtd, loff_t ofs, * first check the locking status of all sectors and save * it for future use. */ - sect = kzalloc(MAX_SECTORS * sizeof(struct ppb_lock), GFP_KERNEL); + sect = kcalloc(MAX_SECTORS, sizeof(struct ppb_lock), GFP_KERNEL); if (!sect) return -ENOMEM; diff --git a/drivers/mtd/devices/docg3.c b/drivers/mtd/devices/docg3.c index 0806f72102c0..6552696f2d45 100644 --- a/drivers/mtd/devices/docg3.c +++ b/drivers/mtd/devices/docg3.c @@ -1910,7 +1910,7 @@ doc_probe_device(struct docg3_cascade *cascade, int floor, struct device *dev) mtd->dev.parent = dev; bbt_nbpages = DIV_ROUND_UP(docg3->max_block + 1, 8 * DOC_LAYOUT_PAGE_SIZE); - docg3->bbt = kzalloc(bbt_nbpages * DOC_LAYOUT_PAGE_SIZE, GFP_KERNEL); + docg3->bbt = kcalloc(DOC_LAYOUT_PAGE_SIZE, bbt_nbpages, GFP_KERNEL); if (!docg3->bbt) goto nomem3; diff --git a/drivers/mtd/maps/physmap_of_core.c b/drivers/mtd/maps/physmap_of_core.c index 5d8399742c75..65663e86ff00 100644 --- a/drivers/mtd/maps/physmap_of_core.c +++ b/drivers/mtd/maps/physmap_of_core.c @@ -114,7 +114,7 @@ static const char * const *of_get_probes(struct device_node *dp) if (count < 0) return part_probe_types_def; - res = kzalloc((count + 1) * sizeof(*res), GFP_KERNEL); + res = kcalloc(count + 1, sizeof(*res), GFP_KERNEL); if (!res) return NULL; @@ -187,7 +187,7 @@ static int of_flash_probe(struct platform_device *dev) dev_set_drvdata(&dev->dev, info); - mtd_list = kzalloc(sizeof(*mtd_list) * count, GFP_KERNEL); + mtd_list = kcalloc(count, sizeof(*mtd_list), GFP_KERNEL); if (!mtd_list) goto err_flash_remove; diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c index 6bdf4e525677..9441a86f03ab 100644 --- a/drivers/mtd/ofpart.c +++ b/drivers/mtd/ofpart.c @@ -71,7 +71,7 @@ static int parse_ofpart_partitions(struct mtd_info *master, if (nr_parts == 0) return 0; - parts = kzalloc(nr_parts * sizeof(*parts), GFP_KERNEL); + parts = kcalloc(nr_parts, sizeof(*parts), GFP_KERNEL); if (!parts) return -ENOMEM; @@ -170,7 +170,7 @@ static int parse_ofoldpart_partitions(struct mtd_info *master, nr_parts = plen / sizeof(part[0]); - parts = kzalloc(nr_parts * sizeof(*parts), GFP_KERNEL); + parts = kcalloc(nr_parts, sizeof(*parts), GFP_KERNEL); if (!parts) return -ENOMEM; diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index 1a6d0e367b89..2e6ef0fc80b5 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -3819,8 +3819,9 @@ static int onenand_probe(struct mtd_info *mtd) this->dies = ONENAND_IS_DDP(this) ? 2 : 1; /* Maximum possible erase regions */ mtd->numeraseregions = this->dies << 1; - mtd->eraseregions = kzalloc(sizeof(struct mtd_erase_region_info) - * (this->dies << 1), GFP_KERNEL); + mtd->eraseregions = kcalloc(this->dies << 1, + sizeof(struct mtd_erase_region_info), + GFP_KERNEL); if (!mtd->eraseregions) return -ENOMEM; } diff --git a/drivers/mtd/parsers/parser_trx.c b/drivers/mtd/parsers/parser_trx.c index df360a75e1eb..17ac33599783 100644 --- a/drivers/mtd/parsers/parser_trx.c +++ b/drivers/mtd/parsers/parser_trx.c @@ -62,7 +62,7 @@ static int parser_trx_parse(struct mtd_info *mtd, uint8_t curr_part = 0, i = 0; int err; - parts = kzalloc(sizeof(struct mtd_partition) * TRX_PARSER_MAX_PARTS, + parts = kcalloc(TRX_PARSER_MAX_PARTS, sizeof(struct mtd_partition), GFP_KERNEL); if (!parts) return -ENOMEM; diff --git a/drivers/mtd/sm_ftl.c b/drivers/mtd/sm_ftl.c index aed391b68ef6..5122a0075bad 100644 --- a/drivers/mtd/sm_ftl.c +++ b/drivers/mtd/sm_ftl.c @@ -82,7 +82,7 @@ static struct attribute_group *sm_create_sysfs_attributes(struct sm_ftl *ftl) /* Create array of pointers to the attributes */ - attributes = kzalloc(sizeof(struct attribute *) * (NUM_ATTRIBUTES + 1), + attributes = kcalloc(NUM_ATTRIBUTES + 1, sizeof(struct attribute *), GFP_KERNEL); if (!attributes) goto error3; @@ -1156,7 +1156,7 @@ static void sm_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) goto error2; /* Allocate zone array, it will be initialized on demand */ - ftl->zones = kzalloc(sizeof(struct ftl_zone) * ftl->zone_count, + ftl->zones = kcalloc(ftl->zone_count, sizeof(struct ftl_zone), GFP_KERNEL); if (!ftl->zones) goto error3; diff --git a/drivers/mtd/tests/pagetest.c b/drivers/mtd/tests/pagetest.c index ff1e0565b020..985fb1eaaf12 100644 --- a/drivers/mtd/tests/pagetest.c +++ b/drivers/mtd/tests/pagetest.c @@ -127,7 +127,7 @@ static int crosstest(void) unsigned char *pp1, *pp2, *pp3, *pp4; pr_info("crosstest\n"); - pp1 = kzalloc(pgsize * 4, GFP_KERNEL); + pp1 = kcalloc(pgsize, 4, GFP_KERNEL); if (!pp1) return -ENOMEM; pp2 = pp1 + pgsize; diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 5c0332e31138..80cb793fdabf 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -1846,7 +1846,7 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai) sprintf(ubi->bgt_name, UBI_BGT_NAME_PATTERN, ubi->ubi_num); err = -ENOMEM; - ubi->lookuptbl = kzalloc(ubi->peb_count * sizeof(void *), GFP_KERNEL); + ubi->lookuptbl = kcalloc(ubi->peb_count, sizeof(void *), GFP_KERNEL); if (!ubi->lookuptbl) return err; diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 1f867e275408..90e1df5b7dab 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -2407,7 +2407,7 @@ struct bond_vlan_tag *bond_verify_device_path(struct net_device *start_dev, struct list_head *iter; if (start_dev == end_dev) { - tags = kzalloc(sizeof(*tags) * (level + 1), GFP_ATOMIC); + tags = kcalloc(level + 1, sizeof(*tags), GFP_ATOMIC); if (!tags) return ERR_PTR(-ENOMEM); tags[level].vlan_proto = VLAN_N_VID; diff --git a/drivers/net/can/grcan.c b/drivers/net/can/grcan.c index a7be12d9a139..55f75f48bffe 100644 --- a/drivers/net/can/grcan.c +++ b/drivers/net/can/grcan.c @@ -1057,7 +1057,7 @@ static int grcan_open(struct net_device *dev) return err; } - priv->echo_skb = kzalloc(dma->tx.size * sizeof(*priv->echo_skb), + priv->echo_skb = kcalloc(dma->tx.size, sizeof(*priv->echo_skb), GFP_KERNEL); if (!priv->echo_skb) { err = -ENOMEM; @@ -1066,7 +1066,7 @@ static int grcan_open(struct net_device *dev) priv->can.echo_skb_max = dma->tx.size; priv->can.echo_skb = priv->echo_skb; - priv->txdlc = kzalloc(dma->tx.size * sizeof(*priv->txdlc), GFP_KERNEL); + priv->txdlc = kcalloc(dma->tx.size, sizeof(*priv->txdlc), GFP_KERNEL); if (!priv->txdlc) { err = -ENOMEM; goto exit_free_echo_skb; diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c index c5a616395c49..d2ec861b5a7d 100644 --- a/drivers/net/can/slcan.c +++ b/drivers/net/can/slcan.c @@ -714,7 +714,7 @@ static int __init slcan_init(void) pr_info("slcan: serial line CAN interface driver\n"); pr_info("slcan: %d dynamic interface channels.\n", maxdev); - slcan_devs = kzalloc(sizeof(struct net_device *)*maxdev, GFP_KERNEL); + slcan_devs = kcalloc(maxdev, sizeof(struct net_device *), GFP_KERNEL); if (!slcan_devs) return -ENOMEM; diff --git a/drivers/net/ethernet/broadcom/bcm63xx_enet.c b/drivers/net/ethernet/broadcom/bcm63xx_enet.c index 35eb0119b015..fb57abb409c2 100644 --- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c +++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c @@ -2182,7 +2182,7 @@ static int bcm_enetsw_open(struct net_device *dev) priv->tx_desc_alloc_size = size; priv->tx_desc_cpu = p; - priv->tx_skb = kzalloc(sizeof(struct sk_buff *) * priv->tx_ring_size, + priv->tx_skb = kcalloc(priv->tx_ring_size, sizeof(struct sk_buff *), GFP_KERNEL); if (!priv->tx_skb) { dev_err(kdev, "cannot allocate rx skb queue\n"); @@ -2196,7 +2196,7 @@ static int bcm_enetsw_open(struct net_device *dev) spin_lock_init(&priv->tx_lock); /* init & fill rx ring with skbs */ - priv->rx_skb = kzalloc(sizeof(struct sk_buff *) * priv->rx_ring_size, + priv->rx_skb = kcalloc(priv->rx_ring_size, sizeof(struct sk_buff *), GFP_KERNEL); if (!priv->rx_skb) { dev_err(kdev, "cannot allocate rx skb queue\n"); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c index 1977e0c552df..4ec2d1a5b955 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c @@ -571,7 +571,7 @@ int bnx2x_vf_mcast(struct bnx2x *bp, struct bnx2x_virtf *vf, else set_bit(RAMROD_COMP_WAIT, &mcast.ramrod_flags); if (mc_num) { - mc = kzalloc(mc_num * sizeof(struct bnx2x_mcast_list_elem), + mc = kcalloc(mc_num, sizeof(struct bnx2x_mcast_list_elem), GFP_KERNEL); if (!mc) { BNX2X_ERR("Cannot Configure multicasts due to lack of memory\n"); @@ -1251,8 +1251,9 @@ int bnx2x_iov_init_one(struct bnx2x *bp, int int_mode_param, num_vfs_param, iov->nr_virtfn); /* allocate the vf array */ - bp->vfdb->vfs = kzalloc(sizeof(struct bnx2x_virtf) * - BNX2X_NR_VIRTFN(bp), GFP_KERNEL); + bp->vfdb->vfs = kcalloc(BNX2X_NR_VIRTFN(bp), + sizeof(struct bnx2x_virtf), + GFP_KERNEL); if (!bp->vfdb->vfs) { BNX2X_ERR("failed to allocate vf array\n"); err = -ENOMEM; @@ -1276,9 +1277,9 @@ int bnx2x_iov_init_one(struct bnx2x *bp, int int_mode_param, } /* allocate the queue arrays for all VFs */ - bp->vfdb->vfqs = kzalloc( - BNX2X_MAX_NUM_VF_QUEUES * sizeof(struct bnx2x_vf_queue), - GFP_KERNEL); + bp->vfdb->vfqs = kcalloc(BNX2X_MAX_NUM_VF_QUEUES, + sizeof(struct bnx2x_vf_queue), + GFP_KERNEL); if (!bp->vfdb->vfqs) { BNX2X_ERR("failed to allocate vf queue array\n"); diff --git a/drivers/net/ethernet/broadcom/cnic.c b/drivers/net/ethernet/broadcom/cnic.c index 8bc126a156e8..30273a7717e2 100644 --- a/drivers/net/ethernet/broadcom/cnic.c +++ b/drivers/net/ethernet/broadcom/cnic.c @@ -660,7 +660,7 @@ static int cnic_init_id_tbl(struct cnic_id_tbl *id_tbl, u32 size, u32 start_id, id_tbl->max = size; id_tbl->next = next; spin_lock_init(&id_tbl->lock); - id_tbl->table = kzalloc(DIV_ROUND_UP(size, 32) * 4, GFP_KERNEL); + id_tbl->table = kcalloc(DIV_ROUND_UP(size, 32), 4, GFP_KERNEL); if (!id_tbl->table) return -ENOMEM; @@ -1255,13 +1255,13 @@ static int cnic_alloc_bnx2x_resc(struct cnic_dev *dev) cp->fcoe_init_cid = 0x10; } - cp->iscsi_tbl = kzalloc(sizeof(struct cnic_iscsi) * MAX_ISCSI_TBL_SZ, + cp->iscsi_tbl = kcalloc(MAX_ISCSI_TBL_SZ, sizeof(struct cnic_iscsi), GFP_KERNEL); if (!cp->iscsi_tbl) goto error; - cp->ctx_tbl = kzalloc(sizeof(struct cnic_context) * - cp->max_cid_space, GFP_KERNEL); + cp->ctx_tbl = kcalloc(cp->max_cid_space, sizeof(struct cnic_context), + GFP_KERNEL); if (!cp->ctx_tbl) goto error; @@ -4100,7 +4100,7 @@ static int cnic_cm_alloc_mem(struct cnic_dev *dev) struct cnic_local *cp = dev->cnic_priv; u32 port_id; - cp->csk_tbl = kzalloc(sizeof(struct cnic_sock) * MAX_CM_SK_TBL_SZ, + cp->csk_tbl = kcalloc(MAX_CM_SK_TBL_SZ, sizeof(struct cnic_sock), GFP_KERNEL); if (!cp->csk_tbl) return -ENOMEM; diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index e40d31b40525..0d10ca2c844b 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -8621,8 +8621,9 @@ static int tg3_mem_tx_acquire(struct tg3 *tp) tnapi++; for (i = 0; i < tp->txq_cnt; i++, tnapi++) { - tnapi->tx_buffers = kzalloc(sizeof(struct tg3_tx_ring_info) * - TG3_TX_RING_SIZE, GFP_KERNEL); + tnapi->tx_buffers = kcalloc(TG3_TX_RING_SIZE, + sizeof(struct tg3_tx_ring_info), + GFP_KERNEL); if (!tnapi->tx_buffers) goto err_out; diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c index 6e13c937d715..ec73b1122b68 100644 --- a/drivers/net/ethernet/brocade/bna/bnad.c +++ b/drivers/net/ethernet/brocade/bna/bnad.c @@ -3143,7 +3143,7 @@ bnad_set_rx_ucast_fltr(struct bnad *bnad) if (uc_count > bna_attr(&bnad->bna)->num_ucmac) goto mode_default; - mac_list = kzalloc(uc_count * ETH_ALEN, GFP_ATOMIC); + mac_list = kcalloc(ETH_ALEN, uc_count, GFP_ATOMIC); if (mac_list == NULL) goto mode_default; @@ -3184,7 +3184,7 @@ bnad_set_rx_mcast_fltr(struct bnad *bnad) if (mc_count > bna_attr(&bnad->bna)->num_mcmac) goto mode_allmulti; - mac_list = kzalloc((mc_count + 1) * ETH_ALEN, GFP_ATOMIC); + mac_list = kcalloc(mc_count + 1, ETH_ALEN, GFP_ATOMIC); if (mac_list == NULL) goto mode_allmulti; diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c index 2bd7c638b178..2c63afff1382 100644 --- a/drivers/net/ethernet/calxeda/xgmac.c +++ b/drivers/net/ethernet/calxeda/xgmac.c @@ -739,7 +739,7 @@ static int xgmac_dma_desc_rings_init(struct net_device *dev) netdev_dbg(priv->dev, "mtu [%d] bfsize [%d]\n", dev->mtu, bfsize); - priv->rx_skbuff = kzalloc(sizeof(struct sk_buff *) * DMA_RX_RING_SZ, + priv->rx_skbuff = kcalloc(DMA_RX_RING_SZ, sizeof(struct sk_buff *), GFP_KERNEL); if (!priv->rx_skbuff) return -ENOMEM; @@ -752,7 +752,7 @@ static int xgmac_dma_desc_rings_init(struct net_device *dev) if (!priv->dma_rx) goto err_dma_rx; - priv->tx_skbuff = kzalloc(sizeof(struct sk_buff *) * DMA_TX_RING_SZ, + priv->tx_skbuff = kcalloc(DMA_TX_RING_SZ, sizeof(struct sk_buff *), GFP_KERNEL); if (!priv->tx_skbuff) goto err_tx_skb; diff --git a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c index 4d2db22e011b..d1e0e651fd94 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c @@ -468,12 +468,12 @@ static int setup_glists(struct lio *lio, int num_iqs) int i, j; lio->glist_lock = - kzalloc(sizeof(*lio->glist_lock) * num_iqs, GFP_KERNEL); + kcalloc(num_iqs, sizeof(*lio->glist_lock), GFP_KERNEL); if (!lio->glist_lock) return -ENOMEM; lio->glist = - kzalloc(sizeof(*lio->glist) * num_iqs, GFP_KERNEL); + kcalloc(num_iqs, sizeof(*lio->glist), GFP_KERNEL); if (!lio->glist) { kfree(lio->glist_lock); lio->glist_lock = NULL; diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c index 7ad1d56d8389..47304dba6a5e 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c @@ -291,8 +291,8 @@ static int nicvf_init_rbdr(struct nicvf *nic, struct rbdr *rbdr, rbdr->is_xdp = true; } rbdr->pgcnt = roundup_pow_of_two(rbdr->pgcnt); - rbdr->pgcache = kzalloc(sizeof(*rbdr->pgcache) * - rbdr->pgcnt, GFP_KERNEL); + rbdr->pgcache = kcalloc(rbdr->pgcnt, sizeof(*rbdr->pgcache), + GFP_KERNEL); if (!rbdr->pgcache) return -ENOMEM; rbdr->pgidx = 0; diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c index ad4c9f17d77c..d6733df3d43f 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c @@ -564,13 +564,13 @@ int t4_uld_mem_alloc(struct adapter *adap) if (!adap->uld) return -ENOMEM; - s->uld_rxq_info = kzalloc(CXGB4_ULD_MAX * + s->uld_rxq_info = kcalloc(CXGB4_ULD_MAX, sizeof(struct sge_uld_rxq_info *), GFP_KERNEL); if (!s->uld_rxq_info) goto err_uld; - s->uld_txq_info = kzalloc(CXGB4_TX_MAX * + s->uld_txq_info = kcalloc(CXGB4_TX_MAX, sizeof(struct sge_uld_txq_info *), GFP_KERNEL); if (!s->uld_txq_info) diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c index 0733745f4be6..e02128a5ef60 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c @@ -2248,7 +2248,7 @@ static int hns_nic_init_ring_data(struct hns_nic_priv *priv) return -EINVAL; } - priv->ring_data = kzalloc(h->q_num * sizeof(*priv->ring_data) * 2, + priv->ring_data = kzalloc(array3_size(h->q_num, sizeof(*priv->ring_data), 2), GFP_KERNEL); if (!priv->ring_data) return -ENOMEM; diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index fff55f0bed30..b9246cba8fea 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -3330,7 +3330,7 @@ static int e1000e_write_mc_addr_list(struct net_device *netdev) return 0; } - mta_list = kzalloc(netdev_mc_count(netdev) * ETH_ALEN, GFP_ATOMIC); + mta_list = kcalloc(netdev_mc_count(netdev), ETH_ALEN, GFP_ATOMIC); if (!mta_list) return -ENOMEM; diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 9c7e75b3b6c7..78fa1ebb3987 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -3151,8 +3151,9 @@ static int igb_sw_init(struct igb_adapter *adapter) /* Assume MSI-X interrupts, will be checked during IRQ allocation */ adapter->flags |= IGB_FLAG_HAS_MSIX; - adapter->mac_table = kzalloc(sizeof(struct igb_mac_addr) * - hw->mac.rar_entry_count, GFP_ATOMIC); + adapter->mac_table = kcalloc(hw->mac.rar_entry_count, + sizeof(struct igb_mac_addr), + GFP_ATOMIC); if (!adapter->mac_table) return -ENOMEM; @@ -4136,7 +4137,7 @@ static int igb_write_mc_addr_list(struct net_device *netdev) return 0; } - mta_list = kzalloc(netdev_mc_count(netdev) * 6, GFP_ATOMIC); + mta_list = kcalloc(netdev_mc_count(netdev), 6, GFP_ATOMIC); if (!mta_list) return -ENOMEM; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 9c3fa0b55551..1eeb1b6fa249 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -6099,8 +6099,8 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter, for (i = 1; i < IXGBE_MAX_LINK_HANDLE; i++) adapter->jump_tables[i] = NULL; - adapter->mac_table = kzalloc(sizeof(struct ixgbe_mac_addr) * - hw->mac.num_rar_entries, + adapter->mac_table = kcalloc(hw->mac.num_rar_entries, + sizeof(struct ixgbe_mac_addr), GFP_ATOMIC); if (!adapter->mac_table) return -ENOMEM; diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c index 62d848df26ef..a171c3264458 100644 --- a/drivers/net/ethernet/jme.c +++ b/drivers/net/ethernet/jme.c @@ -589,8 +589,9 @@ jme_setup_tx_resources(struct jme_adapter *jme) atomic_set(&txring->next_to_clean, 0); atomic_set(&txring->nr_free, jme->tx_ring_size); - txring->bufinf = kzalloc(sizeof(struct jme_buffer_info) * - jme->tx_ring_size, GFP_ATOMIC); + txring->bufinf = kcalloc(jme->tx_ring_size, + sizeof(struct jme_buffer_info), + GFP_ATOMIC); if (unlikely(!(txring->bufinf))) goto err_free_txring; @@ -838,8 +839,9 @@ jme_setup_rx_resources(struct jme_adapter *jme) rxring->next_to_use = 0; atomic_set(&rxring->next_to_clean, 0); - rxring->bufinf = kzalloc(sizeof(struct jme_buffer_info) * - jme->rx_ring_size, GFP_ATOMIC); + rxring->bufinf = kcalloc(jme->rx_ring_size, + sizeof(struct jme_buffer_info), + GFP_ATOMIC); if (unlikely(!(rxring->bufinf))) goto err_free_rxring; diff --git a/drivers/net/ethernet/mellanox/mlx4/alloc.c b/drivers/net/ethernet/mellanox/mlx4/alloc.c index 94f4dc4a77e9..21788d4f9881 100644 --- a/drivers/net/ethernet/mellanox/mlx4/alloc.c +++ b/drivers/net/ethernet/mellanox/mlx4/alloc.c @@ -185,8 +185,8 @@ int mlx4_bitmap_init(struct mlx4_bitmap *bitmap, u32 num, u32 mask, bitmap->avail = num - reserved_top - reserved_bot; bitmap->effective_len = bitmap->avail; spin_lock_init(&bitmap->lock); - bitmap->table = kzalloc(BITS_TO_LONGS(bitmap->max) * - sizeof(long), GFP_KERNEL); + bitmap->table = kcalloc(BITS_TO_LONGS(bitmap->max), sizeof(long), + GFP_KERNEL); if (!bitmap->table) return -ENOMEM; diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c index fba2547eb689..857588e2488d 100644 --- a/drivers/net/ethernet/mellanox/mlx4/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c @@ -2377,20 +2377,23 @@ int mlx4_multi_func_init(struct mlx4_dev *dev) struct mlx4_vf_admin_state *vf_admin; priv->mfunc.master.slave_state = - kzalloc(dev->num_slaves * - sizeof(struct mlx4_slave_state), GFP_KERNEL); + kcalloc(dev->num_slaves, + sizeof(struct mlx4_slave_state), + GFP_KERNEL); if (!priv->mfunc.master.slave_state) goto err_comm; priv->mfunc.master.vf_admin = - kzalloc(dev->num_slaves * - sizeof(struct mlx4_vf_admin_state), GFP_KERNEL); + kcalloc(dev->num_slaves, + sizeof(struct mlx4_vf_admin_state), + GFP_KERNEL); if (!priv->mfunc.master.vf_admin) goto err_comm_admin; priv->mfunc.master.vf_oper = - kzalloc(dev->num_slaves * - sizeof(struct mlx4_vf_oper_state), GFP_KERNEL); + kcalloc(dev->num_slaves, + sizeof(struct mlx4_vf_oper_state), + GFP_KERNEL); if (!priv->mfunc.master.vf_oper) goto err_comm_oper; diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index 0fb85d71c11b..ab8c8498b7e3 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c @@ -2227,13 +2227,15 @@ static int mlx4_en_copy_priv(struct mlx4_en_priv *dst, if (!dst->tx_ring_num[t]) continue; - dst->tx_ring[t] = kzalloc(sizeof(struct mlx4_en_tx_ring *) * - MAX_TX_RINGS, GFP_KERNEL); + dst->tx_ring[t] = kcalloc(MAX_TX_RINGS, + sizeof(struct mlx4_en_tx_ring *), + GFP_KERNEL); if (!dst->tx_ring[t]) goto err_free_tx; - dst->tx_cq[t] = kzalloc(sizeof(struct mlx4_en_cq *) * - MAX_TX_RINGS, GFP_KERNEL); + dst->tx_cq[t] = kcalloc(MAX_TX_RINGS, + sizeof(struct mlx4_en_cq *), + GFP_KERNEL); if (!dst->tx_cq[t]) { kfree(dst->tx_ring[t]); goto err_free_tx; @@ -3314,14 +3316,16 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, if (!priv->tx_ring_num[t]) continue; - priv->tx_ring[t] = kzalloc(sizeof(struct mlx4_en_tx_ring *) * - MAX_TX_RINGS, GFP_KERNEL); + priv->tx_ring[t] = kcalloc(MAX_TX_RINGS, + sizeof(struct mlx4_en_tx_ring *), + GFP_KERNEL); if (!priv->tx_ring[t]) { err = -ENOMEM; goto out; } - priv->tx_cq[t] = kzalloc(sizeof(struct mlx4_en_cq *) * - MAX_TX_RINGS, GFP_KERNEL); + priv->tx_cq[t] = kcalloc(MAX_TX_RINGS, + sizeof(struct mlx4_en_cq *), + GFP_KERNEL); if (!priv->tx_cq[t]) { err = -ENOMEM; goto out; diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index c6660b61e836..79d41834fcbe 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -3058,7 +3058,8 @@ static int mlx4_init_steering(struct mlx4_dev *dev) int num_entries = dev->caps.num_ports; int i, j; - priv->steer = kzalloc(sizeof(struct mlx4_steer) * num_entries, GFP_KERNEL); + priv->steer = kcalloc(num_entries, sizeof(struct mlx4_steer), + GFP_KERNEL); if (!priv->steer) return -ENOMEM; @@ -3179,7 +3180,7 @@ static u64 mlx4_enable_sriov(struct mlx4_dev *dev, struct pci_dev *pdev, } } - dev->dev_vfs = kzalloc(total_vfs * sizeof(*dev->dev_vfs), GFP_KERNEL); + dev->dev_vfs = kcalloc(total_vfs, sizeof(*dev->dev_vfs), GFP_KERNEL); if (NULL == dev->dev_vfs) { mlx4_err(dev, "Failed to allocate memory for VFs\n"); goto disable_sriov; diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index 9a0076f36a81..4638998e4f25 100644 --- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c @@ -505,7 +505,7 @@ int mlx4_init_resource_tracker(struct mlx4_dev *dev) int t; priv->mfunc.master.res_tracker.slave_list = - kzalloc(dev->num_slaves * sizeof(struct slave_list), + kcalloc(dev->num_slaves, sizeof(struct slave_list), GFP_KERNEL); if (!priv->mfunc.master.res_tracker.slave_list) return -ENOMEM; @@ -532,14 +532,13 @@ int mlx4_init_resource_tracker(struct mlx4_dev *dev) sizeof(int), GFP_KERNEL); if (i == RES_MAC || i == RES_VLAN) - res_alloc->allocated = kzalloc(MLX4_MAX_PORTS * - (dev->persist->num_vfs - + 1) * - sizeof(int), GFP_KERNEL); + res_alloc->allocated = kcalloc(MLX4_MAX_PORTS * (dev->persist->num_vfs + 1), + sizeof(int), + GFP_KERNEL); else - res_alloc->allocated = kzalloc((dev->persist-> - num_vfs + 1) * - sizeof(int), GFP_KERNEL); + res_alloc->allocated = kcalloc(dev->persist->num_vfs + 1, + sizeof(int), + GFP_KERNEL); /* Reduce the sink counter */ if (i == RES_COUNTER) res_alloc->res_free = dev->caps.max_counters - 1; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_clock.c b/drivers/net/ethernet/mellanox/mlx5/core/en_clock.c index 27040009d87a..d54bf2264dd2 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_clock.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_clock.c @@ -456,8 +456,9 @@ static int mlx5e_init_pin_config(struct mlx5e_tstamp *tstamp) int i; tstamp->ptp_info.pin_config = - kzalloc(sizeof(*tstamp->ptp_info.pin_config) * - tstamp->ptp_info.n_pins, GFP_KERNEL); + kcalloc(tstamp->ptp_info.n_pins, + sizeof(*tstamp->ptp_info.pin_config), + GFP_KERNEL); if (!tstamp->ptp_info.pin_config) return -ENOMEM; tstamp->ptp_info.enable = mlx5e_ptp_enable; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index 387758fc6be4..e070ba0a15ce 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -1634,7 +1634,7 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev) } esw->offloads.vport_reps = - kzalloc(total_vports * sizeof(struct mlx5_eswitch_rep), + kcalloc(total_vports, sizeof(struct mlx5_eswitch_rep), GFP_KERNEL); if (!esw->offloads.vport_reps) { err = -ENOMEM; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.c b/drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.c index 35d0e33381ca..375e1dd72fb3 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.c @@ -290,7 +290,7 @@ int mlx5_fpga_ipsec_counters_read(struct mlx5_core_dev *mdev, u64 *counters, count = mlx5_fpga_ipsec_counters_count(mdev); - data = kzalloc(sizeof(*data) * count * 2, GFP_KERNEL); + data = kzalloc(array3_size(sizeof(*data), count, 2), GFP_KERNEL); if (!data) { ret = -ENOMEM; goto out; diff --git a/drivers/net/ethernet/micrel/ksz884x.c b/drivers/net/ethernet/micrel/ksz884x.c index e798fbe08600..83160c79a6ab 100644 --- a/drivers/net/ethernet/micrel/ksz884x.c +++ b/drivers/net/ethernet/micrel/ksz884x.c @@ -4372,7 +4372,7 @@ static void ksz_update_timer(struct ksz_timer_info *info) */ static int ksz_alloc_soft_desc(struct ksz_desc_info *desc_info, int transmit) { - desc_info->ring = kzalloc(sizeof(struct ksz_desc) * desc_info->alloc, + desc_info->ring = kcalloc(desc_info->alloc, sizeof(struct ksz_desc), GFP_KERNEL); if (!desc_info->ring) return 1; diff --git a/drivers/net/ethernet/neterion/vxge/vxge-config.c b/drivers/net/ethernet/neterion/vxge/vxge-config.c index 6f57b0b7d57a..c9d02e6165c8 100644 --- a/drivers/net/ethernet/neterion/vxge/vxge-config.c +++ b/drivers/net/ethernet/neterion/vxge/vxge-config.c @@ -2220,22 +2220,22 @@ __vxge_hw_channel_allocate(struct __vxge_hw_vpath_handle *vph, channel->length = length; channel->vp_id = vp_id; - channel->work_arr = kzalloc(sizeof(void *)*length, GFP_KERNEL); + channel->work_arr = kcalloc(length, sizeof(void *), GFP_KERNEL); if (channel->work_arr == NULL) goto exit1; - channel->free_arr = kzalloc(sizeof(void *)*length, GFP_KERNEL); + channel->free_arr = kcalloc(length, sizeof(void *), GFP_KERNEL); if (channel->free_arr == NULL) goto exit1; channel->free_ptr = length; - channel->reserve_arr = kzalloc(sizeof(void *)*length, GFP_KERNEL); + channel->reserve_arr = kcalloc(length, sizeof(void *), GFP_KERNEL); if (channel->reserve_arr == NULL) goto exit1; channel->reserve_ptr = length; channel->reserve_top = 0; - channel->orig_arr = kzalloc(sizeof(void *)*length, GFP_KERNEL); + channel->orig_arr = kcalloc(length, sizeof(void *), GFP_KERNEL); if (channel->orig_arr == NULL) goto exit1; diff --git a/drivers/net/ethernet/neterion/vxge/vxge-main.c b/drivers/net/ethernet/neterion/vxge/vxge-main.c index 50ea69d88480..54d6a42a6140 100644 --- a/drivers/net/ethernet/neterion/vxge/vxge-main.c +++ b/drivers/net/ethernet/neterion/vxge/vxge-main.c @@ -3437,8 +3437,8 @@ static int vxge_device_register(struct __vxge_hw_device *hldev, vxge_initialize_ethtool_ops(ndev); /* Allocate memory for vpath */ - vdev->vpaths = kzalloc((sizeof(struct vxge_vpath)) * - no_of_vpath, GFP_KERNEL); + vdev->vpaths = kcalloc(no_of_vpath, sizeof(struct vxge_vpath), + GFP_KERNEL); if (!vdev->vpaths) { vxge_debug_init(VXGE_ERR, "%s: vpath memory allocation failed", diff --git a/drivers/net/ethernet/pasemi/pasemi_mac.c b/drivers/net/ethernet/pasemi/pasemi_mac.c index c9b4ac9d3330..728d4169d81e 100644 --- a/drivers/net/ethernet/pasemi/pasemi_mac.c +++ b/drivers/net/ethernet/pasemi/pasemi_mac.c @@ -392,8 +392,9 @@ static int pasemi_mac_setup_rx_resources(const struct net_device *dev) spin_lock_init(&ring->lock); ring->size = RX_RING_SIZE; - ring->ring_info = kzalloc(sizeof(struct pasemi_mac_buffer) * - RX_RING_SIZE, GFP_KERNEL); + ring->ring_info = kcalloc(RX_RING_SIZE, + sizeof(struct pasemi_mac_buffer), + GFP_KERNEL); if (!ring->ring_info) goto out_ring_info; @@ -475,8 +476,9 @@ pasemi_mac_setup_tx_resources(const struct net_device *dev) spin_lock_init(&ring->lock); ring->size = TX_RING_SIZE; - ring->ring_info = kzalloc(sizeof(struct pasemi_mac_buffer) * - TX_RING_SIZE, GFP_KERNEL); + ring->ring_info = kcalloc(TX_RING_SIZE, + sizeof(struct pasemi_mac_buffer), + GFP_KERNEL); if (!ring->ring_info) goto out_ring_info; diff --git a/drivers/net/ethernet/qlogic/qed/qed_debug.c b/drivers/net/ethernet/qlogic/qed/qed_debug.c index 99f32202a85c..5f0f1af135b4 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_debug.c +++ b/drivers/net/ethernet/qlogic/qed/qed_debug.c @@ -6468,7 +6468,8 @@ static enum dbg_status qed_mcp_trace_alloc_meta(struct qed_hwfn *p_hwfn, /* Read no. of modules and allocate memory for their pointers */ meta->modules_num = qed_read_byte_from_buf(meta_buf_bytes, &offset); - meta->modules = kzalloc(meta->modules_num * sizeof(char *), GFP_KERNEL); + meta->modules = kcalloc(meta->modules_num, sizeof(char *), + GFP_KERNEL); if (!meta->modules) return DBG_STATUS_VIRT_MEM_ALLOC_FAILED; @@ -6496,7 +6497,7 @@ static enum dbg_status qed_mcp_trace_alloc_meta(struct qed_hwfn *p_hwfn, /* Read number of formats and allocate memory for all formats */ meta->formats_num = qed_read_dword_from_buf(meta_buf_bytes, &offset); - meta->formats = kzalloc(meta->formats_num * + meta->formats = kcalloc(meta->formats_num, sizeof(struct mcp_trace_format), GFP_KERNEL); if (!meta->formats) diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c b/drivers/net/ethernet/qlogic/qed/qed_dev.c index 6024b832b4d9..8812fb5ad07f 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_dev.c +++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c @@ -831,26 +831,26 @@ static int qed_alloc_qm_data(struct qed_hwfn *p_hwfn) if (rc) goto alloc_err; - qm_info->qm_pq_params = kzalloc(sizeof(*qm_info->qm_pq_params) * - qed_init_qm_get_num_pqs(p_hwfn), + qm_info->qm_pq_params = kcalloc(qed_init_qm_get_num_pqs(p_hwfn), + sizeof(*qm_info->qm_pq_params), GFP_KERNEL); if (!qm_info->qm_pq_params) goto alloc_err; - qm_info->qm_vport_params = kzalloc(sizeof(*qm_info->qm_vport_params) * - qed_init_qm_get_num_vports(p_hwfn), + qm_info->qm_vport_params = kcalloc(qed_init_qm_get_num_vports(p_hwfn), + sizeof(*qm_info->qm_vport_params), GFP_KERNEL); if (!qm_info->qm_vport_params) goto alloc_err; - qm_info->qm_port_params = kzalloc(sizeof(*qm_info->qm_port_params) * - p_hwfn->cdev->num_ports_in_engine, + qm_info->qm_port_params = kcalloc(p_hwfn->cdev->num_ports_in_engine, + sizeof(*qm_info->qm_port_params), GFP_KERNEL); if (!qm_info->qm_port_params) goto alloc_err; - qm_info->wfq_data = kzalloc(sizeof(*qm_info->wfq_data) * - qed_init_qm_get_num_vports(p_hwfn), + qm_info->wfq_data = kcalloc(qed_init_qm_get_num_vports(p_hwfn), + sizeof(*qm_info->wfq_data), GFP_KERNEL); if (!qm_info->wfq_data) goto alloc_err; diff --git a/drivers/net/ethernet/qlogic/qed/qed_init_ops.c b/drivers/net/ethernet/qlogic/qed/qed_init_ops.c index e3f368882f46..bc2373b2aab8 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_init_ops.c +++ b/drivers/net/ethernet/qlogic/qed/qed_init_ops.c @@ -149,12 +149,12 @@ int qed_init_alloc(struct qed_hwfn *p_hwfn) if (IS_VF(p_hwfn->cdev)) return 0; - rt_data->b_valid = kzalloc(sizeof(bool) * RUNTIME_ARRAY_SIZE, + rt_data->b_valid = kcalloc(RUNTIME_ARRAY_SIZE, sizeof(bool), GFP_KERNEL); if (!rt_data->b_valid) return -ENOMEM; - rt_data->init_val = kzalloc(sizeof(u32) * RUNTIME_ARRAY_SIZE, + rt_data->init_val = kcalloc(RUNTIME_ARRAY_SIZE, sizeof(u32), GFP_KERNEL); if (!rt_data->init_val) { kfree(rt_data->b_valid); diff --git a/drivers/net/ethernet/qlogic/qed/qed_l2.c b/drivers/net/ethernet/qlogic/qed/qed_l2.c index 5d7adedac68d..5e5ca14bb00f 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_l2.c +++ b/drivers/net/ethernet/qlogic/qed/qed_l2.c @@ -98,7 +98,7 @@ int qed_l2_alloc(struct qed_hwfn *p_hwfn) p_l2_info->queues = max_t(u8, rx, tx); } - pp_qids = kzalloc(sizeof(unsigned long *) * p_l2_info->queues, + pp_qids = kcalloc(p_l2_info->queues, sizeof(unsigned long *), GFP_KERNEL); if (!pp_qids) return -ENOMEM; diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index 1b5f7d57b6f8..8c6724063231 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c @@ -1025,15 +1025,17 @@ int qlcnic_init_pci_info(struct qlcnic_adapter *adapter) act_pci_func = ahw->total_nic_func; - adapter->npars = kzalloc(sizeof(struct qlcnic_npar_info) * - act_pci_func, GFP_KERNEL); + adapter->npars = kcalloc(act_pci_func, + sizeof(struct qlcnic_npar_info), + GFP_KERNEL); if (!adapter->npars) { ret = -ENOMEM; goto err_pci_info; } - adapter->eswitch = kzalloc(sizeof(struct qlcnic_eswitch) * - QLCNIC_NIU_MAX_XG_PORTS, GFP_KERNEL); + adapter->eswitch = kcalloc(QLCNIC_NIU_MAX_XG_PORTS, + sizeof(struct qlcnic_eswitch), + GFP_KERNEL); if (!adapter->eswitch) { ret = -ENOMEM; goto err_npars; diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c index c58180f40844..0c744b9c6e0a 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c @@ -157,8 +157,8 @@ int qlcnic_sriov_init(struct qlcnic_adapter *adapter, int num_vfs) adapter->ahw->sriov = sriov; sriov->num_vfs = num_vfs; bc = &sriov->bc; - sriov->vf_info = kzalloc(sizeof(struct qlcnic_vf_info) * - num_vfs, GFP_KERNEL); + sriov->vf_info = kcalloc(num_vfs, sizeof(struct qlcnic_vf_info), + GFP_KERNEL); if (!sriov->vf_info) { err = -ENOMEM; goto qlcnic_free_sriov; @@ -450,7 +450,7 @@ static int qlcnic_sriov_set_guest_vlan_mode(struct qlcnic_adapter *adapter, return 0; num_vlans = sriov->num_allowed_vlans; - sriov->allowed_vlans = kzalloc(sizeof(u16) * num_vlans, GFP_KERNEL); + sriov->allowed_vlans = kcalloc(num_vlans, sizeof(u16), GFP_KERNEL); if (!sriov->allowed_vlans) return -ENOMEM; @@ -706,7 +706,7 @@ static inline int qlcnic_sriov_alloc_bc_trans(struct qlcnic_bc_trans **trans) static inline int qlcnic_sriov_alloc_bc_msg(struct qlcnic_bc_hdr **hdr, u32 size) { - *hdr = kzalloc(sizeof(struct qlcnic_bc_hdr) * size, GFP_ATOMIC); + *hdr = kcalloc(size, sizeof(struct qlcnic_bc_hdr), GFP_ATOMIC); if (!*hdr) return -ENOMEM; diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c b/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c index eed18f88bdff..302079e22b06 100644 --- a/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c +++ b/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c @@ -2320,8 +2320,9 @@ static struct net_device *gelic_wl_alloc(struct gelic_card *card) pr_debug("%s: wl=%p port=%p\n", __func__, wl, port); /* allocate scan list */ - wl->networks = kzalloc(sizeof(struct gelic_wl_scan_info) * - GELIC_WL_BSS_MAX_ENT, GFP_KERNEL); + wl->networks = kcalloc(GELIC_WL_BSS_MAX_ENT, + sizeof(struct gelic_wl_scan_info), + GFP_KERNEL); if (!wl->networks) goto fail_bss; diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c index 5752280fdb40..206270f7d47b 100644 --- a/drivers/net/phy/dp83640.c +++ b/drivers/net/phy/dp83640.c @@ -1102,8 +1102,9 @@ static struct dp83640_clock *dp83640_clock_get_bus(struct mii_bus *bus) if (!clock) goto out; - clock->caps.pin_config = kzalloc(sizeof(struct ptp_pin_desc) * - DP83640_N_PINS, GFP_KERNEL); + clock->caps.pin_config = kcalloc(DP83640_N_PINS, + sizeof(struct ptp_pin_desc), + GFP_KERNEL); if (!clock->caps.pin_config) { kfree(clock); clock = NULL; diff --git a/drivers/net/slip/slip.c b/drivers/net/slip/slip.c index d7882b548b79..6a49a9979905 100644 --- a/drivers/net/slip/slip.c +++ b/drivers/net/slip/slip.c @@ -1324,7 +1324,7 @@ static int __init slip_init(void) printk(KERN_INFO "SLIP linefill/keepalive option.\n"); #endif - slip_devs = kzalloc(sizeof(struct net_device *)*slip_maxdev, + slip_devs = kcalloc(slip_maxdev, sizeof(struct net_device *), GFP_KERNEL); if (!slip_devs) return -ENOMEM; diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index 636411f46220..2e43aa7d9b3f 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -269,7 +269,7 @@ static int __team_options_register(struct team *team, struct team_option **dst_opts; int err; - dst_opts = kzalloc(sizeof(struct team_option *) * option_count, + dst_opts = kcalloc(option_count, sizeof(struct team_option *), GFP_KERNEL); if (!dst_opts) return -ENOMEM; diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c index bc6bcea67bff..4f29010e1aef 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -1676,7 +1676,7 @@ static int smsc95xx_suspend(struct usb_interface *intf, pm_message_t message) } if (pdata->wolopts & (WAKE_BCAST | WAKE_MCAST | WAKE_ARP | WAKE_UCAST)) { - u32 *filter_mask = kzalloc(sizeof(u32) * 32, GFP_KERNEL); + u32 *filter_mask = kcalloc(32, sizeof(u32), GFP_KERNEL); u32 command[2]; u32 offset[2]; u32 crc[4]; diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 0c7a96334d82..bc40745bf772 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -2279,7 +2279,7 @@ static int virtnet_find_vqs(struct virtnet_info *vi) virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ); /* Allocate space for find_vqs parameters */ - vqs = kzalloc(total_vqs * sizeof(*vqs), GFP_KERNEL); + vqs = kcalloc(total_vqs, sizeof(*vqs), GFP_KERNEL); if (!vqs) goto err_vq; callbacks = kmalloc_array(total_vqs, sizeof(*callbacks), GFP_KERNEL); @@ -2289,7 +2289,7 @@ static int virtnet_find_vqs(struct virtnet_info *vi) if (!names) goto err_names; if (!vi->big_packets || vi->mergeable_rx_bufs) { - ctx = kzalloc(total_vqs * sizeof(*ctx), GFP_KERNEL); + ctx = kcalloc(total_vqs, sizeof(*ctx), GFP_KERNEL); if (!ctx) goto err_ctx; } else { @@ -2357,10 +2357,10 @@ static int virtnet_alloc_queues(struct virtnet_info *vi) vi->ctrl = kzalloc(sizeof(*vi->ctrl), GFP_KERNEL); if (!vi->ctrl) goto err_ctrl; - vi->sq = kzalloc(sizeof(*vi->sq) * vi->max_queue_pairs, GFP_KERNEL); + vi->sq = kcalloc(vi->max_queue_pairs, sizeof(*vi->sq), GFP_KERNEL); if (!vi->sq) goto err_sq; - vi->rq = kzalloc(sizeof(*vi->rq) * vi->max_queue_pairs, GFP_KERNEL); + vi->rq = kcalloc(vi->max_queue_pairs, sizeof(*vi->rq), GFP_KERNEL); if (!vi->rq) goto err_rq; diff --git a/drivers/net/wan/fsl_ucc_hdlc.c b/drivers/net/wan/fsl_ucc_hdlc.c index 6a26cef62193..668c6704af51 100644 --- a/drivers/net/wan/fsl_ucc_hdlc.c +++ b/drivers/net/wan/fsl_ucc_hdlc.c @@ -198,12 +198,14 @@ static int uhdlc_init(struct ucc_hdlc_private *priv) goto free_tx_bd; } - priv->rx_skbuff = kzalloc(priv->rx_ring_size * sizeof(*priv->rx_skbuff), + priv->rx_skbuff = kcalloc(priv->rx_ring_size, + sizeof(*priv->rx_skbuff), GFP_KERNEL); if (!priv->rx_skbuff) goto free_ucc_pram; - priv->tx_skbuff = kzalloc(priv->tx_ring_size * sizeof(*priv->tx_skbuff), + priv->tx_skbuff = kcalloc(priv->tx_ring_size, + sizeof(*priv->tx_skbuff), GFP_KERNEL); if (!priv->tx_skbuff) goto free_rx_skbuff; diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 717110481b88..0e8ef8262f5f 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -583,7 +583,7 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt) } htt->rx_ring.netbufs_ring = - kzalloc(htt->rx_ring.size * sizeof(struct sk_buff *), + kcalloc(htt->rx_ring.size, sizeof(struct sk_buff *), GFP_KERNEL); if (!htt->rx_ring.netbufs_ring) goto err_netbuf; diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index c4dfc61fc164..39eba6d6db3d 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -155,7 +155,7 @@ ath10k_wmi_tlv_parse_alloc(struct ath10k *ar, const void *ptr, const void **tb; int ret; - tb = kzalloc(sizeof(*tb) * WMI_TLV_TAG_MAX, gfp); + tb = kcalloc(WMI_TLV_TAG_MAX, sizeof(*tb), gfp); if (!tb) return ERR_PTR(-ENOMEM); diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 37deb9bae364..83e95f0a9c2a 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -1041,7 +1041,7 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, n_channels = request->n_channels; - channels = kzalloc(n_channels * sizeof(u16), GFP_KERNEL); + channels = kcalloc(n_channels, sizeof(u16), GFP_KERNEL); if (channels == NULL) { ath6kl_warn("failed to set scan channels, scan all channels"); n_channels = 0; diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c index 80312b2fddb1..88523c572f0a 100644 --- a/drivers/net/wireless/ath/carl9170/main.c +++ b/drivers/net/wireless/ath/carl9170/main.c @@ -1945,7 +1945,7 @@ static int carl9170_parse_eeprom(struct ar9170 *ar) if (!bands) return -EINVAL; - ar->survey = kzalloc(sizeof(struct survey_info) * chans, GFP_KERNEL); + ar->survey = kcalloc(chans, sizeof(struct survey_info), GFP_KERNEL); if (!ar->survey) return -ENOMEM; ar->num_channels = chans; @@ -1975,8 +1975,9 @@ int carl9170_register(struct ar9170 *ar) if (WARN_ON(ar->mem_bitmap)) return -EINVAL; - ar->mem_bitmap = kzalloc(roundup(ar->fw.mem_blocks, BITS_PER_LONG) * - sizeof(unsigned long), GFP_KERNEL); + ar->mem_bitmap = kcalloc(roundup(ar->fw.mem_blocks, BITS_PER_LONG), + sizeof(unsigned long), + GFP_KERNEL); if (!ar->mem_bitmap) return -ENOMEM; diff --git a/drivers/net/wireless/broadcom/b43/phy_n.c b/drivers/net/wireless/broadcom/b43/phy_n.c index a5557d70689f..b5d3c7fe241c 100644 --- a/drivers/net/wireless/broadcom/b43/phy_n.c +++ b/drivers/net/wireless/broadcom/b43/phy_n.c @@ -1518,7 +1518,7 @@ static int b43_nphy_load_samples(struct b43_wldev *dev, u16 i; u32 *data; - data = kzalloc(len * sizeof(u32), GFP_KERNEL); + data = kcalloc(len, sizeof(u32), GFP_KERNEL); if (!data) { b43err(dev->wl, "allocation for samples loading failed\n"); return -ENOMEM; diff --git a/drivers/net/wireless/broadcom/b43legacy/main.c b/drivers/net/wireless/broadcom/b43legacy/main.c index 6f123a52ae2d..ef1f1b5d63b1 100644 --- a/drivers/net/wireless/broadcom/b43legacy/main.c +++ b/drivers/net/wireless/broadcom/b43legacy/main.c @@ -3301,8 +3301,8 @@ static int b43legacy_wireless_core_init(struct b43legacy_wldev *dev) if ((phy->type == B43legacy_PHYTYPE_B) || (phy->type == B43legacy_PHYTYPE_G)) { - phy->_lo_pairs = kzalloc(sizeof(struct b43legacy_lopair) - * B43legacy_LO_COUNT, + phy->_lo_pairs = kcalloc(B43legacy_LO_COUNT, + sizeof(struct b43legacy_lopair), GFP_KERNEL); if (!phy->_lo_pairs) return -ENOMEM; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c index 65e16e3646ec..e5705c40aa49 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c @@ -1478,8 +1478,9 @@ int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr) (struct brcmf_commonring **)if_msgbuf->commonrings; msgbuf->flowrings = (struct brcmf_commonring **)if_msgbuf->flowrings; msgbuf->max_flowrings = if_msgbuf->max_flowrings; - msgbuf->flowring_dma_handle = kzalloc(msgbuf->max_flowrings * - sizeof(*msgbuf->flowring_dma_handle), GFP_KERNEL); + msgbuf->flowring_dma_handle = kcalloc(msgbuf->max_flowrings, + sizeof(*msgbuf->flowring_dma_handle), + GFP_KERNEL); if (!msgbuf->flowring_dma_handle) goto fail; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c index 4a883f4bbf88..d70932b8b94a 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c @@ -1063,7 +1063,7 @@ static s32 brcmf_p2p_act_frm_search(struct brcmf_p2p_info *p2p, u16 channel) channel_cnt = AF_PEER_SEARCH_CNT; else channel_cnt = SOCIAL_CHAN_CNT; - default_chan_list = kzalloc(channel_cnt * sizeof(*default_chan_list), + default_chan_list = kcalloc(channel_cnt, sizeof(*default_chan_list), GFP_KERNEL); if (default_chan_list == NULL) { brcmf_err("channel list allocation failed\n"); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.c index 0a14942b8216..7d4e8f589fdc 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.c @@ -507,7 +507,7 @@ brcms_c_attach_malloc(uint unit, uint *err, uint devid) wlc->hw->wlc = wlc; wlc->hw->bandstate[0] = - kzalloc(sizeof(struct brcms_hw_band) * MAXBANDS, GFP_ATOMIC); + kcalloc(MAXBANDS, sizeof(struct brcms_hw_band), GFP_ATOMIC); if (wlc->hw->bandstate[0] == NULL) { *err = 1006; goto fail; @@ -521,7 +521,8 @@ brcms_c_attach_malloc(uint unit, uint *err, uint devid) } wlc->modulecb = - kzalloc(sizeof(struct modulecb) * BRCMS_MAXMODULES, GFP_ATOMIC); + kcalloc(BRCMS_MAXMODULES, sizeof(struct modulecb), + GFP_ATOMIC); if (wlc->modulecb == NULL) { *err = 1009; goto fail; @@ -553,7 +554,7 @@ brcms_c_attach_malloc(uint unit, uint *err, uint devid) } wlc->bandstate[0] = - kzalloc(sizeof(struct brcms_band)*MAXBANDS, GFP_ATOMIC); + kcalloc(MAXBANDS, sizeof(struct brcms_band), GFP_ATOMIC); if (wlc->bandstate[0] == NULL) { *err = 1025; goto fail; diff --git a/drivers/net/wireless/intel/iwlegacy/common.c b/drivers/net/wireless/intel/iwlegacy/common.c index 6e6b124f0d5e..a77ec6ec80ac 100644 --- a/drivers/net/wireless/intel/iwlegacy/common.c +++ b/drivers/net/wireless/intel/iwlegacy/common.c @@ -922,7 +922,7 @@ il_init_channel_map(struct il_priv *il) D_EEPROM("Parsing data for %d channels.\n", il->channel_count); il->channel_info = - kzalloc(sizeof(struct il_channel_info) * il->channel_count, + kcalloc(il->channel_count, sizeof(struct il_channel_info), GFP_KERNEL); if (!il->channel_info) { IL_ERR("Could not allocate channel_info\n"); @@ -3041,9 +3041,9 @@ il_tx_queue_init(struct il_priv *il, u32 txq_id) } txq->meta = - kzalloc(sizeof(struct il_cmd_meta) * actual_slots, GFP_KERNEL); + kcalloc(actual_slots, sizeof(struct il_cmd_meta), GFP_KERNEL); txq->cmd = - kzalloc(sizeof(struct il_device_cmd *) * actual_slots, GFP_KERNEL); + kcalloc(actual_slots, sizeof(struct il_device_cmd *), GFP_KERNEL); if (!txq->meta || !txq->cmd) goto out_free_arrays; @@ -3455,7 +3455,7 @@ il_init_geos(struct il_priv *il) } channels = - kzalloc(sizeof(struct ieee80211_channel) * il->channel_count, + kcalloc(il->channel_count, sizeof(struct ieee80211_channel), GFP_KERNEL); if (!channels) return -ENOMEM; @@ -4654,8 +4654,9 @@ il_alloc_txq_mem(struct il_priv *il) { if (!il->txq) il->txq = - kzalloc(sizeof(struct il_tx_queue) * - il->cfg->num_of_queues, GFP_KERNEL); + kcalloc(il->cfg->num_of_queues, + sizeof(struct il_tx_queue), + GFP_KERNEL); if (!il->txq) { IL_ERR("Not enough memory for txq\n"); return -ENOMEM; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c index e4fd476e9ccb..c36096875c79 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c @@ -501,7 +501,7 @@ iwl_mvm_config_sched_scan_profiles(struct iwl_mvm *mvm, else blacklist_len = IWL_SCAN_MAX_BLACKLIST_LEN; - blacklist = kzalloc(sizeof(*blacklist) * blacklist_len, GFP_KERNEL); + blacklist = kcalloc(blacklist_len, sizeof(*blacklist), GFP_KERNEL); if (!blacklist) return -ENOMEM; diff --git a/drivers/net/wireless/intersil/p54/eeprom.c b/drivers/net/wireless/intersil/p54/eeprom.c index d4c73d39336f..de2ef95c386c 100644 --- a/drivers/net/wireless/intersil/p54/eeprom.c +++ b/drivers/net/wireless/intersil/p54/eeprom.c @@ -161,8 +161,9 @@ static int p54_generate_band(struct ieee80211_hw *dev, if (!tmp) goto err_out; - tmp->channels = kzalloc(sizeof(struct ieee80211_channel) * - list->band_channel_num[band], GFP_KERNEL); + tmp->channels = kcalloc(list->band_channel_num[band], + sizeof(struct ieee80211_channel), + GFP_KERNEL); if (!tmp->channels) goto err_out; @@ -344,7 +345,7 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev) goto free; } priv->chan_num = max_channel_num; - priv->survey = kzalloc(sizeof(struct survey_info) * max_channel_num, + priv->survey = kcalloc(max_channel_num, sizeof(struct survey_info), GFP_KERNEL); if (!priv->survey) { ret = -ENOMEM; @@ -352,8 +353,9 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev) } list->max_entries = max_channel_num; - list->channels = kzalloc(sizeof(struct p54_channel_entry) * - max_channel_num, GFP_KERNEL); + list->channels = kcalloc(max_channel_num, + sizeof(struct p54_channel_entry), + GFP_KERNEL); if (!list->channels) { ret = -ENOMEM; goto free; diff --git a/drivers/net/wireless/intersil/prism54/oid_mgt.c b/drivers/net/wireless/intersil/prism54/oid_mgt.c index 6528ed5b9b1d..6d57e1cbcc07 100644 --- a/drivers/net/wireless/intersil/prism54/oid_mgt.c +++ b/drivers/net/wireless/intersil/prism54/oid_mgt.c @@ -244,7 +244,7 @@ mgt_init(islpci_private *priv) /* Alloc the cache */ for (i = 0; i < OID_NUM_LAST; i++) { if (isl_oid[i].flags & OID_FLAG_CACHED) { - priv->mib[i] = kzalloc(isl_oid[i].size * + priv->mib[i] = kcalloc(isl_oid[i].size, (isl_oid[i].range + 1), GFP_KERNEL); if (!priv->mib[i]) diff --git a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c index 274dd5a1574a..6da0088b3e3a 100644 --- a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c +++ b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c @@ -399,8 +399,8 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta, new_node->win_size = win_size; - new_node->rx_reorder_ptr = kzalloc(sizeof(void *) * win_size, - GFP_KERNEL); + new_node->rx_reorder_ptr = kcalloc(win_size, sizeof(void *), + GFP_KERNEL); if (!new_node->rx_reorder_ptr) { kfree((u8 *) new_node); mwifiex_dbg(priv->adapter, ERROR, diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c index fd5183c10c4e..065c44636157 100644 --- a/drivers/net/wireless/marvell/mwifiex/sdio.c +++ b/drivers/net/wireless/marvell/mwifiex/sdio.c @@ -2094,15 +2094,16 @@ static int mwifiex_init_sdio(struct mwifiex_adapter *adapter) return -ENOMEM; /* Allocate skb pointer buffers */ - card->mpa_rx.skb_arr = kzalloc((sizeof(void *)) * - card->mp_agg_pkt_limit, GFP_KERNEL); + card->mpa_rx.skb_arr = kcalloc(card->mp_agg_pkt_limit, sizeof(void *), + GFP_KERNEL); if (!card->mpa_rx.skb_arr) { kfree(card->mp_regs); return -ENOMEM; } - card->mpa_rx.len_arr = kzalloc(sizeof(*card->mpa_rx.len_arr) * - card->mp_agg_pkt_limit, GFP_KERNEL); + card->mpa_rx.len_arr = kcalloc(card->mp_agg_pkt_limit, + sizeof(*card->mpa_rx.len_arr), + GFP_KERNEL); if (!card->mpa_rx.len_arr) { kfree(card->mp_regs); kfree(card->mpa_rx.skb_arr); diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c index ed087bbc6f63..620cea6f1b54 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/commands.c +++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c @@ -1022,8 +1022,9 @@ static int qtnf_parse_variable_mac_info(struct qtnf_wmac *mac, /* free earlier iface limits memory */ kfree(mac->macinfo.limits); mac->macinfo.limits = - kzalloc(sizeof(*mac->macinfo.limits) * - record_count, GFP_KERNEL); + kcalloc(record_count, + sizeof(*mac->macinfo.limits), + GFP_KERNEL); if (unlikely(!mac->macinfo.limits)) return -ENOMEM; diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c b/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c index 51520a0e2138..660b26e1c662 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c @@ -396,7 +396,7 @@ static ssize_t rt2x00debug_read_crypto_stats(struct file *file, if (*offset) return 0; - data = kzalloc((1 + CIPHER_MAX) * MAX_LINE_LENGTH, GFP_KERNEL); + data = kcalloc(1 + CIPHER_MAX, MAX_LINE_LENGTH, GFP_KERNEL); if (!data) return -ENOMEM; diff --git a/drivers/net/wireless/realtek/rtlwifi/efuse.c b/drivers/net/wireless/realtek/rtlwifi/efuse.c index ef9acd466cca..c8169c92606c 100644 --- a/drivers/net/wireless/realtek/rtlwifi/efuse.c +++ b/drivers/net/wireless/realtek/rtlwifi/efuse.c @@ -253,15 +253,15 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) } /* allocate memory for efuse_tbl and efuse_word */ - efuse_tbl = kzalloc(rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE] * - sizeof(u8), GFP_ATOMIC); + efuse_tbl = kzalloc(rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE], + GFP_ATOMIC); if (!efuse_tbl) return; - efuse_word = kzalloc(EFUSE_MAX_WORD_UNIT * sizeof(u16 *), GFP_ATOMIC); + efuse_word = kcalloc(EFUSE_MAX_WORD_UNIT, sizeof(u16 *), GFP_ATOMIC); if (!efuse_word) goto out; for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) { - efuse_word[i] = kzalloc(efuse_max_section * sizeof(u16), + efuse_word[i] = kcalloc(efuse_max_section, sizeof(u16), GFP_ATOMIC); if (!efuse_word[i]) goto done; diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.c b/drivers/net/wireless/realtek/rtlwifi/usb.c index 7a050a75bdcb..530efda5b208 100644 --- a/drivers/net/wireless/realtek/rtlwifi/usb.c +++ b/drivers/net/wireless/realtek/rtlwifi/usb.c @@ -1062,7 +1062,7 @@ int rtl_usb_probe(struct usb_interface *intf, } rtlpriv = hw->priv; rtlpriv->hw = hw; - rtlpriv->usb_data = kzalloc(RTL_USB_MAX_RX_COUNT * sizeof(u32), + rtlpriv->usb_data = kcalloc(RTL_USB_MAX_RX_COUNT, sizeof(u32), GFP_KERNEL); if (!rtlpriv->usb_data) { ieee80211_free_hw(hw); diff --git a/drivers/net/wireless/st/cw1200/queue.c b/drivers/net/wireless/st/cw1200/queue.c index 0ba5ef9b3e7b..e70771636b4e 100644 --- a/drivers/net/wireless/st/cw1200/queue.c +++ b/drivers/net/wireless/st/cw1200/queue.c @@ -154,7 +154,7 @@ int cw1200_queue_stats_init(struct cw1200_queue_stats *stats, spin_lock_init(&stats->lock); init_waitqueue_head(&stats->wait_link_id_empty); - stats->link_map_cache = kzalloc(sizeof(int) * map_capacity, + stats->link_map_cache = kcalloc(map_capacity, sizeof(int), GFP_KERNEL); if (!stats->link_map_cache) return -ENOMEM; @@ -181,13 +181,13 @@ int cw1200_queue_init(struct cw1200_queue *queue, spin_lock_init(&queue->lock); setup_timer(&queue->gc, cw1200_queue_gc, (unsigned long)queue); - queue->pool = kzalloc(sizeof(struct cw1200_queue_item) * capacity, - GFP_KERNEL); + queue->pool = kcalloc(capacity, sizeof(struct cw1200_queue_item), + GFP_KERNEL); if (!queue->pool) return -ENOMEM; - queue->link_map_cache = kzalloc(sizeof(int) * stats->map_capacity, - GFP_KERNEL); + queue->link_map_cache = kcalloc(stats->map_capacity, sizeof(int), + GFP_KERNEL); if (!queue->link_map_cache) { kfree(queue->pool); queue->pool = NULL; diff --git a/drivers/net/wireless/st/cw1200/scan.c b/drivers/net/wireless/st/cw1200/scan.c index 446d973cba81..71e9b91cf15b 100644 --- a/drivers/net/wireless/st/cw1200/scan.c +++ b/drivers/net/wireless/st/cw1200/scan.c @@ -232,9 +232,9 @@ void cw1200_scan_work(struct work_struct *work) scan.type = WSM_SCAN_TYPE_BACKGROUND; scan.flags = WSM_SCAN_FLAG_FORCE_BACKGROUND; } - scan.ch = kzalloc( - sizeof(struct wsm_scan_ch) * (it - priv->scan.curr), - GFP_KERNEL); + scan.ch = kcalloc(it - priv->scan.curr, + sizeof(struct wsm_scan_ch), + GFP_KERNEL); if (!scan.ch) { priv->scan.status = -ENOMEM; goto fail; diff --git a/drivers/nvmem/rockchip-efuse.c b/drivers/nvmem/rockchip-efuse.c index 63e3eb55f3ac..805c31b97f20 100644 --- a/drivers/nvmem/rockchip-efuse.c +++ b/drivers/nvmem/rockchip-efuse.c @@ -112,7 +112,8 @@ static int rockchip_rk3399_efuse_read(void *context, unsigned int offset, addr_offset = offset % RK3399_NBYTES; addr_len = addr_end - addr_start; - buf = kzalloc(sizeof(*buf) * addr_len * RK3399_NBYTES, GFP_KERNEL); + buf = kzalloc(array3_size(addr_len, RK3399_NBYTES, sizeof(*buf)), + GFP_KERNEL); if (!buf) { clk_disable_unprepare(efuse->clk); return -ENOMEM; diff --git a/drivers/nvmem/sunxi_sid.c b/drivers/nvmem/sunxi_sid.c index 0d6648be93b8..0472a9311949 100644 --- a/drivers/nvmem/sunxi_sid.c +++ b/drivers/nvmem/sunxi_sid.c @@ -157,7 +157,7 @@ static int sunxi_sid_probe(struct platform_device *pdev) if (IS_ERR(nvmem)) return PTR_ERR(nvmem); - randomness = kzalloc(sizeof(u8) * (size), GFP_KERNEL); + randomness = kzalloc(size, GFP_KERNEL); if (!randomness) { ret = -EINVAL; goto err_unreg_nvmem; diff --git a/drivers/of/platform.c b/drivers/of/platform.c index 5a4963060b85..ad3b0b691598 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -130,7 +130,7 @@ struct platform_device *of_device_alloc(struct device_node *np, /* Populate the resource table */ if (num_irq || num_reg) { - res = kzalloc(sizeof(*res) * (num_irq + num_reg), GFP_KERNEL); + res = kcalloc(num_irq + num_reg, sizeof(*res), GFP_KERNEL); if (!res) { platform_device_put(dev); return NULL; diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index 55c98f119df2..ff3253954773 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -155,7 +155,7 @@ static void __init of_unittest_dynamic(void) } /* Array of 4 properties for the purpose of testing */ - prop = kzalloc(sizeof(*prop) * 4, GFP_KERNEL); + prop = kcalloc(4, sizeof(*prop), GFP_KERNEL); if (!prop) { unittest(0, "kzalloc() failed\n"); return; diff --git a/drivers/pci/host/pci-msm.c b/drivers/pci/host/pci-msm.c index e2c452ceabd2..71c7833ee4d3 100644 --- a/drivers/pci/host/pci-msm.c +++ b/drivers/pci/host/pci-msm.c @@ -3578,8 +3578,9 @@ static int msm_pcie_get_resources(struct msm_pcie_dev_t *dev, cnt = of_property_count_elems_of_size((&pdev->dev)->of_node, "max-clock-frequency-hz", sizeof(u32)); if (cnt > 0) { - clkfreq = kzalloc((MSM_PCIE_MAX_CLK + MSM_PCIE_MAX_PIPE_CLK) * - sizeof(*clkfreq), GFP_KERNEL); + clkfreq = kcalloc(MSM_PCIE_MAX_CLK + MSM_PCIE_MAX_PIPE_CLK, + sizeof(*clkfreq), + GFP_KERNEL); if (!clkfreq) { PCIE_ERR(dev, "PCIe: memory alloc failed for RC%d\n", dev->rc_idx); diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 2a203055b16e..39765cc436c8 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -474,7 +474,7 @@ static int populate_msi_sysfs(struct pci_dev *pdev) return 0; /* Dynamically create the MSI attributes for the PCI device */ - msi_attrs = kzalloc(sizeof(void *) * (num_msi + 1), GFP_KERNEL); + msi_attrs = kcalloc(num_msi + 1, sizeof(void *), GFP_KERNEL); if (!msi_attrs) return -ENOMEM; for_each_pci_msi_entry(entry, pdev) { @@ -501,7 +501,7 @@ static int populate_msi_sysfs(struct pci_dev *pdev) msi_irq_group->name = "msi_irqs"; msi_irq_group->attrs = msi_attrs; - msi_irq_groups = kzalloc(sizeof(void *) * 2, GFP_KERNEL); + msi_irq_groups = kcalloc(2, sizeof(void *), GFP_KERNEL); if (!msi_irq_groups) goto error_irq_group; msi_irq_groups[0] = msi_irq_group; diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index ee7dccab771d..9d9b9e6c680a 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -1094,7 +1094,7 @@ void pci_create_legacy_files(struct pci_bus *b) { int error; - b->legacy_io = kzalloc(sizeof(struct bin_attribute) * 2, + b->legacy_io = kcalloc(2, sizeof(struct bin_attribute), GFP_ATOMIC); if (!b->legacy_io) goto kzalloc_err; diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c index 0f70b4d58f9e..7fa731cd4ecc 100644 --- a/drivers/pcmcia/pd6729.c +++ b/drivers/pcmcia/pd6729.c @@ -628,7 +628,7 @@ static int pd6729_pci_probe(struct pci_dev *dev, char configbyte; struct pd6729_socket *socket; - socket = kzalloc(sizeof(struct pd6729_socket) * MAX_SOCKETS, + socket = kcalloc(MAX_SOCKETS, sizeof(struct pd6729_socket), GFP_KERNEL); if (!socket) { dev_warn(&dev->dev, "failed to kzalloc socket.\n"); diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c index e72bf2502eca..ef60c2cddfc1 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c @@ -775,8 +775,8 @@ static int bcm2835_pctl_dt_node_to_map(struct pinctrl_dev *pctldev, maps_per_pin++; if (num_pulls) maps_per_pin++; - cur_map = maps = kzalloc(num_pins * maps_per_pin * sizeof(*maps), - GFP_KERNEL); + cur_map = maps = kcalloc(num_pins * maps_per_pin, sizeof(*maps), + GFP_KERNEL); if (!maps) return -ENOMEM; diff --git a/drivers/pinctrl/freescale/pinctrl-mxs.c b/drivers/pinctrl/freescale/pinctrl-mxs.c index 6852010a6d70..43a6e900c20f 100644 --- a/drivers/pinctrl/freescale/pinctrl-mxs.c +++ b/drivers/pinctrl/freescale/pinctrl-mxs.c @@ -96,7 +96,7 @@ static int mxs_dt_node_to_map(struct pinctrl_dev *pctldev, if (!purecfg && config) new_num = 2; - new_map = kzalloc(sizeof(*new_map) * new_num, GFP_KERNEL); + new_map = kcalloc(new_num, sizeof(*new_map), GFP_KERNEL); if (!new_map) return -ENOMEM; diff --git a/drivers/pinctrl/pinctrl-lantiq.c b/drivers/pinctrl/pinctrl-lantiq.c index 41dc39c7a7b1..81632af3a86a 100644 --- a/drivers/pinctrl/pinctrl-lantiq.c +++ b/drivers/pinctrl/pinctrl-lantiq.c @@ -158,7 +158,8 @@ static int ltq_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev, for_each_child_of_node(np_config, np) max_maps += ltq_pinctrl_dt_subnode_size(np); - *map = kzalloc(max_maps * sizeof(struct pinctrl_map) * 2, GFP_KERNEL); + *map = kzalloc(array3_size(max_maps, sizeof(struct pinctrl_map), 2), + GFP_KERNEL); if (!*map) return -ENOMEM; tmp = *map; diff --git a/drivers/pinctrl/samsung/pinctrl-exynos5440.c b/drivers/pinctrl/samsung/pinctrl-exynos5440.c index 32a3a9fd65c4..f8073ccd449f 100644 --- a/drivers/pinctrl/samsung/pinctrl-exynos5440.c +++ b/drivers/pinctrl/samsung/pinctrl-exynos5440.c @@ -206,7 +206,7 @@ static int exynos5440_dt_node_to_map(struct pinctrl_dev *pctldev, } /* Allocate memory for pin-map entries */ - map = kzalloc(sizeof(*map) * map_cnt, GFP_KERNEL); + map = kcalloc(map_cnt, sizeof(*map), GFP_KERNEL); if (!map) return -ENOMEM; *nmaps = 0; @@ -227,7 +227,7 @@ static int exynos5440_dt_node_to_map(struct pinctrl_dev *pctldev, goto skip_cfgs; /* Allocate memory for config entries */ - cfg = kzalloc(sizeof(*cfg) * cfg_cnt, GFP_KERNEL); + cfg = kcalloc(cfg_cnt, sizeof(*cfg), GFP_KERNEL); if (!cfg) goto free_gname; diff --git a/drivers/pinctrl/sirf/pinctrl-sirf.c b/drivers/pinctrl/sirf/pinctrl-sirf.c index d3ef05973901..3274ecd464d9 100644 --- a/drivers/pinctrl/sirf/pinctrl-sirf.c +++ b/drivers/pinctrl/sirf/pinctrl-sirf.c @@ -108,7 +108,7 @@ static int sirfsoc_dt_node_to_map(struct pinctrl_dev *pctldev, return -ENODEV; } - *map = kzalloc(sizeof(**map) * count, GFP_KERNEL); + *map = kcalloc(count, sizeof(**map), GFP_KERNEL); if (!*map) return -ENOMEM; diff --git a/drivers/pinctrl/spear/pinctrl-spear.c b/drivers/pinctrl/spear/pinctrl-spear.c index 4db52ba38d8d..3a618db9f58a 100644 --- a/drivers/pinctrl/spear/pinctrl-spear.c +++ b/drivers/pinctrl/spear/pinctrl-spear.c @@ -172,7 +172,7 @@ static int spear_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev, return -ENODEV; } - *map = kzalloc(sizeof(**map) * count, GFP_KERNEL); + *map = kcalloc(count, sizeof(**map), GFP_KERNEL); if (!*map) return -ENOMEM; diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index 6d351827facb..8b3fd553ef55 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c @@ -274,7 +274,7 @@ static unsigned long *sunxi_pctrl_build_pin_config(struct device_node *node, if (!configlen) return NULL; - pinconfig = kzalloc(configlen * sizeof(*pinconfig), GFP_KERNEL); + pinconfig = kcalloc(configlen, sizeof(*pinconfig), GFP_KERNEL); if (!pinconfig) return ERR_PTR(-ENOMEM); diff --git a/drivers/pinctrl/vt8500/pinctrl-wmt.c b/drivers/pinctrl/vt8500/pinctrl-wmt.c index d73956bdc211..c08318a5a91b 100644 --- a/drivers/pinctrl/vt8500/pinctrl-wmt.c +++ b/drivers/pinctrl/vt8500/pinctrl-wmt.c @@ -352,7 +352,7 @@ static int wmt_pctl_dt_node_to_map(struct pinctrl_dev *pctldev, if (num_pulls) maps_per_pin++; - cur_map = maps = kzalloc(num_pins * maps_per_pin * sizeof(*maps), + cur_map = maps = kcalloc(num_pins * maps_per_pin, sizeof(*maps), GFP_KERNEL); if (!maps) return -ENOMEM; diff --git a/drivers/platform/chrome/cros_ec_dev.c b/drivers/platform/chrome/cros_ec_dev.c index cf6c4f0846b8..ab7c91b4bba7 100644 --- a/drivers/platform/chrome/cros_ec_dev.c +++ b/drivers/platform/chrome/cros_ec_dev.c @@ -305,13 +305,14 @@ static void cros_ec_sensors_register(struct cros_ec_dev *ec) resp = (struct ec_response_motion_sense *)msg->data; sensor_num = resp->dump.sensor_count; /* Allocate 2 extra sensors in case lid angle or FIFO are needed */ - sensor_cells = kzalloc(sizeof(struct mfd_cell) * (sensor_num + 2), + sensor_cells = kcalloc(sensor_num + 2, sizeof(struct mfd_cell), GFP_KERNEL); if (sensor_cells == NULL) goto error; - sensor_platforms = kzalloc(sizeof(struct cros_ec_sensor_platform) * - (sensor_num + 1), GFP_KERNEL); + sensor_platforms = kcalloc(sensor_num + 1, + sizeof(struct cros_ec_sensor_platform), + GFP_KERNEL); if (sensor_platforms == NULL) goto error_platforms; diff --git a/drivers/platform/msm/ipa/ipa_rm_peers_list.c b/drivers/platform/msm/ipa/ipa_rm_peers_list.c index 19032278acb4..9fd79c791a62 100644 --- a/drivers/platform/msm/ipa/ipa_rm_peers_list.c +++ b/drivers/platform/msm/ipa/ipa_rm_peers_list.c @@ -63,8 +63,9 @@ int ipa_rm_peers_list_create(int max_peers, } (*peers_list)->max_peers = max_peers; - (*peers_list)->peers = kzalloc((*peers_list)->max_peers * - sizeof(*((*peers_list)->peers)), GFP_ATOMIC); + (*peers_list)->peers = kcalloc((*peers_list)->max_peers, + sizeof(*((*peers_list)->peers)), + GFP_ATOMIC); if (!((*peers_list)->peers)) { IPA_RM_ERR("no mem\n"); result = -ENOMEM; diff --git a/drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth_net.c b/drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth_net.c index 1fa89cbd39e7..376afd0df4cb 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth_net.c +++ b/drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth_net.c @@ -1062,8 +1062,8 @@ static int ipa_eth_net_cb_map_ch_mem(struct ipa_eth_device *eth_dev, return -EEXIST; } - ch_mem->cb_mem = kzalloc(sizeof(*ch_mem->cb_mem) * IPA_SMMU_CB_MAX, - GFP_KERNEL); + ch_mem->cb_mem = kcalloc(IPA_SMMU_CB_MAX, sizeof(*ch_mem->cb_mem), + GFP_KERNEL); if (!ch_mem->cb_mem) { ipa_eth_dev_err(eth_dev, "Failed to alloc CB mem resource"); return -ENOMEM; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c index b008a3342b27..b09b69f20121 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c @@ -828,7 +828,7 @@ static ssize_t ipa3_read_rt_hw(struct file *file, char __user *ubuf, IPADBG("Tring to parse %d H/W routing tables - IP=%d\n", tbls_num, ip); - rules = kzalloc(sizeof(*rules) * IPA_DBG_MAX_RULE_IN_TBL, GFP_KERNEL); + rules = kcalloc(IPA_DBG_MAX_RULE_IN_TBL, sizeof(*rules), GFP_KERNEL); if (!rules) { IPAERR("failed to allocate mem for tbl rules\n"); return -ENOMEM; @@ -1053,7 +1053,7 @@ static ssize_t ipa3_read_flt_hw(struct file *file, char __user *ubuf, IPADBG("Tring to parse %d H/W filtering tables - IP=%d\n", ipa3_ctx->ep_flt_num, ip); - rules = kzalloc(sizeof(*rules) * IPA_DBG_MAX_RULE_IN_TBL, GFP_KERNEL); + rules = kcalloc(IPA_DBG_MAX_RULE_IN_TBL, sizeof(*rules), GFP_KERNEL); if (!rules) return -ENOMEM; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c index 3173fbcd3e68..3833d71220dc 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c @@ -1646,7 +1646,7 @@ int ipa3_tx_dp(enum ipa_client_type dst, struct sk_buff *skb, * 1 desc may be needed for the PACKET_INIT; * 1 desc for each frag */ - desc = kzalloc(sizeof(*desc) * (num_frags + 3), GFP_ATOMIC); + desc = kcalloc(num_frags + 3, sizeof(*desc), GFP_ATOMIC); if (!desc) { IPAERR("failed to alloc desc array\n"); goto fail_gen; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c index 083b3360229a..71e8572259dd 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c @@ -6645,7 +6645,7 @@ int ipa3_tag_process(struct ipa3_desc desc[], } sys = ipa3_ctx->ep[ep_idx].sys; - tag_desc = kzalloc(sizeof(*tag_desc) * IPA_TAG_MAX_DESC, GFP_KERNEL); + tag_desc = kcalloc(IPA_TAG_MAX_DESC, sizeof(*tag_desc), GFP_KERNEL); if (!tag_desc) { IPAERR("failed to allocate memory\n"); return -ENOMEM; diff --git a/drivers/platform/msm/ipa/test/ipa_test_dma.c b/drivers/platform/msm/ipa/test/ipa_test_dma.c index e1c46f45c2ce..207fc00c6191 100644 --- a/drivers/platform/msm/ipa/test/ipa_test_dma.c +++ b/drivers/platform/msm/ipa/test/ipa_test_dma.c @@ -969,8 +969,9 @@ static int ipa_test_dma_parallel_async_memcpy_in_loop(void *priv) return rc; } - udata = kzalloc(IPA_DMA_TEST_ASYNC_PARALLEL_LOOP_NUM * - sizeof(struct ipa_test_dma_async_user_data), GFP_KERNEL); + udata = kcalloc(IPA_DMA_TEST_ASYNC_PARALLEL_LOOP_NUM, + sizeof(struct ipa_test_dma_async_user_data), + GFP_KERNEL); if (!udata) { IPA_UT_ERR("fail allocate user_data array\n"); (void)ipa_dma_disable(); diff --git a/drivers/platform/msm/ipa/test/ipa_test_hw_stats.c b/drivers/platform/msm/ipa/test/ipa_test_hw_stats.c index 97be4138be26..811b9b67d49a 100644 --- a/drivers/platform/msm/ipa/test/ipa_test_hw_stats.c +++ b/drivers/platform/msm/ipa/test/ipa_test_hw_stats.c @@ -146,8 +146,9 @@ static int ipa_test_hw_stats_add_FnR(void *priv) IPA_UT_DBG("no mem\n"); return -ENOMEM; } - rt_rule->rules = (uint64_t)kzalloc(1 * - sizeof(struct ipa_rt_rule_add_v2), GFP_KERNEL); + rt_rule->rules = (uint64_t) kcalloc(1, + sizeof(struct ipa_rt_rule_add_v2), + GFP_KERNEL); if (!rt_rule->rules) { IPA_UT_DBG("no mem\n"); ret = -ENOMEM; @@ -160,8 +161,9 @@ static int ipa_test_hw_stats_add_FnR(void *priv) ret = -ENOMEM; goto free_rt; } - flt_rule->rules = (uint64_t)kzalloc(1 * - sizeof(struct ipa_flt_rule_add_v2), GFP_KERNEL); + flt_rule->rules = (uint64_t) kcalloc(1, + sizeof(struct ipa_flt_rule_add_v2), + GFP_KERNEL); if (!flt_rule->rules) { IPA_UT_DBG("no mem\n"); ret = -ENOMEM; diff --git a/drivers/platform/msm/qcom-geni-se.c b/drivers/platform/msm/qcom-geni-se.c index f60e459aad0c..8d5d37809546 100644 --- a/drivers/platform/msm/qcom-geni-se.c +++ b/drivers/platform/msm/qcom-geni-se.c @@ -1282,8 +1282,9 @@ int geni_se_clk_tbl_get(struct se_geni_rsc *rsc, unsigned long **tbl) goto exit_se_clk_tbl_get; } - geni_se_dev->clk_perf_tbl = kzalloc(sizeof(*geni_se_dev->clk_perf_tbl) * - MAX_CLK_PERF_LEVEL, GFP_KERNEL); + geni_se_dev->clk_perf_tbl = kcalloc(MAX_CLK_PERF_LEVEL, + sizeof(*geni_se_dev->clk_perf_tbl), + GFP_KERNEL); if (!geni_se_dev->clk_perf_tbl) { ret = -ENOMEM; goto exit_se_clk_tbl_get; diff --git a/drivers/platform/x86/alienware-wmi.c b/drivers/platform/x86/alienware-wmi.c index 2c82188f8486..d04a9b80a9c0 100644 --- a/drivers/platform/x86/alienware-wmi.c +++ b/drivers/platform/x86/alienware-wmi.c @@ -441,19 +441,19 @@ static int alienware_zone_init(struct platform_device *dev) * - zone_data num_zones is for the distinct zones */ zone_dev_attrs = - kzalloc(sizeof(struct device_attribute) * (quirks->num_zones + 1), + kcalloc(quirks->num_zones + 1, sizeof(struct device_attribute), GFP_KERNEL); if (!zone_dev_attrs) return -ENOMEM; zone_attrs = - kzalloc(sizeof(struct attribute *) * (quirks->num_zones + 2), + kcalloc(quirks->num_zones + 2, sizeof(struct attribute *), GFP_KERNEL); if (!zone_attrs) return -ENOMEM; zone_data = - kzalloc(sizeof(struct platform_zone) * (quirks->num_zones), + kcalloc(quirks->num_zones, sizeof(struct platform_zone), GFP_KERNEL); if (!zone_data) return -ENOMEM; diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c index 58dcee562d64..054005051133 100644 --- a/drivers/platform/x86/intel_ips.c +++ b/drivers/platform/x86/intel_ips.c @@ -968,12 +968,12 @@ static int ips_monitor(void *data) u16 *mcp_samples, *ctv1_samples, *ctv2_samples, *mch_samples; u8 cur_seqno, last_seqno; - mcp_samples = kzalloc(sizeof(u16) * IPS_SAMPLE_COUNT, GFP_KERNEL); - ctv1_samples = kzalloc(sizeof(u16) * IPS_SAMPLE_COUNT, GFP_KERNEL); - ctv2_samples = kzalloc(sizeof(u16) * IPS_SAMPLE_COUNT, GFP_KERNEL); - mch_samples = kzalloc(sizeof(u16) * IPS_SAMPLE_COUNT, GFP_KERNEL); - cpu_samples = kzalloc(sizeof(u32) * IPS_SAMPLE_COUNT, GFP_KERNEL); - mchp_samples = kzalloc(sizeof(u32) * IPS_SAMPLE_COUNT, GFP_KERNEL); + mcp_samples = kcalloc(IPS_SAMPLE_COUNT, sizeof(u16), GFP_KERNEL); + ctv1_samples = kcalloc(IPS_SAMPLE_COUNT, sizeof(u16), GFP_KERNEL); + ctv2_samples = kcalloc(IPS_SAMPLE_COUNT, sizeof(u16), GFP_KERNEL); + mch_samples = kcalloc(IPS_SAMPLE_COUNT, sizeof(u16), GFP_KERNEL); + cpu_samples = kcalloc(IPS_SAMPLE_COUNT, sizeof(u32), GFP_KERNEL); + mchp_samples = kcalloc(IPS_SAMPLE_COUNT, sizeof(u32), GFP_KERNEL); if (!mcp_samples || !ctv1_samples || !ctv2_samples || !mch_samples || !cpu_samples || !mchp_samples) { dev_err(&ips->dev->dev, diff --git a/drivers/platform/x86/panasonic-laptop.c b/drivers/platform/x86/panasonic-laptop.c index 5c39b3211709..8361ad75389a 100644 --- a/drivers/platform/x86/panasonic-laptop.c +++ b/drivers/platform/x86/panasonic-laptop.c @@ -571,7 +571,7 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device) return -ENOMEM; } - pcc->sinf = kzalloc(sizeof(u32) * (num_sifr + 1), GFP_KERNEL); + pcc->sinf = kcalloc(num_sifr + 1, sizeof(u32), GFP_KERNEL); if (!pcc->sinf) { result = -ENOMEM; goto out_hotkey; diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 00d16cdef064..69fe49ceadf7 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -5966,7 +5966,7 @@ static int __init led_init(struct ibm_init_struct *iibm) if (led_supported == TPACPI_LED_NONE) return 1; - tpacpi_leds = kzalloc(sizeof(*tpacpi_leds) * TPACPI_LED_NUMLEDS, + tpacpi_leds = kcalloc(TPACPI_LED_NUMLEDS, sizeof(*tpacpi_leds), GFP_KERNEL); if (!tpacpi_leds) { pr_err("Out of memory for LED data\n"); diff --git a/drivers/power/supply/wm97xx_battery.c b/drivers/power/supply/wm97xx_battery.c index bd4f66651513..6754e761778a 100644 --- a/drivers/power/supply/wm97xx_battery.c +++ b/drivers/power/supply/wm97xx_battery.c @@ -201,7 +201,7 @@ static int wm97xx_bat_probe(struct platform_device *dev) if (pdata->min_voltage >= 0) props++; /* POWER_SUPPLY_PROP_VOLTAGE_MIN */ - prop = kzalloc(props * sizeof(*prop), GFP_KERNEL); + prop = kcalloc(props, sizeof(*prop), GFP_KERNEL); if (!prop) { ret = -ENOMEM; goto err3; diff --git a/drivers/power/supply/z2_battery.c b/drivers/power/supply/z2_battery.c index 8a43b49cfd35..bcc2d1a9b0a7 100644 --- a/drivers/power/supply/z2_battery.c +++ b/drivers/power/supply/z2_battery.c @@ -146,7 +146,7 @@ static int z2_batt_ps_init(struct z2_charger *charger, int props) if (info->min_voltage >= 0) props++; /* POWER_SUPPLY_PROP_VOLTAGE_MIN */ - prop = kzalloc(props * sizeof(*prop), GFP_KERNEL); + prop = kcalloc(props, sizeof(*prop), GFP_KERNEL); if (!prop) return -ENOMEM; diff --git a/drivers/powercap/powercap_sys.c b/drivers/powercap/powercap_sys.c index 5b10b50f8686..f9bce9e93f90 100644 --- a/drivers/powercap/powercap_sys.c +++ b/drivers/powercap/powercap_sys.c @@ -545,15 +545,16 @@ struct powercap_zone *powercap_register_zone( dev_set_name(&power_zone->dev, "%s:%x", dev_name(power_zone->dev.parent), power_zone->id); - power_zone->constraints = kzalloc(sizeof(*power_zone->constraints) * - nr_constraints, GFP_KERNEL); + power_zone->constraints = kcalloc(nr_constraints, + sizeof(*power_zone->constraints), + GFP_KERNEL); if (!power_zone->constraints) goto err_const_alloc; nr_attrs = nr_constraints * POWERCAP_CONSTRAINTS_ATTRS + POWERCAP_ZONE_MAX_ATTRS + 1; - power_zone->zone_dev_attrs = kzalloc(sizeof(void *) * - nr_attrs, GFP_KERNEL); + power_zone->zone_dev_attrs = kcalloc(nr_attrs, sizeof(void *), + GFP_KERNEL); if (!power_zone->zone_dev_attrs) goto err_attr_alloc; create_power_zone_common_attributes(power_zone); diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c index 23429bdaca84..887b3316385f 100644 --- a/drivers/rapidio/rio-scan.c +++ b/drivers/rapidio/rio-scan.c @@ -425,9 +425,8 @@ static struct rio_dev *rio_setup_device(struct rio_net *net, rswitch = rdev->rswitch; rswitch->port_ok = 0; spin_lock_init(&rswitch->lock); - rswitch->route_table = kzalloc(sizeof(u8)* - RIO_MAX_ROUTE_ENTRIES(port->sys_size), - GFP_KERNEL); + rswitch->route_table = kzalloc(RIO_MAX_ROUTE_ENTRIES(port->sys_size), + GFP_KERNEL); if (!rswitch->route_table) goto cleanup; /* Initialize switch route table */ diff --git a/drivers/regulator/cpr-regulator.c b/drivers/regulator/cpr-regulator.c index 0fc02056add3..7c103991214d 100644 --- a/drivers/regulator/cpr-regulator.c +++ b/drivers/regulator/cpr-regulator.c @@ -1903,7 +1903,7 @@ static int cpr_pvs_per_corner_init(struct device_node *of_node, "fuse position for init voltages is invalid\n"); return -EINVAL; } - fuse_sel = kzalloc(sizeof(u32) * size, GFP_KERNEL); + fuse_sel = kcalloc(size, sizeof(u32), GFP_KERNEL); if (!fuse_sel) return -ENOMEM; rc = of_property_read_u32_array(of_node, init_volt_str, @@ -1923,8 +1923,8 @@ static int cpr_pvs_per_corner_init(struct device_node *of_node, return rc; } - ref_uv = kzalloc((cpr_vreg->num_fuse_corners + 1) * sizeof(*ref_uv), - GFP_KERNEL); + ref_uv = kcalloc(cpr_vreg->num_fuse_corners + 1, sizeof(*ref_uv), + GFP_KERNEL); if (!ref_uv) { kfree(fuse_sel); return -ENOMEM; @@ -2036,7 +2036,8 @@ static int cpr_pvs_single_bin_init(struct device_node *of_node, ((1 << pvs_fuse[2]) - 1); pvs_bins = 1 << pvs_fuse[2]; stripe_size = cpr_vreg->num_fuse_corners; - tmp = kzalloc(sizeof(u32) * pvs_bins * stripe_size, GFP_KERNEL); + tmp = kzalloc(array3_size(pvs_bins, stripe_size, sizeof(u32)), + GFP_KERNEL); if (!tmp) return -ENOMEM; @@ -2392,7 +2393,7 @@ static int cpr_get_open_loop_voltage(struct cpr_regulator *cpr_vreg, } max_factor - = kzalloc(sizeof(*max_factor) * (cpr_vreg->num_fuse_corners + 1), + = kcalloc(cpr_vreg->num_fuse_corners + 1, sizeof(*max_factor), GFP_KERNEL); if (!max_factor) return -ENOMEM; @@ -2604,7 +2605,7 @@ static int cpr_get_fuse_quot_offset(struct cpr_regulator *cpr_vreg, return -EINVAL; } - fuse_sel = kzalloc(sizeof(u32) * size, GFP_KERNEL); + fuse_sel = kcalloc(size, sizeof(u32), GFP_KERNEL); if (!fuse_sel) return -ENOMEM; @@ -2636,9 +2637,9 @@ static int cpr_get_fuse_quot_offset(struct cpr_regulator *cpr_vreg, return -EINVAL; } - offset_multiplier = kzalloc(sizeof(*offset_multiplier) - * (cpr_vreg->num_fuse_corners + 1), - GFP_KERNEL); + offset_multiplier = kcalloc(cpr_vreg->num_fuse_corners + 1, + sizeof(*offset_multiplier), + GFP_KERNEL); if (!offset_multiplier) { kfree(fuse_sel); return -ENOMEM; @@ -3208,8 +3209,8 @@ static int cpr_read_ro_select(struct platform_device *pdev, int i; bp_ro_sel - = kzalloc((cpr_vreg->num_fuse_corners + 1) * sizeof(*bp_ro_sel), - GFP_KERNEL); + = kcalloc(cpr_vreg->num_fuse_corners + 1, sizeof(*bp_ro_sel), + GFP_KERNEL); if (!bp_ro_sel) return -ENOMEM; @@ -4824,7 +4825,7 @@ static int cpr_remap_efuse_data(struct platform_device *pdev, return rc; } - temp = kzalloc(sizeof(*temp) * size * 4, GFP_KERNEL); + temp = kzalloc(array3_size(sizeof(*temp), size, 4), GFP_KERNEL); if (!temp) return -ENOMEM; diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index 8f7c19901339..c3a664e64307 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -1162,7 +1162,7 @@ static int s2mps11_pmic_probe(struct platform_device *pdev) } } - rdata = kzalloc(sizeof(*rdata) * rdev_num, GFP_KERNEL); + rdata = kcalloc(rdev_num, sizeof(*rdata), GFP_KERNEL); if (!rdata) return -ENOMEM; diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c index 7abb240847c0..e2ac1bc44aff 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c @@ -230,9 +230,9 @@ dcssblk_is_continuous(struct dcssblk_dev_info *dev_info) if (dev_info->num_of_segments <= 1) return 0; - sort_list = kzalloc( - sizeof(struct segment_info) * dev_info->num_of_segments, - GFP_KERNEL); + sort_list = kcalloc(dev_info->num_of_segments, + sizeof(struct segment_info), + GFP_KERNEL); if (sort_list == NULL) return -ENOMEM; i = 0; diff --git a/drivers/s390/char/keyboard.c b/drivers/s390/char/keyboard.c index 5b505fdaedec..991ab4cad16a 100644 --- a/drivers/s390/char/keyboard.c +++ b/drivers/s390/char/keyboard.c @@ -78,7 +78,7 @@ kbd_alloc(void) { } } kbd->fn_handler = - kzalloc(sizeof(fn_handler_fn *) * NR_FN_HANDLER, GFP_KERNEL); + kcalloc(NR_FN_HANDLER, sizeof(fn_handler_fn *), GFP_KERNEL); if (!kbd->fn_handler) goto out_func; kbd->accent_table = kmemdup(accent_table, diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c index 04aceb694d51..6fcbbd55d675 100644 --- a/drivers/s390/char/vmur.c +++ b/drivers/s390/char/vmur.c @@ -241,7 +241,7 @@ static struct ccw1 *alloc_chan_prog(const char __user *ubuf, int rec_count, * That means we allocate room for CCWs to cover count/reclen * records plus a NOP. */ - cpa = kzalloc((rec_count + 1) * sizeof(struct ccw1), + cpa = kcalloc(rec_count + 1, sizeof(struct ccw1), GFP_KERNEL | GFP_DMA); if (!cpa) return ERR_PTR(-ENOMEM); diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c index aaed778f67c4..646d36b5c8e8 100644 --- a/drivers/s390/char/zcore.c +++ b/drivers/s390/char/zcore.c @@ -152,7 +152,7 @@ static int zcore_memmap_open(struct inode *inode, struct file *filp) char *buf; int i = 0; - buf = kzalloc(memblock.memory.cnt * CHUNK_INFO_SIZE, GFP_KERNEL); + buf = kcalloc(memblock.memory.cnt, CHUNK_INFO_SIZE, GFP_KERNEL); if (!buf) { return -ENOMEM; } diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c index a64615a10352..d06c50623fdc 100644 --- a/drivers/s390/cio/qdio_setup.c +++ b/drivers/s390/cio/qdio_setup.c @@ -535,7 +535,7 @@ void qdio_print_subchannel_info(struct qdio_irq *irq_ptr, int qdio_enable_async_operation(struct qdio_output_q *outq) { - outq->aobs = kzalloc(sizeof(struct qaob *) * QDIO_MAX_BUFFERS_PER_Q, + outq->aobs = kcalloc(QDIO_MAX_BUFFERS_PER_Q, sizeof(struct qaob *), GFP_ATOMIC); if (!outq->aobs) { outq->use_cq = 0; diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c index 4dc1108069d4..89ef40d574c7 100644 --- a/drivers/s390/cio/qdio_thinint.c +++ b/drivers/s390/cio/qdio_thinint.c @@ -244,8 +244,9 @@ out: /* allocate non-shared indicators and shared indicator */ int __init tiqdio_allocate_memory(void) { - q_indicators = kzalloc(sizeof(struct indicator_t) * TIQDIO_NR_INDICATORS, - GFP_KERNEL); + q_indicators = kcalloc(TIQDIO_NR_INDICATORS, + sizeof(struct indicator_t), + GFP_KERNEL); if (!q_indicators) return -ENOMEM; return 0; diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c index fbe35c2ac898..67338c43608c 100644 --- a/drivers/s390/net/ctcm_main.c +++ b/drivers/s390/net/ctcm_main.c @@ -1378,7 +1378,7 @@ static int add_channel(struct ccw_device *cdev, enum ctcm_channel_types type, } else ccw_num = 8; - ch->ccw = kzalloc(ccw_num * sizeof(struct ccw1), GFP_KERNEL | GFP_DMA); + ch->ccw = kcalloc(ccw_num, sizeof(struct ccw1), GFP_KERNEL | GFP_DMA); if (ch->ccw == NULL) goto nomem_return; diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 6566fceef38d..f1d2f250a98d 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -374,9 +374,9 @@ static int qeth_alloc_cq(struct qeth_card *card) } card->qdio.no_in_queues = 2; card->qdio.out_bufstates = - kzalloc(card->qdio.no_out_queues * - QDIO_MAX_BUFFERS_PER_Q * - sizeof(struct qdio_outbuf_state), GFP_KERNEL); + kcalloc(card->qdio.no_out_queues * QDIO_MAX_BUFFERS_PER_Q, + sizeof(struct qdio_outbuf_state), + GFP_KERNEL); outbuf_states = card->qdio.out_bufstates; if (outbuf_states == NULL) { rc = -1; @@ -2517,8 +2517,9 @@ static int qeth_alloc_qdio_buffers(struct qeth_card *card) /* outbound */ card->qdio.out_qs = - kzalloc(card->qdio.no_out_queues * - sizeof(struct qeth_qdio_out_q *), GFP_KERNEL); + kcalloc(card->qdio.no_out_queues, + sizeof(struct qeth_qdio_out_q *), + GFP_KERNEL); if (!card->qdio.out_qs) goto out_freepool; for (i = 0; i < card->qdio.no_out_queues; ++i) { @@ -4951,8 +4952,8 @@ static int qeth_qdio_establish(struct qeth_card *card) QETH_DBF_TEXT(SETUP, 2, "qdioest"); - qib_param_field = kzalloc(QDIO_MAX_BUFFERS_PER_Q * sizeof(char), - GFP_KERNEL); + qib_param_field = kzalloc(QDIO_MAX_BUFFERS_PER_Q, + GFP_KERNEL); if (!qib_param_field) { rc = -ENOMEM; goto out_free_nothing; @@ -4961,8 +4962,8 @@ static int qeth_qdio_establish(struct qeth_card *card) qeth_create_qib_param_field(card, qib_param_field); qeth_create_qib_param_field_blkt(card, qib_param_field); - in_sbal_ptrs = kzalloc(card->qdio.no_in_queues * - QDIO_MAX_BUFFERS_PER_Q * sizeof(void *), + in_sbal_ptrs = kcalloc(card->qdio.no_in_queues * QDIO_MAX_BUFFERS_PER_Q, + sizeof(void *), GFP_KERNEL); if (!in_sbal_ptrs) { rc = -ENOMEM; @@ -4973,7 +4974,7 @@ static int qeth_qdio_establish(struct qeth_card *card) virt_to_phys(card->qdio.in_q->bufs[i].buffer); } - queue_start_poll = kzalloc(sizeof(void *) * card->qdio.no_in_queues, + queue_start_poll = kcalloc(card->qdio.no_in_queues, sizeof(void *), GFP_KERNEL); if (!queue_start_poll) { rc = -ENOMEM; @@ -4985,8 +4986,9 @@ static int qeth_qdio_establish(struct qeth_card *card) qeth_qdio_establish_cq(card, in_sbal_ptrs, queue_start_poll); out_sbal_ptrs = - kzalloc(card->qdio.no_out_queues * QDIO_MAX_BUFFERS_PER_Q * - sizeof(void *), GFP_KERNEL); + kcalloc(card->qdio.no_out_queues * QDIO_MAX_BUFFERS_PER_Q, + sizeof(void *), + GFP_KERNEL); if (!out_sbal_ptrs) { rc = -ENOMEM; goto out_free_queue_start_poll; diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c index 35380a58d3f0..0d4ffe0ae306 100644 --- a/drivers/scsi/BusLogic.c +++ b/drivers/scsi/BusLogic.c @@ -2366,7 +2366,7 @@ static int __init blogic_init(void) if (blogic_probe_options.noprobe) return -ENODEV; blogic_probeinfo_list = - kzalloc(BLOGIC_MAX_ADAPTERS * sizeof(struct blogic_probeinfo), + kcalloc(BLOGIC_MAX_ADAPTERS, sizeof(struct blogic_probeinfo), GFP_KERNEL); if (blogic_probeinfo_list == NULL) { blogic_err("BusLogic: Unable to allocate Probe Info List\n", diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 053a31c5485f..16900b9fdf4b 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -1684,7 +1684,9 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) aac->cardtype = index; INIT_LIST_HEAD(&aac->entry); - aac->fibs = kzalloc(sizeof(struct fib) * (shost->can_queue + AAC_NUM_MGT_FIB), GFP_KERNEL); + aac->fibs = kcalloc(shost->can_queue + AAC_NUM_MGT_FIB, + sizeof(struct fib), + GFP_KERNEL); if (!aac->fibs) goto out_free_host; spin_lock_init(&aac->fib_lock); diff --git a/drivers/scsi/aic7xxx/aic7xxx_core.c b/drivers/scsi/aic7xxx/aic7xxx_core.c index fdbb0a3dc9b4..6d93551fa56a 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_core.c +++ b/drivers/scsi/aic7xxx/aic7xxx_core.c @@ -4779,8 +4779,8 @@ ahc_init_scbdata(struct ahc_softc *ahc) SLIST_INIT(&scb_data->sg_maps); /* Allocate SCB resources */ - scb_data->scbarray = kzalloc(sizeof(struct scb) * AHC_SCB_MAX_ALLOC, - GFP_ATOMIC); + scb_data->scbarray = kcalloc(AHC_SCB_MAX_ALLOC, sizeof(struct scb), + GFP_ATOMIC); if (scb_data->scbarray == NULL) return (ENOMEM); diff --git a/drivers/scsi/aic94xx/aic94xx_hwi.c b/drivers/scsi/aic94xx/aic94xx_hwi.c index dfe8fc16b41b..93bbcb33fd32 100644 --- a/drivers/scsi/aic94xx/aic94xx_hwi.c +++ b/drivers/scsi/aic94xx/aic94xx_hwi.c @@ -220,8 +220,9 @@ static int asd_init_scbs(struct asd_ha_struct *asd_ha) /* allocate the index array and bitmap */ asd_ha->seq.tc_index_bitmap_bits = asd_ha->hw_prof.max_scbs; - asd_ha->seq.tc_index_array = kzalloc(asd_ha->seq.tc_index_bitmap_bits* - sizeof(void *), GFP_KERNEL); + asd_ha->seq.tc_index_array = kcalloc(asd_ha->seq.tc_index_bitmap_bits, + sizeof(void *), + GFP_KERNEL); if (!asd_ha->seq.tc_index_array) return -ENOMEM; diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c index eb5ee0ec5a2f..702da909cee5 100644 --- a/drivers/scsi/aic94xx/aic94xx_init.c +++ b/drivers/scsi/aic94xx/aic94xx_init.c @@ -350,7 +350,7 @@ static ssize_t asd_store_update_bios(struct device *dev, int flash_command = FLASH_CMD_NONE; int err = 0; - cmd_ptr = kzalloc(count*2, GFP_KERNEL); + cmd_ptr = kcalloc(count, 2, GFP_KERNEL); if (!cmd_ptr) { err = FAIL_OUT_MEMORY; diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index d6ce7545f35a..33f0bb5e5683 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -2455,8 +2455,8 @@ static int beiscsi_alloc_mem(struct beiscsi_hba *phba) /* Allocate memory for wrb_context */ phwi_ctrlr = phba->phwi_ctrlr; - phwi_ctrlr->wrb_context = kzalloc(sizeof(struct hwi_wrb_context) * - phba->params.cxns_per_ctrl, + phwi_ctrlr->wrb_context = kcalloc(phba->params.cxns_per_ctrl, + sizeof(struct hwi_wrb_context), GFP_KERNEL); if (!phwi_ctrlr->wrb_context) { kfree(phba->phwi_ctrlr); @@ -2609,8 +2609,8 @@ static int beiscsi_init_wrb_handle(struct beiscsi_hba *phba) /* Allocate memory for WRBQ */ phwi_ctxt = phwi_ctrlr->phwi_ctxt; - phwi_ctxt->be_wrbq = kzalloc(sizeof(struct be_queue_info) * - phba->params.cxns_per_ctrl, + phwi_ctxt->be_wrbq = kcalloc(phba->params.cxns_per_ctrl, + sizeof(struct be_queue_info), GFP_KERNEL); if (!phwi_ctxt->be_wrbq) { beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, @@ -2621,16 +2621,18 @@ static int beiscsi_init_wrb_handle(struct beiscsi_hba *phba) for (index = 0; index < phba->params.cxns_per_ctrl; index++) { pwrb_context = &phwi_ctrlr->wrb_context[index]; pwrb_context->pwrb_handle_base = - kzalloc(sizeof(struct wrb_handle *) * - phba->params.wrbs_per_cxn, GFP_KERNEL); + kcalloc(phba->params.wrbs_per_cxn, + sizeof(struct wrb_handle *), + GFP_KERNEL); if (!pwrb_context->pwrb_handle_base) { beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, "BM_%d : Mem Alloc Failed. Failing to load\n"); goto init_wrb_hndl_failed; } pwrb_context->pwrb_handle_basestd = - kzalloc(sizeof(struct wrb_handle *) * - phba->params.wrbs_per_cxn, GFP_KERNEL); + kcalloc(phba->params.wrbs_per_cxn, + sizeof(struct wrb_handle *), + GFP_KERNEL); if (!pwrb_context->pwrb_handle_basestd) { beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, "BM_%d : Mem Alloc Failed. Failing to load\n"); @@ -3886,17 +3888,16 @@ static int beiscsi_init_sgl_handle(struct beiscsi_hba *phba) mem_descr_sglh = phba->init_mem; mem_descr_sglh += HWI_MEM_SGLH; if (1 == mem_descr_sglh->num_elements) { - phba->io_sgl_hndl_base = kzalloc(sizeof(struct sgl_handle *) * - phba->params.ios_per_ctrl, + phba->io_sgl_hndl_base = kcalloc(phba->params.ios_per_ctrl, + sizeof(struct sgl_handle *), GFP_KERNEL); if (!phba->io_sgl_hndl_base) { beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, "BM_%d : Mem Alloc Failed. Failing to load\n"); return -ENOMEM; } - phba->eh_sgl_hndl_base = kzalloc(sizeof(struct sgl_handle *) * - (phba->params.icds_per_ctrl - - phba->params.ios_per_ctrl), + phba->eh_sgl_hndl_base = kcalloc(phba->params.icds_per_ctrl - phba->params.ios_per_ctrl, + sizeof(struct sgl_handle *), GFP_KERNEL); if (!phba->eh_sgl_hndl_base) { kfree(phba->io_sgl_hndl_base); @@ -4024,8 +4025,9 @@ static int hba_setup_cid_tbls(struct beiscsi_hba *phba) phba->cid_array_info[ulp_num] = ptr_cid_info; } } - phba->ep_array = kzalloc(sizeof(struct iscsi_endpoint *) * - phba->params.cxns_per_ctrl, GFP_KERNEL); + phba->ep_array = kcalloc(phba->params.cxns_per_ctrl, + sizeof(struct iscsi_endpoint *), + GFP_KERNEL); if (!phba->ep_array) { beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, "BM_%d : Failed to allocate memory in " @@ -4035,8 +4037,9 @@ static int hba_setup_cid_tbls(struct beiscsi_hba *phba) goto free_memory; } - phba->conn_table = kzalloc(sizeof(struct beiscsi_conn *) * - phba->params.cxns_per_ctrl, GFP_KERNEL); + phba->conn_table = kcalloc(phba->params.cxns_per_ctrl, + sizeof(struct beiscsi_conn *), + GFP_KERNEL); if (!phba->conn_table) { beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, "BM_%d : Failed to allocate memory in" diff --git a/drivers/scsi/bfa/bfad_attr.c b/drivers/scsi/bfa/bfad_attr.c index 0a70d54a4df6..d2faf6f5ae72 100644 --- a/drivers/scsi/bfa/bfad_attr.c +++ b/drivers/scsi/bfa/bfad_attr.c @@ -932,7 +932,7 @@ bfad_im_num_of_discovered_ports_show(struct device *dev, struct bfa_rport_qualifier_s *rports = NULL; unsigned long flags; - rports = kzalloc(sizeof(struct bfa_rport_qualifier_s) * nrports, + rports = kcalloc(nrports, sizeof(struct bfa_rport_qualifier_s), GFP_ATOMIC); if (rports == NULL) return snprintf(buf, PAGE_SIZE, "Failed\n"); diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c index 9081a5f93aae..9b6ec50373a2 100644 --- a/drivers/scsi/bfa/bfad_bsg.c +++ b/drivers/scsi/bfa/bfad_bsg.c @@ -3261,8 +3261,8 @@ bfad_fcxp_map_sg(struct bfad_s *bfad, void *payload_kbuf, struct bfa_sge_s *sg_table; int sge_num = 1; - buf_base = kzalloc((sizeof(struct bfad_buf_info) + - sizeof(struct bfa_sge_s)) * sge_num, GFP_KERNEL); + buf_base = kcalloc(sizeof(struct bfad_buf_info) + sizeof(struct bfa_sge_s), + sge_num, GFP_KERNEL); if (!buf_base) return NULL; diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index 116a56f0af01..1d8c56cd0c94 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -1397,7 +1397,7 @@ static struct bnx2fc_hba *bnx2fc_hba_create(struct cnic_dev *cnic) hba->next_conn_id = 0; hba->tgt_ofld_list = - kzalloc(sizeof(struct bnx2fc_rport *) * BNX2FC_NUM_MAX_SESS, + kcalloc(BNX2FC_NUM_MAX_SESS, sizeof(struct bnx2fc_rport *), GFP_KERNEL); if (!hba->tgt_ofld_list) { printk(KERN_ERR PFX "Unable to allocate tgt offload list\n"); diff --git a/drivers/scsi/bnx2fc/bnx2fc_io.c b/drivers/scsi/bnx2fc/bnx2fc_io.c index 6626b28ba8fe..582daadb85cd 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_io.c +++ b/drivers/scsi/bnx2fc/bnx2fc_io.c @@ -240,15 +240,15 @@ struct bnx2fc_cmd_mgr *bnx2fc_cmd_mgr_alloc(struct bnx2fc_hba *hba) return NULL; } - cmgr->free_list = kzalloc(sizeof(*cmgr->free_list) * - arr_sz, GFP_KERNEL); + cmgr->free_list = kcalloc(arr_sz, sizeof(*cmgr->free_list), + GFP_KERNEL); if (!cmgr->free_list) { printk(KERN_ERR PFX "failed to alloc free_list\n"); goto mem_err; } - cmgr->free_list_lock = kzalloc(sizeof(*cmgr->free_list_lock) * - arr_sz, GFP_KERNEL); + cmgr->free_list_lock = kcalloc(arr_sz, sizeof(*cmgr->free_list_lock), + GFP_KERNEL); if (!cmgr->free_list_lock) { printk(KERN_ERR PFX "failed to alloc free_list_lock\n"); kfree(cmgr->free_list); diff --git a/drivers/scsi/csiostor/csio_wr.c b/drivers/scsi/csiostor/csio_wr.c index c0a17789752f..faa357b62c61 100644 --- a/drivers/scsi/csiostor/csio_wr.c +++ b/drivers/scsi/csiostor/csio_wr.c @@ -276,7 +276,7 @@ csio_wr_alloc_q(struct csio_hw *hw, uint32_t qsize, uint32_t wrsize, q->un.iq.flq_idx = flq_idx; flq = wrm->q_arr[q->un.iq.flq_idx]; - flq->un.fl.bufs = kzalloc(flq->credits * + flq->un.fl.bufs = kcalloc(flq->credits, sizeof(struct csio_dma_buf), GFP_KERNEL); if (!flq->un.fl.bufs) { @@ -1579,7 +1579,7 @@ csio_wrm_init(struct csio_wrm *wrm, struct csio_hw *hw) return -EINVAL; } - wrm->q_arr = kzalloc(sizeof(struct csio_q *) * wrm->num_q, GFP_KERNEL); + wrm->q_arr = kcalloc(wrm->num_q, sizeof(struct csio_q *), GFP_KERNEL); if (!wrm->q_arr) goto err; diff --git a/drivers/scsi/esas2r/esas2r_init.c b/drivers/scsi/esas2r/esas2r_init.c index 5b14dd29b764..ca539e027925 100644 --- a/drivers/scsi/esas2r/esas2r_init.c +++ b/drivers/scsi/esas2r/esas2r_init.c @@ -854,7 +854,7 @@ bool esas2r_init_adapter_struct(struct esas2r_adapter *a, /* allocate requests for asynchronous events */ a->first_ae_req = - kzalloc(num_ae_requests * sizeof(struct esas2r_request), + kcalloc(num_ae_requests, sizeof(struct esas2r_request), GFP_KERNEL); if (a->first_ae_req == NULL) { @@ -864,8 +864,8 @@ bool esas2r_init_adapter_struct(struct esas2r_adapter *a, } /* allocate the S/G list memory descriptors */ - a->sg_list_mds = kzalloc( - num_sg_lists * sizeof(struct esas2r_mem_desc), GFP_KERNEL); + a->sg_list_mds = kcalloc(num_sg_lists, sizeof(struct esas2r_mem_desc), + GFP_KERNEL); if (a->sg_list_mds == NULL) { esas2r_log(ESAS2R_LOG_CRIT, @@ -875,8 +875,9 @@ bool esas2r_init_adapter_struct(struct esas2r_adapter *a, /* allocate the request table */ a->req_table = - kzalloc((num_requests + num_ae_requests + - 1) * sizeof(struct esas2r_request *), GFP_KERNEL); + kcalloc(num_requests + num_ae_requests + 1, + sizeof(struct esas2r_request *), + GFP_KERNEL); if (a->req_table == NULL) { esas2r_log(ESAS2R_LOG_CRIT, diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index d3fc4922251b..3fa80eb6b355 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -1876,8 +1876,8 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, } spin_unlock_irqrestore(&h->reset_lock, flags); - added = kzalloc(sizeof(*added) * HPSA_MAX_DEVICES, GFP_KERNEL); - removed = kzalloc(sizeof(*removed) * HPSA_MAX_DEVICES, GFP_KERNEL); + added = kcalloc(HPSA_MAX_DEVICES, sizeof(*added), GFP_KERNEL); + removed = kcalloc(HPSA_MAX_DEVICES, sizeof(*removed), GFP_KERNEL); if (!added || !removed) { dev_warn(&h->pdev->dev, "out of memory in " @@ -2119,7 +2119,7 @@ static int hpsa_allocate_ioaccel2_sg_chain_blocks(struct ctlr_info *h) return 0; h->ioaccel2_cmd_sg_list = - kzalloc(sizeof(*h->ioaccel2_cmd_sg_list) * h->nr_cmds, + kcalloc(h->nr_cmds, sizeof(*h->ioaccel2_cmd_sg_list), GFP_KERNEL); if (!h->ioaccel2_cmd_sg_list) return -ENOMEM; @@ -2159,8 +2159,8 @@ static int hpsa_alloc_sg_chain_blocks(struct ctlr_info *h) if (h->chainsize <= 0) return 0; - h->cmd_sg_list = kzalloc(sizeof(*h->cmd_sg_list) * h->nr_cmds, - GFP_KERNEL); + h->cmd_sg_list = kcalloc(h->nr_cmds, sizeof(*h->cmd_sg_list), + GFP_KERNEL); if (!h->cmd_sg_list) return -ENOMEM; @@ -4188,7 +4188,7 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) bool physical_device; DECLARE_BITMAP(lunzerobits, MAX_EXT_TARGETS); - currentsd = kzalloc(sizeof(*currentsd) * HPSA_MAX_DEVICES, GFP_KERNEL); + currentsd = kcalloc(HPSA_MAX_DEVICES, sizeof(*currentsd), GFP_KERNEL); physdev_list = kzalloc(sizeof(*physdev_list), GFP_KERNEL); logdev_list = kzalloc(sizeof(*logdev_list), GFP_KERNEL); tmpdevice = kzalloc(sizeof(*tmpdevice), GFP_KERNEL); @@ -6298,7 +6298,7 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp) status = -EINVAL; goto cleanup1; } - buff = kzalloc(SG_ENTRIES_IN_CMD * sizeof(char *), GFP_KERNEL); + buff = kcalloc(SG_ENTRIES_IN_CMD, sizeof(char *), GFP_KERNEL); if (!buff) { status = -ENOMEM; goto cleanup1; @@ -7816,9 +7816,9 @@ static void hpsa_free_cmd_pool(struct ctlr_info *h) static int hpsa_alloc_cmd_pool(struct ctlr_info *h) { - h->cmd_pool_bits = kzalloc( - DIV_ROUND_UP(h->nr_cmds, BITS_PER_LONG) * - sizeof(unsigned long), GFP_KERNEL); + h->cmd_pool_bits = kcalloc(DIV_ROUND_UP(h->nr_cmds, BITS_PER_LONG), + sizeof(unsigned long), + GFP_KERNEL); h->cmd_pool = pci_alloc_consistent(h->pdev, h->nr_cmds * sizeof(*h->cmd_pool), &(h->cmd_pool_dhandle)); @@ -8328,7 +8328,7 @@ static struct ctlr_info *hpda_alloc_ctlr_info(void) if (!h) return NULL; - h->reply_map = kzalloc(sizeof(*h->reply_map) * nr_cpu_ids, GFP_KERNEL); + h->reply_map = kcalloc(nr_cpu_ids, sizeof(*h->reply_map), GFP_KERNEL); if (!h->reply_map) { kfree(h); return NULL; diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index b172f0a02083..1d2fce8941c8 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -9759,8 +9759,9 @@ static int ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg) int i, rc = -ENOMEM; ENTER; - ioa_cfg->res_entries = kzalloc(sizeof(struct ipr_resource_entry) * - ioa_cfg->max_devs_supported, GFP_KERNEL); + ioa_cfg->res_entries = kcalloc(ioa_cfg->max_devs_supported, + sizeof(struct ipr_resource_entry), + GFP_KERNEL); if (!ioa_cfg->res_entries) goto out; @@ -9821,8 +9822,9 @@ static int ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg) list_add_tail(&ioa_cfg->hostrcb[i]->queue, &ioa_cfg->hostrcb_free_q); } - ioa_cfg->trace = kzalloc(sizeof(struct ipr_trace_entry) * - IPR_NUM_TRACE_ENTRIES, GFP_KERNEL); + ioa_cfg->trace = kcalloc(IPR_NUM_TRACE_ENTRIES, + sizeof(struct ipr_trace_entry), + GFP_KERNEL); if (!ioa_cfg->trace) goto out_free_hostrcb_dma; diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index f77d72f01da9..bd9bbfb44479 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c @@ -442,7 +442,7 @@ static int sas_expander_discover(struct domain_device *dev) struct expander_device *ex = &dev->ex_dev; int res = -ENOMEM; - ex->ex_phy = kzalloc(sizeof(*ex->ex_phy)*ex->num_phys, GFP_KERNEL); + ex->ex_phy = kcalloc(ex->num_phys, sizeof(*ex->ex_phy), GFP_KERNEL); if (!ex->ex_phy) return -ENOMEM; diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 9fc5507ee39e..c6c4aa6faf7e 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -5686,8 +5686,9 @@ lpfc_sli_driver_resource_setup(struct lpfc_hba *phba) } if (!phba->sli.sli3_ring) - phba->sli.sli3_ring = kzalloc(LPFC_SLI3_MAX_RING * - sizeof(struct lpfc_sli_ring), GFP_KERNEL); + phba->sli.sli3_ring = kcalloc(LPFC_SLI3_MAX_RING, + sizeof(struct lpfc_sli_ring), + GFP_KERNEL); if (!phba->sli.sli3_ring) return -ENOMEM; @@ -6176,7 +6177,7 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) /* Allocate eligible FCF bmask memory for FCF roundrobin failover */ longs = (LPFC_SLI4_FCF_TBL_INDX_MAX + BITS_PER_LONG - 1)/BITS_PER_LONG; - phba->fcf.fcf_rr_bmask = kzalloc(longs * sizeof(unsigned long), + phba->fcf.fcf_rr_bmask = kcalloc(longs, sizeof(unsigned long), GFP_KERNEL); if (!phba->fcf.fcf_rr_bmask) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 480d2d467f7a..1061b5008a7c 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -1522,7 +1522,7 @@ lpfc_sli_next_iotag(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) - LPFC_IOCBQ_LOOKUP_INCREMENT)) { new_len = psli->iocbq_lookup_len + LPFC_IOCBQ_LOOKUP_INCREMENT; spin_unlock_irq(&phba->hbalock); - new_arr = kzalloc(new_len * sizeof (struct lpfc_iocbq *), + new_arr = kcalloc(new_len, sizeof(struct lpfc_iocbq *), GFP_KERNEL); if (new_arr) { spin_lock_irq(&phba->hbalock); @@ -4936,16 +4936,17 @@ lpfc_sli_hba_setup(struct lpfc_hba *phba) */ if ((phba->vpi_bmask == NULL) && (phba->vpi_ids == NULL)) { longs = (phba->max_vpi + BITS_PER_LONG) / BITS_PER_LONG; - phba->vpi_bmask = kzalloc(longs * sizeof(unsigned long), + phba->vpi_bmask = kcalloc(longs, + sizeof(unsigned long), GFP_KERNEL); if (!phba->vpi_bmask) { rc = -ENOMEM; goto lpfc_sli_hba_setup_error; } - phba->vpi_ids = kzalloc( - (phba->max_vpi+1) * sizeof(uint16_t), - GFP_KERNEL); + phba->vpi_ids = kcalloc(phba->max_vpi + 1, + sizeof(uint16_t), + GFP_KERNEL); if (!phba->vpi_ids) { kfree(phba->vpi_bmask); rc = -ENOMEM; @@ -5629,14 +5630,14 @@ lpfc_sli4_alloc_extent(struct lpfc_hba *phba, uint16_t type) length = sizeof(struct lpfc_rsrc_blks); switch (type) { case LPFC_RSC_TYPE_FCOE_RPI: - phba->sli4_hba.rpi_bmask = kzalloc(longs * + phba->sli4_hba.rpi_bmask = kcalloc(longs, sizeof(unsigned long), GFP_KERNEL); if (unlikely(!phba->sli4_hba.rpi_bmask)) { rc = -ENOMEM; goto err_exit; } - phba->sli4_hba.rpi_ids = kzalloc(rsrc_id_cnt * + phba->sli4_hba.rpi_ids = kcalloc(rsrc_id_cnt, sizeof(uint16_t), GFP_KERNEL); if (unlikely(!phba->sli4_hba.rpi_ids)) { @@ -5658,15 +5659,13 @@ lpfc_sli4_alloc_extent(struct lpfc_hba *phba, uint16_t type) ext_blk_list = &phba->sli4_hba.lpfc_rpi_blk_list; break; case LPFC_RSC_TYPE_FCOE_VPI: - phba->vpi_bmask = kzalloc(longs * - sizeof(unsigned long), + phba->vpi_bmask = kcalloc(longs, sizeof(unsigned long), GFP_KERNEL); if (unlikely(!phba->vpi_bmask)) { rc = -ENOMEM; goto err_exit; } - phba->vpi_ids = kzalloc(rsrc_id_cnt * - sizeof(uint16_t), + phba->vpi_ids = kcalloc(rsrc_id_cnt, sizeof(uint16_t), GFP_KERNEL); if (unlikely(!phba->vpi_ids)) { kfree(phba->vpi_bmask); @@ -5680,7 +5679,7 @@ lpfc_sli4_alloc_extent(struct lpfc_hba *phba, uint16_t type) ext_blk_list = &phba->lpfc_vpi_blk_list; break; case LPFC_RSC_TYPE_FCOE_XRI: - phba->sli4_hba.xri_bmask = kzalloc(longs * + phba->sli4_hba.xri_bmask = kcalloc(longs, sizeof(unsigned long), GFP_KERNEL); if (unlikely(!phba->sli4_hba.xri_bmask)) { @@ -5688,7 +5687,7 @@ lpfc_sli4_alloc_extent(struct lpfc_hba *phba, uint16_t type) goto err_exit; } phba->sli4_hba.max_cfg_param.xri_used = 0; - phba->sli4_hba.xri_ids = kzalloc(rsrc_id_cnt * + phba->sli4_hba.xri_ids = kcalloc(rsrc_id_cnt, sizeof(uint16_t), GFP_KERNEL); if (unlikely(!phba->sli4_hba.xri_ids)) { @@ -5703,14 +5702,14 @@ lpfc_sli4_alloc_extent(struct lpfc_hba *phba, uint16_t type) ext_blk_list = &phba->sli4_hba.lpfc_xri_blk_list; break; case LPFC_RSC_TYPE_FCOE_VFI: - phba->sli4_hba.vfi_bmask = kzalloc(longs * + phba->sli4_hba.vfi_bmask = kcalloc(longs, sizeof(unsigned long), GFP_KERNEL); if (unlikely(!phba->sli4_hba.vfi_bmask)) { rc = -ENOMEM; goto err_exit; } - phba->sli4_hba.vfi_ids = kzalloc(rsrc_id_cnt * + phba->sli4_hba.vfi_ids = kcalloc(rsrc_id_cnt, sizeof(uint16_t), GFP_KERNEL); if (unlikely(!phba->sli4_hba.vfi_ids)) { @@ -6043,15 +6042,14 @@ lpfc_sli4_alloc_resource_identifiers(struct lpfc_hba *phba) } base = phba->sli4_hba.max_cfg_param.rpi_base; longs = (count + BITS_PER_LONG - 1) / BITS_PER_LONG; - phba->sli4_hba.rpi_bmask = kzalloc(longs * + phba->sli4_hba.rpi_bmask = kcalloc(longs, sizeof(unsigned long), GFP_KERNEL); if (unlikely(!phba->sli4_hba.rpi_bmask)) { rc = -ENOMEM; goto err_exit; } - phba->sli4_hba.rpi_ids = kzalloc(count * - sizeof(uint16_t), + phba->sli4_hba.rpi_ids = kcalloc(count, sizeof(uint16_t), GFP_KERNEL); if (unlikely(!phba->sli4_hba.rpi_ids)) { rc = -ENOMEM; @@ -6072,15 +6070,13 @@ lpfc_sli4_alloc_resource_identifiers(struct lpfc_hba *phba) } base = phba->sli4_hba.max_cfg_param.vpi_base; longs = (count + BITS_PER_LONG - 1) / BITS_PER_LONG; - phba->vpi_bmask = kzalloc(longs * - sizeof(unsigned long), + phba->vpi_bmask = kcalloc(longs, sizeof(unsigned long), GFP_KERNEL); if (unlikely(!phba->vpi_bmask)) { rc = -ENOMEM; goto free_rpi_ids; } - phba->vpi_ids = kzalloc(count * - sizeof(uint16_t), + phba->vpi_ids = kcalloc(count, sizeof(uint16_t), GFP_KERNEL); if (unlikely(!phba->vpi_ids)) { rc = -ENOMEM; @@ -6101,7 +6097,7 @@ lpfc_sli4_alloc_resource_identifiers(struct lpfc_hba *phba) } base = phba->sli4_hba.max_cfg_param.xri_base; longs = (count + BITS_PER_LONG - 1) / BITS_PER_LONG; - phba->sli4_hba.xri_bmask = kzalloc(longs * + phba->sli4_hba.xri_bmask = kcalloc(longs, sizeof(unsigned long), GFP_KERNEL); if (unlikely(!phba->sli4_hba.xri_bmask)) { @@ -6109,8 +6105,7 @@ lpfc_sli4_alloc_resource_identifiers(struct lpfc_hba *phba) goto free_vpi_ids; } phba->sli4_hba.max_cfg_param.xri_used = 0; - phba->sli4_hba.xri_ids = kzalloc(count * - sizeof(uint16_t), + phba->sli4_hba.xri_ids = kcalloc(count, sizeof(uint16_t), GFP_KERNEL); if (unlikely(!phba->sli4_hba.xri_ids)) { rc = -ENOMEM; @@ -6131,15 +6126,14 @@ lpfc_sli4_alloc_resource_identifiers(struct lpfc_hba *phba) } base = phba->sli4_hba.max_cfg_param.vfi_base; longs = (count + BITS_PER_LONG - 1) / BITS_PER_LONG; - phba->sli4_hba.vfi_bmask = kzalloc(longs * + phba->sli4_hba.vfi_bmask = kcalloc(longs, sizeof(unsigned long), GFP_KERNEL); if (unlikely(!phba->sli4_hba.vfi_bmask)) { rc = -ENOMEM; goto free_xri_ids; } - phba->sli4_hba.vfi_ids = kzalloc(count * - sizeof(uint16_t), + phba->sli4_hba.vfi_ids = kcalloc(count, sizeof(uint16_t), GFP_KERNEL); if (unlikely(!phba->sli4_hba.vfi_ids)) { rc = -ENOMEM; diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c index c714482bf4c5..7c282f688b68 100644 --- a/drivers/scsi/lpfc/lpfc_vport.c +++ b/drivers/scsi/lpfc/lpfc_vport.c @@ -831,7 +831,7 @@ lpfc_create_vport_work_array(struct lpfc_hba *phba) struct lpfc_vport *port_iterator; struct lpfc_vport **vports; int index = 0; - vports = kzalloc((phba->max_vports + 1) * sizeof(struct lpfc_vport *), + vports = kcalloc(phba->max_vports + 1, sizeof(struct lpfc_vport *), GFP_KERNEL); if (vports == NULL) return NULL; diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 42d876034741..e1346abb42aa 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -5394,9 +5394,9 @@ static int megasas_init_fw(struct megasas_instance *instance) /* stream detection initialization */ if (instance->adapter_type == VENTURA_SERIES) { fusion->stream_detect_by_ld = - kzalloc(sizeof(struct LD_STREAM_DETECT *) - * MAX_LOGICAL_DRIVES_EXT, - GFP_KERNEL); + kcalloc(MAX_LOGICAL_DRIVES_EXT, + sizeof(struct LD_STREAM_DETECT *), + GFP_KERNEL); if (!fusion->stream_detect_by_ld) { dev_err(&instance->pdev->dev, "unable to allocate stream detection for pool of LDs\n"); @@ -6073,7 +6073,7 @@ static inline int megasas_alloc_mfi_ctrl_mem(struct megasas_instance *instance) */ static int megasas_alloc_ctrl_mem(struct megasas_instance *instance) { - instance->reply_map = kzalloc(sizeof(unsigned int) * nr_cpu_ids, + instance->reply_map = kcalloc(nr_cpu_ids, sizeof(unsigned int), GFP_KERNEL); if (!instance->reply_map) return -ENOMEM; diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index b13721290f4b..05a25aa4e112 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c @@ -432,7 +432,7 @@ megasas_alloc_cmdlist_fusion(struct megasas_instance *instance) * commands. */ fusion->cmd_list = - kzalloc(sizeof(struct megasas_cmd_fusion *) * max_mpt_cmd, + kcalloc(max_mpt_cmd, sizeof(struct megasas_cmd_fusion *), GFP_KERNEL); if (!fusion->cmd_list) { dev_err(&instance->pdev->dev, diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index d04e4d433c9f..b78158d8cab8 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c @@ -381,7 +381,7 @@ static int osst_execute(struct osst_request *SRpnt, const unsigned char *cmd, struct scatterlist *sg, *sgl = (struct scatterlist *)buffer; int i; - pages = kzalloc(use_sg * sizeof(struct page *), GFP_KERNEL); + pages = kcalloc(use_sg, sizeof(struct page *), GFP_KERNEL); if (!pages) goto free_req; diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c index be8269c8d127..b989ed968020 100644 --- a/drivers/scsi/pm8001/pm8001_ctl.c +++ b/drivers/scsi/pm8001/pm8001_ctl.c @@ -653,7 +653,7 @@ static ssize_t pm8001_store_update_fw(struct device *cdev, return -EINPROGRESS; pm8001_ha->fw_status = FLASH_IN_PROGRESS; - cmd_ptr = kzalloc(count*2, GFP_KERNEL); + cmd_ptr = kcalloc(count, 2, GFP_KERNEL); if (!cmd_ptr) { pm8001_ha->fw_status = FAIL_OUT_MEMORY; return -ENOMEM; diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c index b4d6cd8cd1ad..9baac4f8d948 100644 --- a/drivers/scsi/pmcraid.c +++ b/drivers/scsi/pmcraid.c @@ -4915,8 +4915,9 @@ static int pmcraid_allocate_config_buffers(struct pmcraid_instance *pinstance) int i; pinstance->res_entries = - kzalloc(sizeof(struct pmcraid_resource_entry) * - PMCRAID_MAX_RESOURCES, GFP_KERNEL); + kcalloc(PMCRAID_MAX_RESOURCES, + sizeof(struct pmcraid_resource_entry), + GFP_KERNEL); if (NULL == pinstance->res_entries) { pmcraid_err("failed to allocate memory for resource table\n"); diff --git a/drivers/scsi/qedi/qedi_main.c b/drivers/scsi/qedi/qedi_main.c index 24b945b555ba..84cbaee810b6 100644 --- a/drivers/scsi/qedi/qedi_main.c +++ b/drivers/scsi/qedi/qedi_main.c @@ -523,7 +523,7 @@ static int qedi_init_id_tbl(struct qedi_portid_tbl *id_tbl, u16 size, id_tbl->max = size; id_tbl->next = next; spin_lock_init(&id_tbl->lock); - id_tbl->table = kzalloc(DIV_ROUND_UP(size, 32) * 4, GFP_KERNEL); + id_tbl->table = kcalloc(DIV_ROUND_UP(size, 32), 4, GFP_KERNEL); if (!id_tbl->table) return -ENOMEM; diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index a66f7cec797c..ca1f4ea70a5a 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -2842,8 +2842,9 @@ qla2x00_alloc_outstanding_cmds(struct qla_hw_data *ha, struct req_que *req) req->num_outstanding_cmds = ha->cur_fw_iocb_count; } - req->outstanding_cmds = kzalloc(sizeof(srb_t *) * - req->num_outstanding_cmds, GFP_KERNEL); + req->outstanding_cmds = kcalloc(req->num_outstanding_cmds, + sizeof(srb_t *), + GFP_KERNEL); if (!req->outstanding_cmds) { /* @@ -2851,8 +2852,9 @@ qla2x00_alloc_outstanding_cmds(struct qla_hw_data *ha, struct req_que *req) * initialization. */ req->num_outstanding_cmds = MIN_OUTSTANDING_COMMANDS; - req->outstanding_cmds = kzalloc(sizeof(srb_t *) * - req->num_outstanding_cmds, GFP_KERNEL); + req->outstanding_cmds = kcalloc(req->num_outstanding_cmds, + sizeof(srb_t *), + GFP_KERNEL); if (!req->outstanding_cmds) { ql_log(ql_log_fatal, NULL, 0x0126, diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index b39faf2bfa0d..f556c8634fd3 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -3395,8 +3395,9 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp) "Adjusted Max no of queues pairs: %d.\n", ha->max_qpairs); } } - ha->msix_entries = kzalloc(sizeof(struct qla_msix_entry) * - ha->msix_count, GFP_KERNEL); + ha->msix_entries = kcalloc(ha->msix_count, + sizeof(struct qla_msix_entry), + GFP_KERNEL); if (!ha->msix_entries) { ql_log(ql_log_fatal, vha, 0x00c8, "Failed to allocate memory for ha->msix_entries.\n"); diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index ea60c6e603c0..f60f87daf2bf 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -399,7 +399,7 @@ static int qla2x00_alloc_queues(struct qla_hw_data *ha, struct req_que *req, struct rsp_que *rsp) { scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev); - ha->req_q_map = kzalloc(sizeof(struct req_que *) * ha->max_req_queues, + ha->req_q_map = kcalloc(ha->max_req_queues, sizeof(struct req_que *), GFP_KERNEL); if (!ha->req_q_map) { ql_log(ql_log_fatal, vha, 0x003b, @@ -407,7 +407,7 @@ static int qla2x00_alloc_queues(struct qla_hw_data *ha, struct req_que *req, goto fail_req_map; } - ha->rsp_q_map = kzalloc(sizeof(struct rsp_que *) * ha->max_rsp_queues, + ha->rsp_q_map = kcalloc(ha->max_rsp_queues, sizeof(struct rsp_que *), GFP_KERNEL); if (!ha->rsp_q_map) { ql_log(ql_log_fatal, vha, 0x003c, @@ -4003,8 +4003,9 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len, (*rsp)->ring); /* Allocate memory for NVRAM data for vports */ if (ha->nvram_npiv_size) { - ha->npiv_info = kzalloc(sizeof(struct qla_npiv_entry) * - ha->nvram_npiv_size, GFP_KERNEL); + ha->npiv_info = kcalloc(ha->nvram_npiv_size, + sizeof(struct qla_npiv_entry), + GFP_KERNEL); if (!ha->npiv_info) { ql_log_pci(ql_log_fatal, ha->pdev, 0x002d, "Failed to allocate memory for npiv_info.\n"); @@ -4038,8 +4039,9 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len, INIT_LIST_HEAD(&ha->vp_list); /* Allocate memory for our loop_id bitmap */ - ha->loop_id_map = kzalloc(BITS_TO_LONGS(LOOPID_MAP_SIZE) * sizeof(long), - GFP_KERNEL); + ha->loop_id_map = kcalloc(BITS_TO_LONGS(LOOPID_MAP_SIZE), + sizeof(long), + GFP_KERNEL); if (!ha->loop_id_map) goto fail_loop_id_map; else { diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 21011c5fddeb..52e28b0f2200 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -6109,8 +6109,9 @@ int qlt_add_target(struct qla_hw_data *ha, struct scsi_qla_host *base_vha) return -ENOMEM; } - tgt->qphints = kzalloc((ha->max_qpairs + 1) * - sizeof(struct qla_qpair_hint), GFP_KERNEL); + tgt->qphints = kcalloc(ha->max_qpairs + 1, + sizeof(struct qla_qpair_hint), + GFP_KERNEL); if (!tgt->qphints) { kfree(tgt); ql_log(ql_log_warn, base_vha, 0x0197, @@ -6916,8 +6917,9 @@ qlt_mem_alloc(struct qla_hw_data *ha) if (!QLA_TGT_MODE_ENABLED()) return 0; - ha->tgt.tgt_vp_map = kzalloc(sizeof(struct qla_tgt_vp_map) * - MAX_MULTI_ID_FABRIC, GFP_KERNEL); + ha->tgt.tgt_vp_map = kcalloc(MAX_MULTI_ID_FABRIC, + sizeof(struct qla_tgt_vp_map), + GFP_KERNEL); if (!ha->tgt.tgt_vp_map) return -ENOMEM; diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index ac936b5ca74e..ec2c5f07d362 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -3164,7 +3164,7 @@ static int resp_comp_write(struct scsi_cmnd *scp, return check_condition_result; } dnum = 2 * num; - arr = kzalloc(dnum * lb_size, GFP_ATOMIC); + arr = kcalloc(lb_size, dnum, GFP_ATOMIC); if (NULL == arr) { mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC, INSUFF_RES_ASCQ); diff --git a/drivers/scsi/ses.c b/drivers/scsi/ses.c index 62f04c0511cf..0fc39224ce1e 100644 --- a/drivers/scsi/ses.c +++ b/drivers/scsi/ses.c @@ -747,7 +747,7 @@ static int ses_intf_add(struct device *cdev, buf = NULL; } page2_not_supported: - scomp = kzalloc(sizeof(struct ses_component) * components, GFP_KERNEL); + scomp = kcalloc(components, sizeof(struct ses_component), GFP_KERNEL); if (!scomp) goto err_free; diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 633e4beaf7cb..e16e48ae1b57 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -1095,7 +1095,7 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) else { sg_req_info_t *rinfo; - rinfo = kzalloc(SZ_SG_REQ_INFO * SG_MAX_QUEUE, + rinfo = kcalloc(SG_MAX_QUEUE, SZ_SG_REQ_INFO, GFP_KERNEL); if (!rinfo) return -ENOMEM; diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c index 01e74d499735..9fdbafe69230 100644 --- a/drivers/scsi/smartpqi/smartpqi_init.c +++ b/drivers/scsi/smartpqi/smartpqi_init.c @@ -4297,8 +4297,9 @@ static int pqi_alloc_io_resources(struct pqi_ctrl_info *ctrl_info) struct device *dev; struct pqi_io_request *io_request; - ctrl_info->io_request_pool = kzalloc(ctrl_info->max_io_slots * - sizeof(ctrl_info->io_request_pool[0]), GFP_KERNEL); + ctrl_info->io_request_pool = kcalloc(ctrl_info->max_io_slots, + sizeof(ctrl_info->io_request_pool[0]), + GFP_KERNEL); if (!ctrl_info->io_request_pool) { dev_err(&ctrl_info->pci_dev->dev, diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 56c0eefa1cfc..481fd71e824f 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -3888,7 +3888,7 @@ static struct st_buffer *new_tape_buffer(int need_dma, int max_sg) tb->dma = need_dma; tb->buffer_size = 0; - tb->reserved_pages = kzalloc(max_sg * sizeof(struct page *), + tb->reserved_pages = kcalloc(max_sg, sizeof(struct page *), GFP_ATOMIC); if (!tb->reserved_pages) { kfree(tb); diff --git a/drivers/scsi/ufs/ufs-debugfs.c b/drivers/scsi/ufs/ufs-debugfs.c index d686f0a304fb..f8a9abac88a5 100644 --- a/drivers/scsi/ufs/ufs-debugfs.c +++ b/drivers/scsi/ufs/ufs-debugfs.c @@ -803,13 +803,13 @@ static int ufshcd_init_statistics(struct ufs_hba *hba) int i; stats->enabled = false; - stats->tag_stats = kzalloc(sizeof(*stats->tag_stats) * hba->nutrs, - GFP_KERNEL); + stats->tag_stats = kcalloc(hba->nutrs, sizeof(*stats->tag_stats), + GFP_KERNEL); if (!hba->ufs_stats.tag_stats) goto no_mem; - stats->tag_stats[0] = kzalloc(sizeof(**stats->tag_stats) * - TS_NUM_STATS * hba->nutrs, GFP_KERNEL); + stats->tag_stats[0] = kzalloc(array3_size(sizeof(**stats->tag_stats), TS_NUM_STATS, hba->nutrs), + GFP_KERNEL); if (!stats->tag_stats[0]) goto no_mem; diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index a6109d43b4a1..bce6a4175eab 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -682,8 +682,9 @@ static void ufshcd_cmd_log_init(struct ufs_hba *hba) { /* Allocate log entries */ if (!hba->cmd_log.entries) { - hba->cmd_log.entries = kzalloc(UFSHCD_MAX_CMD_LOGGING * - sizeof(struct ufshcd_cmd_log_entry), GFP_KERNEL); + hba->cmd_log.entries = kcalloc(UFSHCD_MAX_CMD_LOGGING, + sizeof(struct ufshcd_cmd_log_entry), + GFP_KERNEL); if (!hba->cmd_log.entries) return; dev_dbg(hba->dev, "%s: cmd_log.entries initialized\n", diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c index 7442bc130055..eeb028b9cdb3 100644 --- a/drivers/sh/clk/cpg.c +++ b/drivers/sh/clk/cpg.c @@ -249,7 +249,7 @@ static int __init sh_clk_div_register_ops(struct clk *clks, int nr, int k; freq_table_size *= (nr_divs + 1); - freq_table = kzalloc(freq_table_size * nr, GFP_KERNEL); + freq_table = kcalloc(nr, freq_table_size, GFP_KERNEL); if (!freq_table) { pr_err("%s: unable to alloc memory\n", __func__); return -ENOMEM; diff --git a/drivers/sh/intc/core.c b/drivers/sh/intc/core.c index 8e72bcbd3d6d..46f0f322d4d8 100644 --- a/drivers/sh/intc/core.c +++ b/drivers/sh/intc/core.c @@ -203,7 +203,7 @@ int __init register_intc_controller(struct intc_desc *desc) if (desc->num_resources) { d->nr_windows = desc->num_resources; - d->window = kzalloc(d->nr_windows * sizeof(*d->window), + d->window = kcalloc(d->nr_windows, sizeof(*d->window), GFP_NOWAIT); if (!d->window) goto err1; @@ -230,12 +230,12 @@ int __init register_intc_controller(struct intc_desc *desc) d->nr_reg += hw->ack_regs ? hw->nr_ack_regs : 0; d->nr_reg += hw->subgroups ? hw->nr_subgroups : 0; - d->reg = kzalloc(d->nr_reg * sizeof(*d->reg), GFP_NOWAIT); + d->reg = kcalloc(d->nr_reg, sizeof(*d->reg), GFP_NOWAIT); if (!d->reg) goto err2; #ifdef CONFIG_SMP - d->smp = kzalloc(d->nr_reg * sizeof(*d->smp), GFP_NOWAIT); + d->smp = kcalloc(d->nr_reg, sizeof(*d->smp), GFP_NOWAIT); if (!d->smp) goto err3; #endif @@ -253,7 +253,7 @@ int __init register_intc_controller(struct intc_desc *desc) } if (hw->prio_regs) { - d->prio = kzalloc(hw->nr_vectors * sizeof(*d->prio), + d->prio = kcalloc(hw->nr_vectors, sizeof(*d->prio), GFP_NOWAIT); if (!d->prio) goto err4; @@ -269,7 +269,7 @@ int __init register_intc_controller(struct intc_desc *desc) } if (hw->sense_regs) { - d->sense = kzalloc(hw->nr_vectors * sizeof(*d->sense), + d->sense = kcalloc(hw->nr_vectors, sizeof(*d->sense), GFP_NOWAIT); if (!d->sense) goto err5; diff --git a/drivers/sh/maple/maple.c b/drivers/sh/maple/maple.c index bec81c2404f7..040ba4777d63 100644 --- a/drivers/sh/maple/maple.c +++ b/drivers/sh/maple/maple.c @@ -161,7 +161,7 @@ int maple_add_packet(struct maple_device *mdev, u32 function, u32 command, void *sendbuf = NULL; if (length) { - sendbuf = kzalloc(length * 4, GFP_KERNEL); + sendbuf = kcalloc(length, 4, GFP_KERNEL); if (!sendbuf) { ret = -ENOMEM; goto out; diff --git a/drivers/slimbus/slim-msm-ctrl.c b/drivers/slimbus/slim-msm-ctrl.c index 3f99b2bc0f78..02e032cf293d 100644 --- a/drivers/slimbus/slim-msm-ctrl.c +++ b/drivers/slimbus/slim-msm-ctrl.c @@ -838,9 +838,9 @@ static void slim_sat_rxprocess(struct work_struct *work) continue; } /* Satellite-channels */ - sat->satch = kzalloc(MSM_MAX_SATCH * - sizeof(struct msm_sat_chan), - GFP_KERNEL); + sat->satch = kcalloc(MSM_MAX_SATCH, + sizeof(struct msm_sat_chan), + GFP_KERNEL); send_capability: txn.mc = SLIM_USR_MC_MASTER_CAPABILITY; txn.mt = SLIM_MSG_MT_SRC_REFERRED_USER; @@ -1198,7 +1198,7 @@ static int msm_slim_probe(struct platform_device *pdev) ret = -ENOMEM; goto err_get_res_failed; } - dev->wr_comp = kzalloc(sizeof(struct completion *) * MSM_TX_BUFS, + dev->wr_comp = kcalloc(MSM_TX_BUFS, sizeof(struct completion *), GFP_KERNEL); if (!dev->wr_comp) return -ENOMEM; diff --git a/drivers/slimbus/slim-msm-ngd.c b/drivers/slimbus/slim-msm-ngd.c index 681e244def0d..bdbc089e7a58 100644 --- a/drivers/slimbus/slim-msm-ngd.c +++ b/drivers/slimbus/slim-msm-ngd.c @@ -1794,7 +1794,7 @@ static int ngd_slim_probe(struct platform_device *pdev) dev_err(&pdev->dev, "no memory for MSM slimbus controller\n"); return PTR_ERR(dev); } - dev->wr_comp = kzalloc(sizeof(struct completion *) * MSM_TX_BUFS, + dev->wr_comp = kcalloc(MSM_TX_BUFS, sizeof(struct completion *), GFP_KERNEL); if (!dev->wr_comp) { ret = -ENOMEM; diff --git a/drivers/soc/qcom/msm_bus/msm_bus_arb_adhoc.c b/drivers/soc/qcom/msm_bus/msm_bus_arb_adhoc.c index a96b55cab9fb..731fa98d9ee8 100644 --- a/drivers/soc/qcom/msm_bus/msm_bus_arb_adhoc.c +++ b/drivers/soc/qcom/msm_bus/msm_bus_arb_adhoc.c @@ -916,8 +916,9 @@ static int alloc_handle_lst(int size) struct msm_bus_client **t_cl_list; if (!handle_list.num_entries) { - t_cl_list = kzalloc(sizeof(struct msm_bus_client *) - * NUM_CL_HANDLES, GFP_KERNEL); + t_cl_list = kcalloc(NUM_CL_HANDLES, + sizeof(struct msm_bus_client *), + GFP_KERNEL); if (ZERO_OR_NULL_PTR(t_cl_list)) { ret = -ENOMEM; MSM_BUS_ERR("%s: Failed to allocate handles list", diff --git a/drivers/soc/qcom/msm_bus/msm_bus_arb_rpmh.c b/drivers/soc/qcom/msm_bus/msm_bus_arb_rpmh.c index d376f14e7dd4..a64a294e0e8c 100644 --- a/drivers/soc/qcom/msm_bus/msm_bus_arb_rpmh.c +++ b/drivers/soc/qcom/msm_bus/msm_bus_arb_rpmh.c @@ -1165,8 +1165,9 @@ static int alloc_handle_lst(int size) struct msm_bus_client **t_cl_list; if (!handle_list.num_entries) { - t_cl_list = kzalloc(sizeof(struct msm_bus_client *) - * NUM_CL_HANDLES, GFP_KERNEL); + t_cl_list = kcalloc(NUM_CL_HANDLES, + sizeof(struct msm_bus_client *), + GFP_KERNEL); if (ZERO_OR_NULL_PTR(t_cl_list)) { ret = -ENOMEM; MSM_BUS_ERR("%s: Failed to allocate handles list", diff --git a/drivers/soc/qcom/rpmh.c b/drivers/soc/qcom/rpmh.c index d18d9a925bfd..2325f259bd50 100644 --- a/drivers/soc/qcom/rpmh.c +++ b/drivers/soc/qcom/rpmh.c @@ -1024,8 +1024,8 @@ static struct rpmh_mbox *get_mbox(struct platform_device *pdev, rpmh = &mbox_ctrlr[i]; - rpmh->msg_pool = kzalloc(sizeof(struct rpmh_msg) * - RPMH_MAX_FAST_RES, GFP_KERNEL); + rpmh->msg_pool = kcalloc(RPMH_MAX_FAST_RES, sizeof(struct rpmh_msg), + GFP_KERNEL); if (!rpmh->msg_pool) { of_node_put(spec.np); return ERR_PTR(-ENOMEM); diff --git a/drivers/soc/qcom/spcom.c b/drivers/soc/qcom/spcom.c index 64fb72f8a393..25d56591830c 100644 --- a/drivers/soc/qcom/spcom.c +++ b/drivers/soc/qcom/spcom.c @@ -2072,7 +2072,7 @@ static int spcom_register_rpmsg_drv(struct spcom_channel *ch) return -ENOMEM; /* zalloc array of two to NULL terminate the match list */ - match = kzalloc(2 * sizeof(*match), GFP_KERNEL); + match = kcalloc(2, sizeof(*match), GFP_KERNEL); if (!match) { kfree(rpdrv); return -ENOMEM; diff --git a/drivers/staging/ccree/ssi_sysfs.c b/drivers/staging/ccree/ssi_sysfs.c index 0655658bba4d..f7e0c5024a29 100644 --- a/drivers/staging/ccree/ssi_sysfs.c +++ b/drivers/staging/ccree/ssi_sysfs.c @@ -376,7 +376,7 @@ static int sys_init_dir(struct sys_dir *sys_dir, struct ssi_drvdata *drvdata, return -ENOMEM; /* allocate memory for directory's attributes list */ sys_dir->sys_dir_attr_list = - kzalloc(sizeof(struct attribute *) * (num_of_attrs + 1), + kcalloc(num_of_attrs + 1, sizeof(struct attribute *), GFP_KERNEL); if (!(sys_dir->sys_dir_attr_list)) { diff --git a/drivers/staging/lustre/lustre/obdclass/cl_object.c b/drivers/staging/lustre/lustre/obdclass/cl_object.c index 95c7fa3b532c..28cb84890614 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_object.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_object.c @@ -1016,7 +1016,7 @@ int cl_global_init(void) { int result; - cl_envs = kzalloc(sizeof(*cl_envs) * num_possible_cpus(), GFP_KERNEL); + cl_envs = kcalloc(num_possible_cpus(), sizeof(*cl_envs), GFP_KERNEL); if (!cl_envs) { result = -ENOMEM; goto out; diff --git a/drivers/staging/media/atomisp/pci/atomisp2/atomisp_compat_css20.c b/drivers/staging/media/atomisp/pci/atomisp2/atomisp_compat_css20.c index 05897b747349..7ae2478fecc8 100644 --- a/drivers/staging/media/atomisp/pci/atomisp2/atomisp_compat_css20.c +++ b/drivers/staging/media/atomisp/pci/atomisp2/atomisp_compat_css20.c @@ -4331,8 +4331,8 @@ int atomisp_css_create_acc_pipe(struct atomisp_sub_device *asd) pipe_config = &stream_env->pipe_configs[CSS_PIPE_ID_ACC]; ia_css_pipe_config_defaults(pipe_config); - asd->acc.acc_stages = kzalloc(MAX_ACC_STAGES * - sizeof(void *), GFP_KERNEL); + asd->acc.acc_stages = kcalloc(MAX_ACC_STAGES, sizeof(void *), + GFP_KERNEL); if (!asd->acc.acc_stages) return -ENOMEM; pipe_config->acc_stages = asd->acc.acc_stages; diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css_firmware.c b/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css_firmware.c index 06f13e55e9d1..2150a650aa84 100644 --- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css_firmware.c +++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css_firmware.c @@ -235,7 +235,8 @@ sh_css_load_firmware(const char *fw_data, sh_css_blob_info = NULL; } - fw_minibuffer = kzalloc(sh_css_num_binaries * sizeof(struct fw_param), GFP_KERNEL); + fw_minibuffer = kcalloc(sh_css_num_binaries, sizeof(struct fw_param), + GFP_KERNEL); if (fw_minibuffer == NULL) return IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; diff --git a/drivers/staging/rtlwifi/efuse.c b/drivers/staging/rtlwifi/efuse.c index 6d5e657017c6..711d9ef8908b 100644 --- a/drivers/staging/rtlwifi/efuse.c +++ b/drivers/staging/rtlwifi/efuse.c @@ -248,15 +248,15 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) } /* allocate memory for efuse_tbl and efuse_word */ - efuse_tbl = kzalloc(rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE] * - sizeof(u8), GFP_ATOMIC); + efuse_tbl = kzalloc(rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE], + GFP_ATOMIC); if (!efuse_tbl) return; - efuse_word = kzalloc(EFUSE_MAX_WORD_UNIT * sizeof(u16 *), GFP_ATOMIC); + efuse_word = kcalloc(EFUSE_MAX_WORD_UNIT, sizeof(u16 *), GFP_ATOMIC); if (!efuse_word) goto out; for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) { - efuse_word[i] = kzalloc(efuse_max_section * sizeof(u16), + efuse_word[i] = kcalloc(efuse_max_section, sizeof(u16), GFP_ATOMIC); if (!efuse_word[i]) goto done; diff --git a/drivers/staging/unisys/visorhba/visorhba_main.c b/drivers/staging/unisys/visorhba/visorhba_main.c index 419dba89af06..6eb3ba56937d 100644 --- a/drivers/staging/unisys/visorhba/visorhba_main.c +++ b/drivers/staging/unisys/visorhba/visorhba_main.c @@ -873,7 +873,7 @@ static void do_scsi_nolinuxstat(struct uiscmdrsp *cmdrsp, if (cmdrsp->scsi.no_disk_result == 0) return; - buf = kzalloc(sizeof(char) * 36, GFP_KERNEL); + buf = kzalloc(36, GFP_KERNEL); if (!buf) return; diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 0d0be7d8b9d6..4b41a3a4412c 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -251,7 +251,7 @@ int transport_alloc_session_tags(struct se_session *se_sess, { int rc; - se_sess->sess_cmd_map = kzalloc(tag_num * tag_size, + se_sess->sess_cmd_map = kcalloc(tag_size, tag_num, GFP_KERNEL | __GFP_NOWARN | __GFP_RETRY_MAYFAIL); if (!se_sess->sess_cmd_map) { se_sess->sess_cmd_map = vzalloc(tag_num * tag_size); diff --git a/drivers/thermal/int340x_thermal/acpi_thermal_rel.c b/drivers/thermal/int340x_thermal/acpi_thermal_rel.c index c719167e9f28..45e7e5cbdffb 100644 --- a/drivers/thermal/int340x_thermal/acpi_thermal_rel.c +++ b/drivers/thermal/int340x_thermal/acpi_thermal_rel.c @@ -96,7 +96,7 @@ int acpi_parse_trt(acpi_handle handle, int *trt_count, struct trt **trtp, } *trt_count = p->package.count; - trts = kzalloc(*trt_count * sizeof(struct trt), GFP_KERNEL); + trts = kcalloc(*trt_count, sizeof(struct trt), GFP_KERNEL); if (!trts) { result = -ENOMEM; goto end; @@ -178,7 +178,7 @@ int acpi_parse_art(acpi_handle handle, int *art_count, struct art **artp, /* ignore p->package.elements[0], as this is _ART Revision field */ *art_count = p->package.count - 1; - arts = kzalloc(*art_count * sizeof(struct art), GFP_KERNEL); + arts = kcalloc(*art_count, sizeof(struct art), GFP_KERNEL); if (!arts) { result = -ENOMEM; goto end; diff --git a/drivers/thermal/int340x_thermal/int340x_thermal_zone.c b/drivers/thermal/int340x_thermal/int340x_thermal_zone.c index 145a5c53ff5c..8a11162eab2a 100644 --- a/drivers/thermal/int340x_thermal/int340x_thermal_zone.c +++ b/drivers/thermal/int340x_thermal/int340x_thermal_zone.c @@ -239,9 +239,9 @@ struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *adev, if (ACPI_FAILURE(status)) trip_cnt = 0; else { - int34x_thermal_zone->aux_trips = kzalloc( - sizeof(*int34x_thermal_zone->aux_trips) * - trip_cnt, GFP_KERNEL); + int34x_thermal_zone->aux_trips = kcalloc(trip_cnt, + sizeof(*int34x_thermal_zone->aux_trips), + GFP_KERNEL); if (!int34x_thermal_zone->aux_trips) { ret = -ENOMEM; goto err_trip_alloc; diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c index 6925765f0e2c..f7fc624933e9 100644 --- a/drivers/thermal/of-thermal.c +++ b/drivers/thermal/of-thermal.c @@ -1360,7 +1360,7 @@ __init *thermal_of_build_thermal_zone(struct device_node *np) if (tz->ntrips == 0) /* must have at least one child */ goto finish; - tz->trips = kzalloc(tz->ntrips * sizeof(*tz->trips), GFP_KERNEL); + tz->trips = kcalloc(tz->ntrips, sizeof(*tz->trips), GFP_KERNEL); if (!tz->trips) { ret = -ENOMEM; goto free_tz; @@ -1386,7 +1386,7 @@ __init *thermal_of_build_thermal_zone(struct device_node *np) if (tz->num_tbps == 0) goto finish; - tz->tbps = kzalloc(tz->num_tbps * sizeof(*tz->tbps), GFP_KERNEL); + tz->tbps = kcalloc(tz->num_tbps, sizeof(*tz->tbps), GFP_KERNEL); if (!tz->tbps) { ret = -ENOMEM; goto free_trips; diff --git a/drivers/thermal/qcom/lmh_dbg.c b/drivers/thermal/qcom/lmh_dbg.c index 00e32c235eac..0fd8b36f4315 100644 --- a/drivers/thermal/qcom/lmh_dbg.c +++ b/drivers/thermal/qcom/lmh_dbg.c @@ -198,8 +198,8 @@ static int lmh_parse_and_extract(const char __user *user_buf, size_t count, ret = -EINVAL; goto dfs_cfg_write_exit; } - config_buf = kzalloc((++data_ct) * sizeof(uint32_t), - GFP_KERNEL); + config_buf = kcalloc(++data_ct, sizeof(uint32_t), + GFP_KERNEL); if (!config_buf) { ret = -ENOMEM; goto dfs_cfg_write_exit; diff --git a/drivers/thermal/x86_pkg_temp_thermal.c b/drivers/thermal/x86_pkg_temp_thermal.c index d93eee2f101b..a4001e08bd32 100644 --- a/drivers/thermal/x86_pkg_temp_thermal.c +++ b/drivers/thermal/x86_pkg_temp_thermal.c @@ -516,7 +516,8 @@ static int __init pkg_temp_thermal_init(void) return -ENODEV; max_packages = topology_max_packages(); - packages = kzalloc(max_packages * sizeof(struct pkg_device *), GFP_KERNEL); + packages = kcalloc(max_packages, sizeof(struct pkg_device *), + GFP_KERNEL); if (!packages) return -ENOMEM; diff --git a/drivers/tty/ehv_bytechan.c b/drivers/tty/ehv_bytechan.c index 5a348efb91ad..f05b92b3be70 100644 --- a/drivers/tty/ehv_bytechan.c +++ b/drivers/tty/ehv_bytechan.c @@ -772,7 +772,7 @@ static int __init ehv_bc_init(void) * array, then you can use pointer math (e.g. "bc - bcs") to get its * tty index. */ - bcs = kzalloc(count * sizeof(struct ehv_bc_data), GFP_KERNEL); + bcs = kcalloc(count, sizeof(struct ehv_bc_data), GFP_KERNEL); if (!bcs) return -ENOMEM; diff --git a/drivers/tty/goldfish.c b/drivers/tty/goldfish.c index 85a500ddbcaa..65a6831d3c74 100644 --- a/drivers/tty/goldfish.c +++ b/drivers/tty/goldfish.c @@ -254,8 +254,9 @@ static int goldfish_tty_create_driver(void) int ret; struct tty_driver *tty; - goldfish_ttys = kzalloc(sizeof(*goldfish_ttys) * - goldfish_tty_line_count, GFP_KERNEL); + goldfish_ttys = kcalloc(goldfish_tty_line_count, + sizeof(*goldfish_ttys), + GFP_KERNEL); if (goldfish_ttys == NULL) { ret = -ENOMEM; goto err_alloc_goldfish_ttys_failed; diff --git a/drivers/tty/hvc/hvc_iucv.c b/drivers/tty/hvc/hvc_iucv.c index a74680729825..2af1e5751bd6 100644 --- a/drivers/tty/hvc/hvc_iucv.c +++ b/drivers/tty/hvc/hvc_iucv.c @@ -1252,7 +1252,7 @@ static int hvc_iucv_setup_filter(const char *val) if (size > MAX_VMID_FILTER) return -ENOSPC; - array = kzalloc(size * 8, GFP_KERNEL); + array = kcalloc(size, 8, GFP_KERNEL); if (!array) return -ENOMEM; diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 15ddcbd1f9d2..dbca9b901fb5 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -1005,7 +1005,7 @@ static unsigned int dma_handle_tx(struct eg20t_port *priv) priv->tx_dma_use = 1; - priv->sg_tx_p = kzalloc(sizeof(struct scatterlist)*num, GFP_ATOMIC); + priv->sg_tx_p = kcalloc(num, sizeof(struct scatterlist), GFP_ATOMIC); if (!priv->sg_tx_p) { dev_err(priv->port.dev, "%s:kzalloc Failed\n", __func__); return 0; diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index dbec0f6063f8..c357d49e087e 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -2506,7 +2506,7 @@ int uart_register_driver(struct uart_driver *drv) * Maybe we should be using a slab cache for this, especially if * we have a large number of ports to handle. */ - drv->state = kzalloc(sizeof(struct uart_state) * drv->nr, GFP_KERNEL); + drv->state = kcalloc(drv->nr, sizeof(struct uart_state), GFP_KERNEL); if (!drv->state) goto out; diff --git a/drivers/tty/serial/sunsab.c b/drivers/tty/serial/sunsab.c index 653a076d89d3..fbb8afe4a71f 100644 --- a/drivers/tty/serial/sunsab.c +++ b/drivers/tty/serial/sunsab.c @@ -1124,8 +1124,9 @@ static int __init sunsab_init(void) } if (num_channels) { - sunsab_ports = kzalloc(sizeof(struct uart_sunsab_port) * - num_channels, GFP_KERNEL); + sunsab_ports = kcalloc(num_channels, + sizeof(struct uart_sunsab_port), + GFP_KERNEL); if (!sunsab_ports) return -ENOMEM; diff --git a/drivers/uio/uio_pruss.c b/drivers/uio/uio_pruss.c index 31d5b1d3b5af..91aea8823af5 100644 --- a/drivers/uio/uio_pruss.c +++ b/drivers/uio/uio_pruss.c @@ -129,7 +129,7 @@ static int pruss_probe(struct platform_device *pdev) if (!gdev) return -ENOMEM; - gdev->info = kzalloc(sizeof(*p) * MAX_PRUSS_EVT, GFP_KERNEL); + gdev->info = kcalloc(MAX_PRUSS_EVT, sizeof(*p), GFP_KERNEL); if (!gdev->info) { kfree(gdev); return -ENOMEM; diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index b71409a0e6b0..c3df4079f3cb 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1404,7 +1404,7 @@ static int hub_configure(struct usb_hub *hub, dev_info(hub_dev, "%d port%s detected\n", maxchild, (maxchild == 1) ? "" : "s"); - hub->ports = kzalloc(maxchild * sizeof(struct usb_port *), GFP_KERNEL); + hub->ports = kcalloc(maxchild, sizeof(struct usb_port *), GFP_KERNEL); if (!hub->ports) { ret = -ENOMEM; goto fail; diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c index e6f8825835b0..376ab024330d 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c @@ -5184,13 +5184,14 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg) dev_dbg(hsotg->dev, "hcfg=%08x\n", hcfg); #ifdef CONFIG_USB_DWC2_TRACK_MISSED_SOFS - hsotg->frame_num_array = kzalloc(sizeof(*hsotg->frame_num_array) * - FRAME_NUM_ARRAY_SIZE, GFP_KERNEL); + hsotg->frame_num_array = kcalloc(FRAME_NUM_ARRAY_SIZE, + sizeof(*hsotg->frame_num_array), + GFP_KERNEL); if (!hsotg->frame_num_array) goto error1; - hsotg->last_frame_num_array = kzalloc( - sizeof(*hsotg->last_frame_num_array) * - FRAME_NUM_ARRAY_SIZE, GFP_KERNEL); + hsotg->last_frame_num_array = kcalloc(FRAME_NUM_ARRAY_SIZE, + sizeof(*hsotg->last_frame_num_array), + GFP_KERNEL); if (!hsotg->last_frame_num_array) goto error1; #endif diff --git a/drivers/usb/gadget/function/f_cdev.c b/drivers/usb/gadget/function/f_cdev.c index 2451aab593ba..be24a8c83acf 100644 --- a/drivers/usb/gadget/function/f_cdev.c +++ b/drivers/usb/gadget/function/f_cdev.c @@ -1990,7 +1990,7 @@ static ssize_t usb_cser_status_show(struct config_item *item, char *page) int temp = 0; int ret; - buf = kzalloc(sizeof(char) * 512, GFP_KERNEL); + buf = kzalloc(512, GFP_KERNEL); if (!buf) return -ENOMEM; diff --git a/drivers/usb/gadget/udc/bdc/bdc_ep.c b/drivers/usb/gadget/udc/bdc/bdc_ep.c index be9f40bc9c12..642f7912f6de 100644 --- a/drivers/usb/gadget/udc/bdc/bdc_ep.c +++ b/drivers/usb/gadget/udc/bdc/bdc_ep.c @@ -143,9 +143,9 @@ static int ep_bd_list_alloc(struct bdc_ep *ep) __func__, ep, num_tabs); /* Allocate memory for table array */ - ep->bd_list.bd_table_array = kzalloc( - num_tabs * sizeof(struct bd_table *), - GFP_ATOMIC); + ep->bd_list.bd_table_array = kcalloc(num_tabs, + sizeof(struct bd_table *), + GFP_ATOMIC); if (!ep->bd_list.bd_table_array) return -ENOMEM; diff --git a/drivers/usb/gadget/udc/fsl_udc_core.c b/drivers/usb/gadget/udc/fsl_udc_core.c index ee48c7938d61..dfacd20c4ee3 100644 --- a/drivers/usb/gadget/udc/fsl_udc_core.c +++ b/drivers/usb/gadget/udc/fsl_udc_core.c @@ -2263,7 +2263,7 @@ static int struct_udc_setup(struct fsl_udc *udc, pdata = dev_get_platdata(&pdev->dev); udc->phy_mode = pdata->phy_mode; - udc->eps = kzalloc(sizeof(struct fsl_ep) * udc->max_ep, GFP_KERNEL); + udc->eps = kcalloc(udc->max_ep, sizeof(struct fsl_ep), GFP_KERNEL); if (!udc->eps) return -1; diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index fb4f104d5830..e04edb71fa43 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -130,8 +130,9 @@ static struct ehci_tt *find_tt(struct usb_device *udev) if (utt->multi) { tt_index = utt->hcpriv; if (!tt_index) { /* Create the index array */ - tt_index = kzalloc(utt->hub->maxchild * - sizeof(*tt_index), GFP_ATOMIC); + tt_index = kcalloc(utt->hub->maxchild, + sizeof(*tt_index), + GFP_ATOMIC); if (!tt_index) return ERR_PTR(-ENOMEM); utt->hcpriv = tt_index; diff --git a/drivers/usb/host/imx21-hcd.c b/drivers/usb/host/imx21-hcd.c index 39ae7fb64b6f..f7b08280ab11 100644 --- a/drivers/usb/host/imx21-hcd.c +++ b/drivers/usb/host/imx21-hcd.c @@ -754,8 +754,8 @@ static int imx21_hc_urb_enqueue_isoc(struct usb_hcd *hcd, if (urb_priv == NULL) return -ENOMEM; - urb_priv->isoc_td = kzalloc( - sizeof(struct td) * urb->number_of_packets, mem_flags); + urb_priv->isoc_td = kcalloc(urb->number_of_packets, sizeof(struct td), + mem_flags); if (urb_priv->isoc_td == NULL) { ret = -ENOMEM; goto alloc_td_failed; diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 7cbf6275055b..55e3b85c3875 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -646,9 +646,9 @@ struct xhci_stream_info *xhci_alloc_stream_info(struct xhci_hcd *xhci, stream_info->num_stream_ctxs = num_stream_ctxs; /* Initialize the array of virtual pointers to stream rings. */ - stream_info->stream_rings = kzalloc( - sizeof(struct xhci_ring *)*num_streams, - mem_flags); + stream_info->stream_rings = kcalloc(num_streams, + sizeof(struct xhci_ring *), + mem_flags); if (!stream_info->stream_rings) goto cleanup_info; @@ -1670,7 +1670,7 @@ static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags) if (!xhci->scratchpad->sp_array) goto fail_sp2; - xhci->scratchpad->sp_buffers = kzalloc(sizeof(void *) * num_sp, flags); + xhci->scratchpad->sp_buffers = kcalloc(num_sp, sizeof(void *), flags); if (!xhci->scratchpad->sp_buffers) goto fail_sp3; @@ -2313,11 +2313,12 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags) u32 cap_start; num_ports = HCS_MAX_PORTS(xhci->hcs_params1); - xhci->port_array = kzalloc(sizeof(*xhci->port_array)*num_ports, flags); + xhci->port_array = kcalloc(num_ports, sizeof(*xhci->port_array), + flags); if (!xhci->port_array) return -ENOMEM; - xhci->rh_bw = kzalloc(sizeof(*xhci->rh_bw)*num_ports, flags); + xhci->rh_bw = kcalloc(num_ports, sizeof(*xhci->rh_bw), flags); if (!xhci->rh_bw) return -ENOMEM; for (i = 0; i < num_ports; i++) { @@ -2344,7 +2345,7 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags) XHCI_EXT_CAPS_PROTOCOL); } - xhci->ext_caps = kzalloc(sizeof(*xhci->ext_caps) * cap_count, flags); + xhci->ext_caps = kcalloc(cap_count, sizeof(*xhci->ext_caps), flags); if (!xhci->ext_caps) return -ENOMEM; diff --git a/drivers/usb/misc/diag_bridge.c b/drivers/usb/misc/diag_bridge.c index 5a0dc78be31f..2bb5f3403a25 100644 --- a/drivers/usb/misc/diag_bridge.c +++ b/drivers/usb/misc/diag_bridge.c @@ -389,7 +389,7 @@ static ssize_t diag_read_stats(struct file *file, char __user *ubuf, char *buf; int i, ret = 0; - buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL); + buf = kzalloc(DEBUG_BUF_SIZE, GFP_KERNEL); if (!buf) return -ENOMEM; diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c index 156aebf62e61..9d1ac043fdfe 100644 --- a/drivers/usb/mon/mon_bin.c +++ b/drivers/usb/mon/mon_bin.c @@ -1024,7 +1024,8 @@ static long mon_bin_ioctl(struct file *file, unsigned int cmd, unsigned long arg return -EINVAL; size = CHUNK_ALIGN(arg); - vec = kzalloc(sizeof(struct mon_pgmap) * (size / CHUNK_SIZE), GFP_KERNEL); + vec = kcalloc(size / CHUNK_SIZE, sizeof(struct mon_pgmap), + GFP_KERNEL); if (vec == NULL) { ret = -ENOMEM; break; diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index b27f2135b66d..17d574896a05 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c @@ -1095,7 +1095,7 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv) if (!gpriv) return -ENOMEM; - uep = kzalloc(sizeof(struct usbhsg_uep) * pipe_size, GFP_KERNEL); + uep = kcalloc(pipe_size, sizeof(struct usbhsg_uep), GFP_KERNEL); if (!uep) { ret = -ENOMEM; goto usbhs_mod_gadget_probe_err_gpriv; diff --git a/drivers/usb/renesas_usbhs/pipe.c b/drivers/usb/renesas_usbhs/pipe.c index 98ed6fcacd36..3c61d3ec2c10 100644 --- a/drivers/usb/renesas_usbhs/pipe.c +++ b/drivers/usb/renesas_usbhs/pipe.c @@ -818,7 +818,8 @@ int usbhs_pipe_probe(struct usbhs_priv *priv) return -EINVAL; } - info->pipe = kzalloc(sizeof(struct usbhs_pipe) * pipe_size, GFP_KERNEL); + info->pipe = kcalloc(pipe_size, sizeof(struct usbhs_pipe), + GFP_KERNEL); if (!info->pipe) return -ENOMEM; diff --git a/drivers/usb/wusbcore/wa-rpipe.c b/drivers/usb/wusbcore/wa-rpipe.c index c7ecdbe19a32..ebf0a40d2ea5 100644 --- a/drivers/usb/wusbcore/wa-rpipe.c +++ b/drivers/usb/wusbcore/wa-rpipe.c @@ -484,7 +484,8 @@ error: int wa_rpipes_create(struct wahc *wa) { wa->rpipes = le16_to_cpu(wa->wa_descr->wNumRPipes); - wa->rpipe_bm = kzalloc(BITS_TO_LONGS(wa->rpipes)*sizeof(unsigned long), + wa->rpipe_bm = kcalloc(BITS_TO_LONGS(wa->rpipes), + sizeof(unsigned long), GFP_KERNEL); if (wa->rpipe_bm == NULL) return -ENOMEM; diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c index d3e90a2f7ebc..57cea5a891dc 100644 --- a/drivers/vhost/scsi.c +++ b/drivers/vhost/scsi.c @@ -1722,22 +1722,25 @@ static int vhost_scsi_nexus_cb(struct se_portal_group *se_tpg, for (i = 0; i < VHOST_SCSI_DEFAULT_TAGS; i++) { tv_cmd = &((struct vhost_scsi_cmd *)se_sess->sess_cmd_map)[i]; - tv_cmd->tvc_sgl = kzalloc(sizeof(struct scatterlist) * - VHOST_SCSI_PREALLOC_SGLS, GFP_KERNEL); + tv_cmd->tvc_sgl = kcalloc(VHOST_SCSI_PREALLOC_SGLS, + sizeof(struct scatterlist), + GFP_KERNEL); if (!tv_cmd->tvc_sgl) { pr_err("Unable to allocate tv_cmd->tvc_sgl\n"); goto out; } - tv_cmd->tvc_upages = kzalloc(sizeof(struct page *) * - VHOST_SCSI_PREALLOC_UPAGES, GFP_KERNEL); + tv_cmd->tvc_upages = kcalloc(VHOST_SCSI_PREALLOC_UPAGES, + sizeof(struct page *), + GFP_KERNEL); if (!tv_cmd->tvc_upages) { pr_err("Unable to allocate tv_cmd->tvc_upages\n"); goto out; } - tv_cmd->tvc_prot_sgl = kzalloc(sizeof(struct scatterlist) * - VHOST_SCSI_PREALLOC_PROT_SGLS, GFP_KERNEL); + tv_cmd->tvc_prot_sgl = kcalloc(VHOST_SCSI_PREALLOC_PROT_SGLS, + sizeof(struct scatterlist), + GFP_KERNEL); if (!tv_cmd->tvc_prot_sgl) { pr_err("Unable to allocate tv_cmd->tvc_prot_sgl\n"); goto out; diff --git a/drivers/video/console/sticore.c b/drivers/video/console/sticore.c index d1d3796773aa..63884a68bd24 100644 --- a/drivers/video/console/sticore.c +++ b/drivers/video/console/sticore.c @@ -649,7 +649,7 @@ static void *sti_bmode_font_raw(struct sti_cooked_font *f) unsigned char *n, *p, *q; int size = f->raw->bytes_per_char*256+sizeof(struct sti_rom_font); - n = kzalloc(4*size, STI_LOWMEM); + n = kcalloc(4, size, STI_LOWMEM); if (!n) return NULL; p = n + 3; diff --git a/drivers/video/fbdev/bfin_adv7393fb.c b/drivers/video/fbdev/bfin_adv7393fb.c index 542ffaddc6ab..1dccffcc42f5 100644 --- a/drivers/video/fbdev/bfin_adv7393fb.c +++ b/drivers/video/fbdev/bfin_adv7393fb.c @@ -459,7 +459,7 @@ static int bfin_adv7393_fb_probe(struct i2c_client *client, fbdev->info.par = &bfin_par; fbdev->info.flags = FBINFO_DEFAULT; - fbdev->info.pseudo_palette = kzalloc(sizeof(u32) * 16, GFP_KERNEL); + fbdev->info.pseudo_palette = kcalloc(16, sizeof(u32), GFP_KERNEL); if (!fbdev->info.pseudo_palette) { dev_err(&client->dev, "failed to allocate pseudo_palette\n"); ret = -ENOMEM; diff --git a/drivers/video/fbdev/broadsheetfb.c b/drivers/video/fbdev/broadsheetfb.c index 9f9a7bef1ff6..d6ba348deb9f 100644 --- a/drivers/video/fbdev/broadsheetfb.c +++ b/drivers/video/fbdev/broadsheetfb.c @@ -617,7 +617,7 @@ static int broadsheet_spiflash_rewrite_sector(struct broadsheetfb_par *par, int tail_start_addr; int start_sector_addr; - sector_buffer = kzalloc(sizeof(char)*sector_size, GFP_KERNEL); + sector_buffer = kzalloc(sector_size, GFP_KERNEL); if (!sector_buffer) return -ENOMEM; diff --git a/drivers/video/fbdev/core/fbmon.c b/drivers/video/fbdev/core/fbmon.c index b73839c19660..8607439d6932 100644 --- a/drivers/video/fbdev/core/fbmon.c +++ b/drivers/video/fbdev/core/fbmon.c @@ -620,7 +620,7 @@ static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize, int num = 0, i, first = 1; int ver, rev; - mode = kzalloc(50 * sizeof(struct fb_videomode), GFP_KERNEL); + mode = kcalloc(50, sizeof(struct fb_videomode), GFP_KERNEL); if (mode == NULL) return NULL; diff --git a/drivers/video/fbdev/igafb.c b/drivers/video/fbdev/igafb.c index 486f18897414..0d8ee405344b 100644 --- a/drivers/video/fbdev/igafb.c +++ b/drivers/video/fbdev/igafb.c @@ -462,7 +462,7 @@ static int __init igafb_init(void) * one additional region with size == 0. */ - par->mmap_map = kzalloc(4 * sizeof(*par->mmap_map), GFP_ATOMIC); + par->mmap_map = kcalloc(4, sizeof(*par->mmap_map), GFP_ATOMIC); if (!par->mmap_map) { printk("igafb_init: can't alloc mmap_map\n"); iounmap((void *)par->io_base); diff --git a/drivers/video/fbdev/mmp/fb/mmpfb.c b/drivers/video/fbdev/mmp/fb/mmpfb.c index 92279e02dd94..f27697e07c55 100644 --- a/drivers/video/fbdev/mmp/fb/mmpfb.c +++ b/drivers/video/fbdev/mmp/fb/mmpfb.c @@ -493,8 +493,8 @@ static int modes_setup(struct mmpfb_info *fbi) return 0; } /* put videomode list to info structure */ - videomodes = kzalloc(sizeof(struct fb_videomode) * videomode_num, - GFP_KERNEL); + videomodes = kcalloc(videomode_num, sizeof(struct fb_videomode), + GFP_KERNEL); if (!videomodes) { dev_err(fbi->dev, "can't malloc video modes\n"); return -ENOMEM; diff --git a/drivers/video/fbdev/msm/mdss_mdp_pp.c b/drivers/video/fbdev/msm/mdss_mdp_pp.c index 2007ed66e725..4581d2538bb8 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_pp.c +++ b/drivers/video/fbdev/msm/mdss_mdp_pp.c @@ -5620,8 +5620,9 @@ int mdss_mdp_hist_collect(struct mdp_histogram_data *hist) goto hist_collect_exit; } if (pipe_cnt > 1) { - hist_concat = kzalloc(HIST_V_SIZE * pipe_cnt * - sizeof(u32), GFP_KERNEL); + hist_concat = kcalloc(HIST_V_SIZE * pipe_cnt, + sizeof(u32), + GFP_KERNEL); if (!hist_concat) { ret = -ENOMEM; goto hist_collect_exit; diff --git a/drivers/video/fbdev/msm/mdss_mdp_pp_v1_7.c b/drivers/video/fbdev/msm/mdss_mdp_pp_v1_7.c index 5ffa4ad6b692..2ba16c97fcf8 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_pp_v1_7.c +++ b/drivers/video/fbdev/msm/mdss_mdp_pp_v1_7.c @@ -1834,7 +1834,7 @@ static int pp_igc_get_config(char __iomem *base_addr, void *cfg_data, goto exit; } /* Allocate for c0c1 and c2 tables */ - c0c1_data = kzalloc(sz * 2, GFP_KERNEL); + c0c1_data = kcalloc(sz, 2, GFP_KERNEL); if (!c0c1_data) { pr_err("allocation failed for c0c1 size %d\n", sz * 2); ret = -ENOMEM; @@ -1994,9 +1994,8 @@ static int pp_pgc_get_config(char __iomem *base_addr, void *cfg_data, PGC_LUT_ENTRIES); return -EFAULT; } - c0_data = kzalloc(sz * 3, GFP_KERNEL); - if (!c0_data) { - pr_err("memory allocation failure sz %d", sz * 3); + c0_data = kcalloc(sz, 3, GFP_KERNEL); + if (!c0_data) return -ENOMEM; } c1_data = c0_data + PGC_LUT_ENTRIES; diff --git a/drivers/video/fbdev/omap2/omapfb/dss/manager.c b/drivers/video/fbdev/omap2/omapfb/dss/manager.c index 69f86d2cc274..d21c641e1f3c 100644 --- a/drivers/video/fbdev/omap2/omapfb/dss/manager.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/manager.c @@ -42,8 +42,8 @@ int dss_init_overlay_managers(void) num_managers = dss_feat_get_num_mgrs(); - managers = kzalloc(sizeof(struct omap_overlay_manager) * num_managers, - GFP_KERNEL); + managers = kcalloc(num_managers, sizeof(struct omap_overlay_manager), + GFP_KERNEL); BUG_ON(managers == NULL); diff --git a/drivers/video/fbdev/omap2/omapfb/dss/overlay.c b/drivers/video/fbdev/omap2/omapfb/dss/overlay.c index d6c5d75d2ef8..be17a4785a5e 100644 --- a/drivers/video/fbdev/omap2/omapfb/dss/overlay.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/overlay.c @@ -59,8 +59,8 @@ void dss_init_overlays(struct platform_device *pdev) num_overlays = dss_feat_get_num_ovls(); - overlays = kzalloc(sizeof(struct omap_overlay) * num_overlays, - GFP_KERNEL); + overlays = kcalloc(num_overlays, sizeof(struct omap_overlay), + GFP_KERNEL); BUG_ON(overlays == NULL); diff --git a/drivers/video/fbdev/uvesafb.c b/drivers/video/fbdev/uvesafb.c index c592ca513115..440a6636d8f0 100644 --- a/drivers/video/fbdev/uvesafb.c +++ b/drivers/video/fbdev/uvesafb.c @@ -486,8 +486,9 @@ static int uvesafb_vbe_getmodes(struct uvesafb_ktask *task, mode++; } - par->vbe_modes = kzalloc(sizeof(struct vbe_mode_ib) * - par->vbe_modes_cnt, GFP_KERNEL); + par->vbe_modes = kcalloc(par->vbe_modes_cnt, + sizeof(struct vbe_mode_ib), + GFP_KERNEL); if (!par->vbe_modes) return -ENOMEM; @@ -858,7 +859,7 @@ static int uvesafb_vbe_init_mode(struct fb_info *info) * Convert the modelist into a modedb so that we can use it with * fb_find_mode(). */ - mode = kzalloc(i * sizeof(*mode), GFP_KERNEL); + mode = kcalloc(i, sizeof(*mode), GFP_KERNEL); if (mode) { i = 0; list_for_each(pos, &info->modelist) { diff --git a/drivers/video/of_display_timing.c b/drivers/video/of_display_timing.c index 8ce0a99bf17c..684e9ec5985c 100644 --- a/drivers/video/of_display_timing.c +++ b/drivers/video/of_display_timing.c @@ -181,8 +181,9 @@ struct display_timings *of_get_display_timings(const struct device_node *np) goto entryfail; } - disp->timings = kzalloc(sizeof(struct display_timing *) * - disp->num_timings, GFP_KERNEL); + disp->timings = kcalloc(disp->num_timings, + sizeof(struct display_timing *), + GFP_KERNEL); if (!disp->timings) { pr_err("%pOF: could not allocate timings array\n", np); goto entryfail; diff --git a/drivers/virt/fsl_hypervisor.c b/drivers/virt/fsl_hypervisor.c index 2e1678d22f6f..14748bb8b33f 100644 --- a/drivers/virt/fsl_hypervisor.c +++ b/drivers/virt/fsl_hypervisor.c @@ -226,7 +226,7 @@ static long ioctl_memcpy(struct fsl_hv_ioctl_memcpy __user *p) * 'pages' is an array of struct page pointers that's initialized by * get_user_pages(). */ - pages = kzalloc(num_pages * sizeof(struct page *), GFP_KERNEL); + pages = kcalloc(num_pages, sizeof(struct page *), GFP_KERNEL); if (!pages) { pr_debug("fsl-hv: could not allocate page list\n"); return -ENOMEM; diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c index 916c4ad22eee..51527648ff0b 100644 --- a/drivers/virtio/virtio_pci_common.c +++ b/drivers/virtio/virtio_pci_common.c @@ -119,7 +119,7 @@ static int vp_request_msix_vectors(struct virtio_device *vdev, int nvectors, if (!vp_dev->msix_names) goto error; vp_dev->msix_affinity_masks - = kzalloc(nvectors * sizeof *vp_dev->msix_affinity_masks, + = kcalloc(nvectors, sizeof(*vp_dev->msix_affinity_masks), GFP_KERNEL); if (!vp_dev->msix_affinity_masks) goto error; diff --git a/drivers/vservices/devio.c b/drivers/vservices/devio.c index fa716d59e042..f95685e970a0 100644 --- a/drivers/vservices/devio.c +++ b/drivers/vservices/devio.c @@ -816,11 +816,11 @@ vs_devio_check_compat_iov(struct vs_compat_ioctl_iovec *c_io, if (c_io->iovcnt > UIO_MAXIOV) return ERR_PTR(-EINVAL); - c_iov = kzalloc(sizeof(*c_iov) * c_io->iovcnt, GFP_KERNEL); + c_iov = kcalloc(c_io->iovcnt, sizeof(*c_iov), GFP_KERNEL); if (!c_iov) return ERR_PTR(-ENOMEM); - iov = kzalloc(sizeof(*iov) * c_io->iovcnt, GFP_KERNEL); + iov = kcalloc(c_io->iovcnt, sizeof(*iov), GFP_KERNEL); if (!iov) { kfree(c_iov); return ERR_PTR(-ENOMEM); diff --git a/drivers/xen/arm-device.c b/drivers/xen/arm-device.c index 85dd20e05726..3e789c77f568 100644 --- a/drivers/xen/arm-device.c +++ b/drivers/xen/arm-device.c @@ -70,9 +70,9 @@ static int xen_map_device_mmio(const struct resource *resources, if ((resource_type(r) != IORESOURCE_MEM) || (nr == 0)) continue; - gpfns = kzalloc(sizeof(xen_pfn_t) * nr, GFP_KERNEL); - idxs = kzalloc(sizeof(xen_ulong_t) * nr, GFP_KERNEL); - errs = kzalloc(sizeof(int) * nr, GFP_KERNEL); + gpfns = kcalloc(nr, sizeof(xen_pfn_t), GFP_KERNEL); + idxs = kcalloc(nr, sizeof(xen_ulong_t), GFP_KERNEL); + errs = kcalloc(nr, sizeof(int), GFP_KERNEL); if (!gpfns || !idxs || !errs) { kfree(gpfns); kfree(idxs); diff --git a/fs/btrfs/check-integrity.c b/fs/btrfs/check-integrity.c index 4be07cf31d74..42e898b2cf35 100644 --- a/fs/btrfs/check-integrity.c +++ b/fs/btrfs/check-integrity.c @@ -1615,8 +1615,7 @@ static int btrfsic_read_block(struct btrfsic_state *state, num_pages = (block_ctx->len + (u64)PAGE_SIZE - 1) >> PAGE_SHIFT; - block_ctx->mem_to_free = kzalloc((sizeof(*block_ctx->datav) + - sizeof(*block_ctx->pagev)) * + block_ctx->mem_to_free = kcalloc(sizeof(*block_ctx->datav) + sizeof(*block_ctx->pagev), num_pages, GFP_NOFS); if (!block_ctx->mem_to_free) return -ENOMEM; diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index d487b5bc9478..909878ddbb1f 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -598,7 +598,7 @@ int ext4_ext_precache(struct inode *inode) down_read(&ei->i_data_sem); depth = ext_depth(inode); - path = kzalloc(sizeof(struct ext4_ext_path) * (depth + 1), + path = kcalloc(depth + 1, sizeof(struct ext4_ext_path), GFP_NOFS); if (path == NULL) { up_read(&ei->i_data_sem); @@ -906,7 +906,7 @@ ext4_find_extent(struct inode *inode, ext4_lblk_t block, } if (!path) { /* account possible depth increase */ - path = kzalloc(sizeof(struct ext4_ext_path) * (depth + 2), + path = kcalloc(depth + 2, sizeof(struct ext4_ext_path), GFP_NOFS); if (unlikely(!path)) return ERR_PTR(-ENOMEM); @@ -1093,7 +1093,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, * We need this to handle errors and free blocks * upon them. */ - ablocks = kzalloc(sizeof(ext4_fsblk_t) * depth, GFP_NOFS); + ablocks = kcalloc(depth, sizeof(ext4_fsblk_t), GFP_NOFS); if (!ablocks) return -ENOMEM; @@ -2963,7 +2963,7 @@ again: path[k].p_block = le16_to_cpu(path[k].p_hdr->eh_entries)+1; } else { - path = kzalloc(sizeof(struct ext4_ext_path) * (depth + 1), + path = kcalloc(depth + 1, sizeof(struct ext4_ext_path), GFP_NOFS); if (path == NULL) { ext4_journal_stop(handle); diff --git a/fs/ext4/hash.c b/fs/ext4/hash.c index ed76a6d7a2d8..9adcadeceaa9 100644 --- a/fs/ext4/hash.c +++ b/fs/ext4/hash.c @@ -283,7 +283,7 @@ int ext4fs_dirhash(const struct inode *dir, const char *name, int len, struct qstr qstr = {.name = name, .len = len }; if (len && IS_CASEFOLDED(dir) && um) { - buff = kzalloc(sizeof(char) * PATH_MAX, GFP_KERNEL); + buff = kzalloc(PATH_MAX, GFP_KERNEL); if (!buff) return -ENOMEM; diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c index 74f15498c9bf..69be69d93f76 100644 --- a/fs/nfs/flexfilelayout/flexfilelayout.c +++ b/fs/nfs/flexfilelayout/flexfilelayout.c @@ -461,7 +461,7 @@ ff_layout_alloc_lseg(struct pnfs_layout_hdr *lh, fh_count = be32_to_cpup(p); fls->mirror_array[i]->fh_versions = - kzalloc(fh_count * sizeof(struct nfs_fh), + kcalloc(fh_count, sizeof(struct nfs_fh), gfp_flags); if (fls->mirror_array[i]->fh_versions == NULL) { rc = -ENOMEM; diff --git a/fs/nfs/flexfilelayout/flexfilelayoutdev.c b/fs/nfs/flexfilelayout/flexfilelayoutdev.c index 2464b9b80698..8da239b6cc16 100644 --- a/fs/nfs/flexfilelayout/flexfilelayoutdev.c +++ b/fs/nfs/flexfilelayout/flexfilelayoutdev.c @@ -99,7 +99,8 @@ nfs4_ff_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev, version_count = be32_to_cpup(p); dprintk("%s: version count %d\n", __func__, version_count); - ds_versions = kzalloc(version_count * sizeof(struct nfs4_ff_ds_version), + ds_versions = kcalloc(version_count, + sizeof(struct nfs4_ff_ds_version), gfp_flags); if (!ds_versions) goto out_scratch; diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 46b48dbbdd32..d299f91ac375 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c @@ -404,8 +404,9 @@ fsloc_parse(char **mesg, char *buf, struct nfsd4_fs_locations *fsloc) if (fsloc->locations_count == 0) return 0; - fsloc->locations = kzalloc(fsloc->locations_count - * sizeof(struct nfsd4_fs_location), GFP_KERNEL); + fsloc->locations = kcalloc(fsloc->locations_count, + sizeof(struct nfsd4_fs_location), + GFP_KERNEL); if (!fsloc->locations) return -ENOMEM; for (i=0; i < fsloc->locations_count; i++) { diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index 39bb80fb2934..405dbf0ab96e 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c @@ -1390,7 +1390,7 @@ static int __ocfs2_recovery_thread(void *arg) goto bail; } - rm_quota = kzalloc(osb->max_slots * sizeof(int), GFP_NOFS); + rm_quota = kcalloc(osb->max_slots, sizeof(int), GFP_NOFS); if (!rm_quota) { status = -ENOMEM; goto bail; diff --git a/fs/ocfs2/sysfile.c b/fs/ocfs2/sysfile.c index af155c183123..bef0932590ce 100644 --- a/fs/ocfs2/sysfile.c +++ b/fs/ocfs2/sysfile.c @@ -69,9 +69,7 @@ static struct inode **get_local_system_inode(struct ocfs2_super *osb, spin_unlock(&osb->osb_lock); if (unlikely(!local_system_inodes)) { - local_system_inodes = kzalloc(sizeof(struct inode *) * - NUM_LOCAL_SYSTEM_INODES * - osb->max_slots, + local_system_inodes = kzalloc(array3_size(sizeof(struct inode *), NUM_LOCAL_SYSTEM_INODES, osb->max_slots), GFP_NOFS); if (!local_system_inodes) { mlog_errno(-ENOMEM); diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c index 6071196a7b63..098f6f0a2c2a 100644 --- a/fs/overlayfs/namei.c +++ b/fs/overlayfs/namei.c @@ -489,7 +489,7 @@ int ovl_get_index_name(struct dentry *origin, struct qstr *name) return PTR_ERR(fh); err = -ENOMEM; - n = kzalloc(fh->len * 2, GFP_KERNEL); + n = kcalloc(fh->len, 2, GFP_KERNEL); if (n) { s = bin2hex(n, fh, fh->len); *name = (struct qstr) QSTR_INIT(n, s - n); diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c index 2d783e1a827f..370b9b04edcc 100644 --- a/fs/proc/proc_sysctl.c +++ b/fs/proc/proc_sysctl.c @@ -1420,7 +1420,7 @@ static int register_leaf_sysctl_tables(const char *path, char *pos, /* If there are mixed files and directories we need a new table */ if (nr_dirs && nr_files) { struct ctl_table *new; - files = kzalloc(sizeof(struct ctl_table) * (nr_files + 1), + files = kcalloc(nr_files + 1, sizeof(struct ctl_table), GFP_KERNEL); if (!files) goto out; diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 683496322aa8..023cfd699eb3 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c @@ -1044,7 +1044,8 @@ research: if (blocks_needed == 1) { un = &unf_single; } else { - un = kzalloc(min(blocks_needed, max_to_insert) * UNFM_P_SIZE, GFP_NOFS); + un = kcalloc(min(blocks_needed, max_to_insert), + UNFM_P_SIZE, GFP_NOFS); if (!un) { un = &unf_single; blocks_needed = 1; diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c index dac2cc0c17b5..3f29db30bae9 100644 --- a/kernel/debug/kdb/kdb_main.c +++ b/kernel/debug/kdb/kdb_main.c @@ -691,7 +691,7 @@ static int kdb_defcmd2(const char *cmdstr, const char *argv0) } if (!s->usable) return KDB_NOTIMP; - s->command = kzalloc((s->count + 1) * sizeof(*(s->command)), GFP_KDB); + s->command = kcalloc(s->count + 1, sizeof(*(s->command)), GFP_KDB); if (!s->command) { kdb_printf("Could not allocate new kdb_defcmd table for %s\n", cmdstr); diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c index f08ba79ee5d1..ef435f77ecf1 100644 --- a/kernel/events/uprobes.c +++ b/kernel/events/uprobes.c @@ -1188,7 +1188,8 @@ static struct xol_area *__create_xol_area(unsigned long vaddr) if (unlikely(!area)) goto out; - area->bitmap = kzalloc(BITS_TO_LONGS(UINSNS_PER_PAGE) * sizeof(long), GFP_KERNEL); + area->bitmap = kcalloc(BITS_TO_LONGS(UINSNS_PER_PAGE), sizeof(long), + GFP_KERNEL); if (!area->bitmap) goto free_area; diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c index 03e3ab61a2ed..524da96ad908 100644 --- a/kernel/locking/lockdep.c +++ b/kernel/locking/lockdep.c @@ -5141,7 +5141,7 @@ void lockdep_init_task(struct task_struct *task) task->hist_id_save[i] = 0; } - task->xhlocks = kzalloc(sizeof(struct hist_lock) * MAX_XHLOCKS_NR, + task->xhlocks = kcalloc(MAX_XHLOCKS_NR, sizeof(struct hist_lock), GFP_KERNEL); } diff --git a/kernel/locking/locktorture.c b/kernel/locking/locktorture.c index fe8109492901..ac730bba45d0 100644 --- a/kernel/locking/locktorture.c +++ b/kernel/locking/locktorture.c @@ -1005,7 +1005,8 @@ static int __init lock_torture_init(void) } if (nwriters_stress) { - writer_tasks = kzalloc(cxt.nrealwriters_stress * sizeof(writer_tasks[0]), + writer_tasks = kcalloc(cxt.nrealwriters_stress, + sizeof(writer_tasks[0]), GFP_KERNEL); if (writer_tasks == NULL) { VERBOSE_TOROUT_ERRSTRING("writer_tasks: Out of memory"); @@ -1015,7 +1016,8 @@ static int __init lock_torture_init(void) } if (cxt.cur_ops->readlock) { - reader_tasks = kzalloc(cxt.nrealreaders_stress * sizeof(reader_tasks[0]), + reader_tasks = kcalloc(cxt.nrealreaders_stress, + sizeof(reader_tasks[0]), GFP_KERNEL); if (reader_tasks == NULL) { VERBOSE_TOROUT_ERRSTRING("reader_tasks: Out of memory"); diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c index f0c599bf4058..8d342869f268 100644 --- a/kernel/rcu/rcutorture.c +++ b/kernel/rcu/rcutorture.c @@ -1549,10 +1549,10 @@ static int rcu_torture_barrier_init(void) atomic_set(&barrier_cbs_count, 0); atomic_set(&barrier_cbs_invoked, 0); barrier_cbs_tasks = - kzalloc(n_barrier_cbs * sizeof(barrier_cbs_tasks[0]), + kcalloc(n_barrier_cbs, sizeof(barrier_cbs_tasks[0]), GFP_KERNEL); barrier_cbs_wq = - kzalloc(n_barrier_cbs * sizeof(barrier_cbs_wq[0]), + kcalloc(n_barrier_cbs, sizeof(barrier_cbs_wq[0]), GFP_KERNEL); if (barrier_cbs_tasks == NULL || !barrier_cbs_wq) return -ENOMEM; @@ -1796,7 +1796,7 @@ rcu_torture_init(void) if (firsterr) goto unwind; if (nfakewriters > 0) { - fakewriter_tasks = kzalloc(nfakewriters * + fakewriter_tasks = kcalloc(nfakewriters, sizeof(fakewriter_tasks[0]), GFP_KERNEL); if (fakewriter_tasks == NULL) { @@ -1811,7 +1811,7 @@ rcu_torture_init(void) if (firsterr) goto unwind; } - reader_tasks = kzalloc(nrealreaders * sizeof(reader_tasks[0]), + reader_tasks = kcalloc(nrealreaders, sizeof(reader_tasks[0]), GFP_KERNEL); if (reader_tasks == NULL) { VERBOSE_TOROUT_ERRSTRING("out of memory"); diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index d84b0f4bdc9f..6df300ecde0e 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -12562,10 +12562,10 @@ int alloc_fair_sched_group(struct task_group *tg, struct task_group *parent) struct cfs_rq *cfs_rq; int i; - tg->cfs_rq = kzalloc(sizeof(cfs_rq) * nr_cpu_ids, GFP_KERNEL); + tg->cfs_rq = kcalloc(nr_cpu_ids, sizeof(cfs_rq), GFP_KERNEL); if (!tg->cfs_rq) goto err; - tg->se = kzalloc(sizeof(se) * nr_cpu_ids, GFP_KERNEL); + tg->se = kcalloc(nr_cpu_ids, sizeof(se), GFP_KERNEL); if (!tg->se) goto err; diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c index d869bf8c2a1f..6815c8d68c21 100644 --- a/kernel/sched/rt.c +++ b/kernel/sched/rt.c @@ -191,10 +191,10 @@ int alloc_rt_sched_group(struct task_group *tg, struct task_group *parent) struct sched_rt_entity *rt_se; int i; - tg->rt_rq = kzalloc(sizeof(rt_rq) * nr_cpu_ids, GFP_KERNEL); + tg->rt_rq = kcalloc(nr_cpu_ids, sizeof(rt_rq), GFP_KERNEL); if (!tg->rt_rq) goto err; - tg->rt_se = kzalloc(sizeof(rt_se) * nr_cpu_ids, GFP_KERNEL); + tg->rt_se = kcalloc(nr_cpu_ids, sizeof(rt_se), GFP_KERNEL); if (!tg->rt_se) goto err; diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 743e3885c7dd..4446802629a8 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -3385,7 +3385,8 @@ int proc_do_large_bitmap(struct ctl_table *table, int write, if (IS_ERR(kbuf)) return PTR_ERR(kbuf); - tmp_bitmap = kzalloc(BITS_TO_LONGS(bitmap_len) * sizeof(unsigned long), + tmp_bitmap = kcalloc(BITS_TO_LONGS(bitmap_len), + sizeof(unsigned long), GFP_KERNEL); if (!tmp_bitmap) { kfree(kbuf); diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 24d7fd60ff1c..03eed9b1a717 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -759,7 +759,7 @@ static int ftrace_profile_init_cpu(int cpu) */ size = FTRACE_PROFILE_HASH_SIZE; - stat->hash = kzalloc(sizeof(struct hlist_head) * size, GFP_KERNEL); + stat->hash = kcalloc(size, sizeof(struct hlist_head), GFP_KERNEL); if (!stat->hash) return -ENOMEM; diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index d0a2ca3023fb..f0f9cccf5981 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -4400,7 +4400,8 @@ int set_tracer_flag(struct trace_array *tr, unsigned int mask, int enabled) if (mask == TRACE_ITER_RECORD_TGID) { if (!tgid_map) - tgid_map = kzalloc((PID_MAX_DEFAULT + 1) * sizeof(*tgid_map), + tgid_map = kcalloc(PID_MAX_DEFAULT + 1, + sizeof(*tgid_map), GFP_KERNEL); if (!tgid_map) { tr->trace_flags &= ~TRACE_ITER_RECORD_TGID; diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 8263b5f54923..7a51c266e082 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -5625,7 +5625,7 @@ static void __init wq_numa_init(void) * available. Build one from cpu_to_node() which should have been * fully initialized by now. */ - tbl = kzalloc(nr_node_ids * sizeof(tbl[0]), GFP_KERNEL); + tbl = kcalloc(nr_node_ids, sizeof(tbl[0]), GFP_KERNEL); BUG_ON(!tbl); for_each_node(node) diff --git a/lib/lru_cache.c b/lib/lru_cache.c index 28ba40b99337..2b10a4024c35 100644 --- a/lib/lru_cache.c +++ b/lib/lru_cache.c @@ -119,7 +119,7 @@ struct lru_cache *lc_create(const char *name, struct kmem_cache *cache, slot = kcalloc(e_count, sizeof(struct hlist_head), GFP_KERNEL); if (!slot) goto out_fail; - element = kzalloc(e_count * sizeof(struct lc_element *), GFP_KERNEL); + element = kcalloc(e_count, sizeof(struct lc_element *), GFP_KERNEL); if (!element) goto out_fail; diff --git a/lib/mpi/mpiutil.c b/lib/mpi/mpiutil.c index 2dbfc4c8a237..20ed0f766787 100644 --- a/lib/mpi/mpiutil.c +++ b/lib/mpi/mpiutil.c @@ -98,7 +98,7 @@ int mpi_resize(MPI a, unsigned nlimbs) kzfree(a->d); a->d = p; } else { - a->d = kzalloc(nlimbs * sizeof(mpi_limb_t), GFP_KERNEL); + a->d = kcalloc(nlimbs, sizeof(mpi_limb_t), GFP_KERNEL); if (!a->d) return -ENOMEM; } diff --git a/mm/slab.c b/mm/slab.c index 678fe5034bbc..fdf56c95efa9 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -4356,7 +4356,8 @@ static int leaks_show(struct seq_file *m, void *p) if (x[0] == x[1]) { /* Increase the buffer size */ mutex_unlock(&slab_mutex); - m->private = kzalloc(x[0] * 4 * sizeof(unsigned long), GFP_KERNEL); + m->private = kcalloc(x[0] * 4, sizeof(unsigned long), + GFP_KERNEL); if (!m->private) { /* Too bad, we are really out */ m->private = x; diff --git a/mm/slub.c b/mm/slub.c index 7a7ed043fc09..7cf688e9f5b6 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -3781,8 +3781,9 @@ static void list_slab_objects(struct kmem_cache *s, struct page *page, #ifdef CONFIG_SLUB_DEBUG void *addr = page_address(page); void *p; - unsigned long *map = kzalloc(BITS_TO_LONGS(page->objects) * - sizeof(long), GFP_ATOMIC); + unsigned long *map = kcalloc(BITS_TO_LONGS(page->objects), + sizeof(long), + GFP_ATOMIC); if (!map) return; slab_err(s, page, text, s->name); @@ -4902,7 +4903,7 @@ static ssize_t show_slab_objects(struct kmem_cache *s, int x; unsigned long *nodes; - nodes = kzalloc(sizeof(unsigned long) * nr_node_ids, GFP_KERNEL); + nodes = kcalloc(nr_node_ids, sizeof(unsigned long), GFP_KERNEL); if (!nodes) return -ENOMEM; diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index b24782d53474..c9b9ca8e8d4f 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -332,7 +332,7 @@ static int br_mdb_rehash(struct net_bridge_mdb_htable __rcu **mdbp, int max, mdb->max = max; mdb->old = old; - mdb->mhash = kzalloc(max * sizeof(*mdb->mhash), GFP_ATOMIC); + mdb->mhash = kcalloc(max, sizeof(*mdb->mhash), GFP_ATOMIC); if (!mdb->mhash) { kfree(mdb); return -ENOMEM; diff --git a/net/can/bcm.c b/net/can/bcm.c index 81b2e1f5ddff..dd45a8e4f3fb 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c @@ -1145,7 +1145,8 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg, } /* create and init array for received CAN frames */ - op->last_frames = kzalloc(msg_head->nframes * op->cfsiz, + op->last_frames = kcalloc(msg_head->nframes, + op->cfsiz, GFP_KERNEL); if (!op->last_frames) { kfree(op->frames); diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 08781b9aa6bf..24ddcc194607 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -930,7 +930,7 @@ static noinline_for_stack int ethtool_get_sset_info(struct net_device *dev, memset(&info, 0, sizeof(info)); info.cmd = ETHTOOL_GSSET_INFO; - info_buf = kzalloc(n_bits * sizeof(u32), GFP_USER); + info_buf = kcalloc(n_bits, sizeof(u32), GFP_USER); if (!info_buf) return -ENOMEM; @@ -1022,7 +1022,7 @@ static noinline_for_stack int ethtool_get_rxnfc(struct net_device *dev, if (info.cmd == ETHTOOL_GRXCLSRLALL) { if (info.rule_cnt > 0) { if (info.rule_cnt <= KMALLOC_MAX_SIZE / sizeof(u32)) - rule_buf = kzalloc(info.rule_cnt * sizeof(u32), + rule_buf = kcalloc(info.rule_cnt, sizeof(u32), GFP_USER); if (!rule_buf) return -ENOMEM; diff --git a/net/ieee802154/nl-phy.c b/net/ieee802154/nl-phy.c index dc2960be51e0..b231e40f006a 100644 --- a/net/ieee802154/nl-phy.c +++ b/net/ieee802154/nl-phy.c @@ -38,7 +38,7 @@ static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 portid, { void *hdr; int i, pages = 0; - uint32_t *buf = kzalloc(32 * sizeof(uint32_t), GFP_KERNEL); + uint32_t *buf = kcalloc(32, sizeof(uint32_t), GFP_KERNEL); pr_debug("%s\n", __func__); diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index ff499000f6cd..d56350f42eb9 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -542,7 +542,7 @@ static int rtentry_to_fib_config(struct net *net, int cmd, struct rtentry *rt, struct nlattr *mx; int len = 0; - mx = kzalloc(3 * nla_total_size(4), GFP_KERNEL); + mx = kcalloc(3, nla_total_size(4), GFP_KERNEL); if (!mx) return -ENOMEM; diff --git a/net/ipv4/route.c b/net/ipv4/route.c index f6713119eaf4..ab2252174433 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -665,7 +665,7 @@ static void update_or_create_fnhe(struct fib_nh *nh, __be32 daddr, __be32 gw, hash = rcu_dereference(nh->nh_exceptions); if (!hash) { - hash = kzalloc(FNHE_HASH_SIZE * sizeof(*hash), GFP_ATOMIC); + hash = kcalloc(FNHE_HASH_SIZE, sizeof(*hash), GFP_ATOMIC); if (!hash) goto out_unlock; rcu_assign_pointer(nh->nh_exceptions, hash); diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index c5f2b17b7ee1..0fbc1553646d 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -966,7 +966,7 @@ static int __net_init icmpv6_sk_init(struct net *net) int err, i, j; net->ipv6.icmp_sk = - kzalloc(nr_cpu_ids * sizeof(struct sock *), GFP_KERNEL); + kcalloc(nr_cpu_ids, sizeof(struct sock *), GFP_KERNEL); if (!net->ipv6.icmp_sk) return -ENOMEM; diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 98ab1564aade..49358f7e4f80 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -1828,7 +1828,7 @@ static int ip6_convert_metrics(struct mx6_config *mxc, if (!cfg->fc_mx) return 0; - mp = kzalloc(sizeof(u32) * RTAX_MAX, GFP_KERNEL); + mp = kcalloc(RTAX_MAX, sizeof(u32), GFP_KERNEL); if (unlikely(!mp)) return -ENOMEM; diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index 89178b46b32f..d9558ffb8acf 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c @@ -1186,7 +1186,7 @@ static int ieee80211_chsw_switch_vifs(struct ieee80211_local *local, lockdep_assert_held(&local->mtx); lockdep_assert_held(&local->chanctx_mtx); - vif_chsw = kzalloc(sizeof(vif_chsw[0]) * n_vifs, GFP_KERNEL); + vif_chsw = kcalloc(n_vifs, sizeof(vif_chsw[0]), GFP_KERNEL); if (!vif_chsw) return -ENOMEM; diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index 7c9d817e2b04..7b20e6f6a4fc 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c @@ -592,7 +592,7 @@ minstrel_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp) max_rates = sband->n_bitrates; } - mi->r = kzalloc(sizeof(struct minstrel_rate) * max_rates, gfp); + mi->r = kcalloc(max_rates, sizeof(struct minstrel_rate), gfp); if (!mi->r) goto error; diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index e19919b6dd14..d108a7c8bcee 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c @@ -1317,7 +1317,7 @@ minstrel_ht_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp) if (!msp) return NULL; - msp->ratelist = kzalloc(sizeof(struct minstrel_rate) * max_rates, gfp); + msp->ratelist = kcalloc(max_rates, sizeof(struct minstrel_rate), gfp); if (!msp->ratelist) goto error; diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 47d2ed570470..af9ef59a0513 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -1136,7 +1136,7 @@ int __ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, } } - ie = kzalloc(num_bands * iebufsz, GFP_KERNEL); + ie = kcalloc(iebufsz, num_bands, GFP_KERNEL); if (!ie) { ret = -ENOMEM; goto out; diff --git a/net/mac80211/util.c b/net/mac80211/util.c index cd3cdd1a0b57..c3a798f95684 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1768,8 +1768,9 @@ static int ieee80211_reconfig_nan(struct ieee80211_sub_if_data *sdata) if (WARN_ON(res)) return res; - funcs = kzalloc((sdata->local->hw.max_nan_de_entries + 1) * - sizeof(*funcs), GFP_KERNEL); + funcs = kcalloc(sdata->local->hw.max_nan_de_entries + 1, + sizeof(*funcs), + GFP_KERNEL); if (!funcs) return -ENOMEM; diff --git a/net/netfilter/nfnetlink_cthelper.c b/net/netfilter/nfnetlink_cthelper.c index dfe4e6787219..8d8dcb005775 100644 --- a/net/netfilter/nfnetlink_cthelper.c +++ b/net/netfilter/nfnetlink_cthelper.c @@ -190,8 +190,9 @@ nfnl_cthelper_parse_expect_policy(struct nf_conntrack_helper *helper, if (class_max > NF_CT_MAX_EXPECT_CLASSES) return -EOVERFLOW; - expect_policy = kzalloc(sizeof(struct nf_conntrack_expect_policy) * - class_max, GFP_KERNEL); + expect_policy = kcalloc(class_max, + sizeof(struct nf_conntrack_expect_policy), + GFP_KERNEL); if (expect_policy == NULL) return -ENOMEM; diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index aebc804c10aa..c244133a7e70 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c @@ -1414,7 +1414,7 @@ static int __init nr_proto_init(void) return -1; } - dev_nr = kzalloc(nr_ndevs * sizeof(struct net_device *), GFP_KERNEL); + dev_nr = kcalloc(nr_ndevs, sizeof(struct net_device *), GFP_KERNEL); if (dev_nr == NULL) { printk(KERN_ERR "NET/ROM: nr_proto_init - unable to allocate device array\n"); return -1; diff --git a/net/openvswitch/vport.c b/net/openvswitch/vport.c index b6c8524032a0..da2a77c67b4c 100644 --- a/net/openvswitch/vport.c +++ b/net/openvswitch/vport.c @@ -47,7 +47,7 @@ static struct hlist_head *dev_table; */ int ovs_vport_init(void) { - dev_table = kzalloc(VPORT_HASH_BUCKETS * sizeof(struct hlist_head), + dev_table = kcalloc(VPORT_HASH_BUCKETS, sizeof(struct hlist_head), GFP_KERNEL); if (!dev_table) return -ENOMEM; diff --git a/net/rds/ib.c b/net/rds/ib.c index e723146cec29..21f8923a556e 100644 --- a/net/rds/ib.c +++ b/net/rds/ib.c @@ -164,7 +164,8 @@ static void rds_ib_add_one(struct ib_device *device) rds_ibdev->max_initiator_depth = device->attrs.max_qp_init_rd_atom; rds_ibdev->max_responder_resources = device->attrs.max_qp_rd_atom; - rds_ibdev->vector_load = kzalloc(sizeof(int) * device->num_comp_vectors, + rds_ibdev->vector_load = kcalloc(device->num_comp_vectors, + sizeof(int), GFP_KERNEL); if (!rds_ibdev->vector_load) { pr_err("RDS/IB: %s failed to allocate vector memory\n", diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index 6a5c4992cf61..685e38044368 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c @@ -1528,7 +1528,8 @@ static int __init rose_proto_init(void) rose_callsign = null_ax25_address; - dev_rose = kzalloc(rose_ndevs * sizeof(struct net_device *), GFP_KERNEL); + dev_rose = kcalloc(rose_ndevs, sizeof(struct net_device *), + GFP_KERNEL); if (dev_rose == NULL) { printk(KERN_ERR "ROSE: rose_proto_init - unable to allocate device structure\n"); rc = -ENOMEM; diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index 0c9bc29dcf97..eaf01c381f49 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c @@ -735,7 +735,8 @@ static u32 gen_new_kid(struct tc_u_hnode *ht, u32 handle) { struct tc_u_knode *n; unsigned long i; - unsigned long *bitmap = kzalloc(BITS_TO_LONGS(NR_U32_NODE) * sizeof(unsigned long), + unsigned long *bitmap = kcalloc(BITS_TO_LONGS(NR_U32_NODE), + sizeof(unsigned long), GFP_KERNEL); if (!bitmap) return handle | 0xFFF; diff --git a/net/sctp/auth.c b/net/sctp/auth.c index 00667c50efa7..9b133db2d4dc 100644 --- a/net/sctp/auth.c +++ b/net/sctp/auth.c @@ -461,8 +461,9 @@ int sctp_auth_init_hmacs(struct sctp_endpoint *ep, gfp_t gfp) return 0; /* Allocated the array of pointers to transorms */ - ep->auth_hmacs = kzalloc(sizeof(struct crypto_shash *) * - SCTP_AUTH_NUM_HMACS, gfp); + ep->auth_hmacs = kcalloc(SCTP_AUTH_NUM_HMACS, + sizeof(struct crypto_shash *), + gfp); if (!ep->auth_hmacs) return -ENOMEM; diff --git a/net/smc/smc_wr.c b/net/smc/smc_wr.c index ed6736a1a112..5cdebdbb8f13 100644 --- a/net/smc/smc_wr.c +++ b/net/smc/smc_wr.c @@ -597,9 +597,9 @@ int smc_wr_alloc_link_mem(struct smc_link *link) GFP_KERNEL); if (!link->wr_rx_sges) goto no_mem_wr_tx_sges; - link->wr_tx_mask = kzalloc( - BITS_TO_LONGS(SMC_WR_BUF_CNT) * sizeof(*link->wr_tx_mask), - GFP_KERNEL); + link->wr_tx_mask = kcalloc(BITS_TO_LONGS(SMC_WR_BUF_CNT), + sizeof(*link->wr_tx_mask), + GFP_KERNEL); if (!link->wr_tx_mask) goto no_mem_wr_rx_sges; link->wr_tx_pends = kcalloc(SMC_WR_BUF_CNT, diff --git a/net/sunrpc/auth_gss/gss_rpc_upcall.c b/net/sunrpc/auth_gss/gss_rpc_upcall.c index 46b295e4f2b8..d58bd058b09b 100644 --- a/net/sunrpc/auth_gss/gss_rpc_upcall.c +++ b/net/sunrpc/auth_gss/gss_rpc_upcall.c @@ -224,7 +224,7 @@ static void gssp_free_receive_pages(struct gssx_arg_accept_sec_context *arg) static int gssp_alloc_receive_pages(struct gssx_arg_accept_sec_context *arg) { arg->npages = DIV_ROUND_UP(NGROUPS_MAX * 4, PAGE_SIZE); - arg->pages = kzalloc(arg->npages * sizeof(struct page *), GFP_KERNEL); + arg->pages = kcalloc(arg->npages, sizeof(struct page *), GFP_KERNEL); /* * XXX: actual pages are allocated by xdr layer in * xdr_partial_copy_from_skb. diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 556989b0b5fc..c6f5343f8c81 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -1688,7 +1688,7 @@ struct cache_detail *cache_create_net(struct cache_detail *tmpl, struct net *net if (cd == NULL) return ERR_PTR(-ENOMEM); - cd->hash_table = kzalloc(cd->hash_size * sizeof(struct hlist_head), + cd->hash_table = kcalloc(cd->hash_size, sizeof(struct hlist_head), GFP_KERNEL); if (cd->hash_table == NULL) { kfree(cd); diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 09ee36ab0ef8..04e021398fce 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -10737,7 +10737,7 @@ static int nl80211_parse_wowlan_nd(struct cfg80211_registered_device *rdev, struct nlattr **tb; int err; - tb = kzalloc(NUM_NL80211_ATTR * sizeof(*tb), GFP_KERNEL); + tb = kcalloc(NUM_NL80211_ATTR, sizeof(*tb), GFP_KERNEL); if (!tb) return -ENOMEM; @@ -11712,7 +11712,7 @@ static int nl80211_nan_add_func(struct sk_buff *skb, func->srf_num_macs = n_entries; func->srf_macs = - kzalloc(sizeof(*func->srf_macs) * n_entries, + kcalloc(n_entries, sizeof(*func->srf_macs), GFP_KERNEL); if (!func->srf_macs) { err = -ENOMEM; diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c index 2cef8d4404cc..5e4233afd20a 100644 --- a/security/apparmor/policy_unpack.c +++ b/security/apparmor/policy_unpack.c @@ -458,7 +458,7 @@ static bool unpack_trans_table(struct aa_ext *e, struct aa_profile *profile) /* currently 4 exec bits and entries 0-3 are reserved iupcx */ if (size > 16 - 4) goto fail; - profile->file.trans.table = kzalloc(sizeof(char *) * size, + profile->file.trans.table = kcalloc(size, sizeof(char *), GFP_KERNEL); if (!profile->file.trans.table) goto fail; diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 97ef755237c9..398206f25eac 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -2190,7 +2190,7 @@ int security_load_policy(struct selinux_state *state, void *data, size_t len) int rc = 0; struct policy_file file = { data, len }, *fp = &file; - oldpolicydb = kzalloc(2 * sizeof(*oldpolicydb), GFP_KERNEL); + oldpolicydb = kcalloc(2, sizeof(*oldpolicydb), GFP_KERNEL); if (!oldpolicydb) { rc = -ENOMEM; goto out; diff --git a/sound/firewire/fireface/ff-protocol-ff400.c b/sound/firewire/fireface/ff-protocol-ff400.c index bb0c1abf4718..4d191172fe3f 100644 --- a/sound/firewire/fireface/ff-protocol-ff400.c +++ b/sound/firewire/fireface/ff-protocol-ff400.c @@ -148,7 +148,7 @@ static int ff400_switch_fetching_mode(struct snd_ff *ff, bool enable) int i; int err; - reg = kzalloc(sizeof(__le32) * 18, GFP_KERNEL); + reg = kcalloc(18, sizeof(__le32), GFP_KERNEL); if (reg == NULL) return -ENOMEM; diff --git a/sound/oss/swarm_cs4297a.c b/sound/oss/swarm_cs4297a.c index 97899352b15f..2f6942cf6e08 100644 --- a/sound/oss/swarm_cs4297a.c +++ b/sound/oss/swarm_cs4297a.c @@ -630,7 +630,8 @@ static int init_serdma(serdma_t *dma) /* Descriptors */ dma->ringsz = DMA_DESCR; - dma->descrtab = kzalloc(dma->ringsz * sizeof(serdma_descr_t), GFP_KERNEL); + dma->descrtab = kcalloc(dma->ringsz, sizeof(serdma_descr_t), + GFP_KERNEL); if (!dma->descrtab) { printk(KERN_ERR "cs4297a: kzalloc descrtab failed\n"); return -1; diff --git a/sound/pci/ctxfi/ctatc.c b/sound/pci/ctxfi/ctatc.c index 908658a00377..2ada8444abd9 100644 --- a/sound/pci/ctxfi/ctatc.c +++ b/sound/pci/ctxfi/ctatc.c @@ -275,7 +275,7 @@ static int atc_pcm_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm) /* Get AMIXER resource */ n_amixer = (n_amixer < 2) ? 2 : n_amixer; - apcm->amixers = kzalloc(sizeof(void *)*n_amixer, GFP_KERNEL); + apcm->amixers = kcalloc(n_amixer, sizeof(void *), GFP_KERNEL); if (!apcm->amixers) { err = -ENOMEM; goto error1; @@ -543,18 +543,18 @@ atc_pcm_capture_get_resources(struct ct_atc *atc, struct ct_atc_pcm *apcm) } if (n_srcc) { - apcm->srccs = kzalloc(sizeof(void *)*n_srcc, GFP_KERNEL); + apcm->srccs = kcalloc(n_srcc, sizeof(void *), GFP_KERNEL); if (!apcm->srccs) return -ENOMEM; } if (n_amixer) { - apcm->amixers = kzalloc(sizeof(void *)*n_amixer, GFP_KERNEL); + apcm->amixers = kcalloc(n_amixer, sizeof(void *), GFP_KERNEL); if (!apcm->amixers) { err = -ENOMEM; goto error1; } } - apcm->srcimps = kzalloc(sizeof(void *)*n_srcimp, GFP_KERNEL); + apcm->srcimps = kcalloc(n_srcimp, sizeof(void *), GFP_KERNEL); if (!apcm->srcimps) { err = -ENOMEM; goto error1; @@ -819,7 +819,7 @@ static int spdif_passthru_playback_get_resources(struct ct_atc *atc, /* Get AMIXER resource */ n_amixer = (n_amixer < 2) ? 2 : n_amixer; - apcm->amixers = kzalloc(sizeof(void *)*n_amixer, GFP_KERNEL); + apcm->amixers = kcalloc(n_amixer, sizeof(void *), GFP_KERNEL); if (!apcm->amixers) { err = -ENOMEM; goto error1; @@ -1378,19 +1378,19 @@ static int atc_get_resources(struct ct_atc *atc) num_daios = ((atc->model == CTSB1270) ? 8 : 7); num_srcs = ((atc->model == CTSB1270) ? 6 : 4); - atc->daios = kzalloc(sizeof(void *)*num_daios, GFP_KERNEL); + atc->daios = kcalloc(num_daios, sizeof(void *), GFP_KERNEL); if (!atc->daios) return -ENOMEM; - atc->srcs = kzalloc(sizeof(void *)*num_srcs, GFP_KERNEL); + atc->srcs = kcalloc(num_srcs, sizeof(void *), GFP_KERNEL); if (!atc->srcs) return -ENOMEM; - atc->srcimps = kzalloc(sizeof(void *)*num_srcs, GFP_KERNEL); + atc->srcimps = kcalloc(num_srcs, sizeof(void *), GFP_KERNEL); if (!atc->srcimps) return -ENOMEM; - atc->pcm = kzalloc(sizeof(void *)*(2*4), GFP_KERNEL); + atc->pcm = kcalloc(2 * 4, sizeof(void *), GFP_KERNEL); if (!atc->pcm) return -ENOMEM; diff --git a/sound/pci/ctxfi/ctdaio.c b/sound/pci/ctxfi/ctdaio.c index 7f089cb433e1..f35a7341e446 100644 --- a/sound/pci/ctxfi/ctdaio.c +++ b/sound/pci/ctxfi/ctdaio.c @@ -398,7 +398,8 @@ static int dao_rsc_init(struct dao *dao, if (err) return err; - dao->imappers = kzalloc(sizeof(void *)*desc->msr*2, GFP_KERNEL); + dao->imappers = kzalloc(array3_size(sizeof(void *), desc->msr, 2), + GFP_KERNEL); if (!dao->imappers) { err = -ENOMEM; goto error1; diff --git a/sound/pci/ctxfi/ctmixer.c b/sound/pci/ctxfi/ctmixer.c index 4f4a2a5dedb8..db710d0a609f 100644 --- a/sound/pci/ctxfi/ctmixer.c +++ b/sound/pci/ctxfi/ctmixer.c @@ -910,13 +910,14 @@ static int ct_mixer_get_mem(struct ct_mixer **rmixer) if (!mixer) return -ENOMEM; - mixer->amixers = kzalloc(sizeof(void *)*(NUM_CT_AMIXERS*CHN_NUM), + mixer->amixers = kcalloc(NUM_CT_AMIXERS * CHN_NUM, sizeof(void *), GFP_KERNEL); if (!mixer->amixers) { err = -ENOMEM; goto error1; } - mixer->sums = kzalloc(sizeof(void *)*(NUM_CT_SUMS*CHN_NUM), GFP_KERNEL); + mixer->sums = kcalloc(NUM_CT_SUMS * CHN_NUM, sizeof(void *), + GFP_KERNEL); if (!mixer->sums) { err = -ENOMEM; goto error2; diff --git a/sound/pci/ctxfi/ctsrc.c b/sound/pci/ctxfi/ctsrc.c index bb4c9c3c89ae..a4fc10723fc6 100644 --- a/sound/pci/ctxfi/ctsrc.c +++ b/sound/pci/ctxfi/ctsrc.c @@ -679,7 +679,7 @@ static int srcimp_rsc_init(struct srcimp *srcimp, return err; /* Reserve memory for imapper nodes */ - srcimp->imappers = kzalloc(sizeof(struct imapper)*desc->msr, + srcimp->imappers = kcalloc(desc->msr, sizeof(struct imapper), GFP_KERNEL); if (!srcimp->imappers) { err = -ENOMEM; diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 92f5f452bee2..31d693bb6139 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -4703,7 +4703,9 @@ static int ca0132_prepare_verbs(struct hda_codec *codec) struct ca0132_spec *spec = codec->spec; spec->chip_init_verbs = ca0132_init_verbs0; - spec->spec_init_verbs = kzalloc(sizeof(struct hda_verb) * NUM_SPEC_VERBS, GFP_KERNEL); + spec->spec_init_verbs = kcalloc(NUM_SPEC_VERBS, + sizeof(struct hda_verb), + GFP_KERNEL); if (!spec->spec_init_verbs) return -ENOMEM; diff --git a/sound/soc/blackfin/bf5xx-sport.c b/sound/soc/blackfin/bf5xx-sport.c index 9dfa1241ea66..dce1c84f70bc 100644 --- a/sound/soc/blackfin/bf5xx-sport.c +++ b/sound/soc/blackfin/bf5xx-sport.c @@ -929,7 +929,7 @@ struct sport_device *sport_init(struct platform_device *pdev, if (L1_DATA_A_LENGTH) sport->dummy_buf = l1_data_sram_zalloc(param.dummy_count * 2); else - sport->dummy_buf = kzalloc(param.dummy_count * 2, GFP_KERNEL); + sport->dummy_buf = kcalloc(param.dummy_count, 2, GFP_KERNEL); if (sport->dummy_buf == NULL) { dev_err(dev, "failed to allocate dummy buffer\n"); goto __error1; diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 158ce68bc9bf..feecbc2caae1 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -1895,7 +1895,7 @@ static void *wm_adsp_read_algs(struct wm_adsp *dsp, size_t n_algs, adsp_warn(dsp, "Algorithm list end %x 0x%x != 0xbedead\n", pos + len, be32_to_cpu(val)); - alg = kzalloc(len * 2, GFP_KERNEL | GFP_DMA); + alg = kcalloc(len, 2, GFP_KERNEL | GFP_DMA); if (!alg) return ERR_PTR(-ENOMEM); diff --git a/sound/soc/intel/common/sst-ipc.c b/sound/soc/intel/common/sst-ipc.c index fedce78675e8..771734fd7707 100644 --- a/sound/soc/intel/common/sst-ipc.c +++ b/sound/soc/intel/common/sst-ipc.c @@ -121,8 +121,8 @@ static int msg_empty_list_init(struct sst_generic_ipc *ipc) { int i; - ipc->msg = kzalloc(sizeof(struct ipc_message) * - IPC_EMPTY_LIST_SIZE, GFP_KERNEL); + ipc->msg = kcalloc(IPC_EMPTY_LIST_SIZE, sizeof(struct ipc_message), + GFP_KERNEL); if (ipc->msg == NULL) return -ENOMEM; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 123dcd1b9327..9de75e5a0b3f 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -626,8 +626,8 @@ static struct snd_soc_pcm_runtime *soc_new_pcm_runtime( INIT_LIST_HEAD(&rtd->component_list); rtd->card = card; rtd->dai_link = dai_link; - rtd->codec_dais = kzalloc(sizeof(struct snd_soc_dai *) * - dai_link->num_codecs, + rtd->codec_dais = kcalloc(dai_link->num_codecs, + sizeof(struct snd_soc_dai *), GFP_KERNEL); if (!rtd->codec_dais) { kfree(rtd); diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index ec1aa2bbc297..fcfc77793236 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -3091,7 +3091,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_card *card) continue; if (w->num_kcontrols) { - w->kcontrols = kzalloc(w->num_kcontrols * + w->kcontrols = kcalloc(w->num_kcontrols, sizeof(struct snd_kcontrol *), GFP_KERNEL); if (!w->kcontrols) { diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 50aa45525be5..fbadd6088c8e 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -936,7 +936,7 @@ static int soc_tplg_denum_create_texts(struct soc_enum *se, int i, ret; se->dobj.control.dtexts = - kzalloc(sizeof(char *) * ec->items, GFP_KERNEL); + kcalloc(ec->items, sizeof(char *), GFP_KERNEL); if (se->dobj.control.dtexts == NULL) return -ENOMEM; diff --git a/sound/usb/6fire/pcm.c b/sound/usb/6fire/pcm.c index 224a6a5d1c0e..2dd2518a71d3 100644 --- a/sound/usb/6fire/pcm.c +++ b/sound/usb/6fire/pcm.c @@ -591,12 +591,14 @@ static int usb6fire_pcm_buffers_init(struct pcm_runtime *rt) int i; for (i = 0; i < PCM_N_URBS; i++) { - rt->out_urbs[i].buffer = kzalloc(PCM_N_PACKETS_PER_URB - * PCM_MAX_PACKET_SIZE, GFP_KERNEL); + rt->out_urbs[i].buffer = kcalloc(PCM_MAX_PACKET_SIZE, + PCM_N_PACKETS_PER_URB, + GFP_KERNEL); if (!rt->out_urbs[i].buffer) return -ENOMEM; - rt->in_urbs[i].buffer = kzalloc(PCM_N_PACKETS_PER_URB - * PCM_MAX_PACKET_SIZE, GFP_KERNEL); + rt->in_urbs[i].buffer = kcalloc(PCM_MAX_PACKET_SIZE, + PCM_N_PACKETS_PER_URB, + GFP_KERNEL); if (!rt->in_urbs[i].buffer) return -ENOMEM; } diff --git a/sound/usb/line6/capture.c b/sound/usb/line6/capture.c index a65a82d5791d..bd0171cfec4c 100644 --- a/sound/usb/line6/capture.c +++ b/sound/usb/line6/capture.c @@ -264,8 +264,8 @@ int line6_create_audio_in_urbs(struct snd_line6_pcm *line6pcm) struct usb_line6 *line6 = line6pcm->line6; int i; - line6pcm->in.urbs = kzalloc( - sizeof(struct urb *) * line6->iso_buffers, GFP_KERNEL); + line6pcm->in.urbs = kcalloc(line6->iso_buffers, sizeof(struct urb *), + GFP_KERNEL); if (line6pcm->in.urbs == NULL) return -ENOMEM; diff --git a/sound/usb/line6/playback.c b/sound/usb/line6/playback.c index 1736eb3ee98e..6b8f2dd358a1 100644 --- a/sound/usb/line6/playback.c +++ b/sound/usb/line6/playback.c @@ -409,8 +409,8 @@ int line6_create_audio_out_urbs(struct snd_line6_pcm *line6pcm) struct usb_line6 *line6 = line6pcm->line6; int i; - line6pcm->out.urbs = kzalloc( - sizeof(struct urb *) * line6->iso_buffers, GFP_KERNEL); + line6pcm->out.urbs = kcalloc(line6->iso_buffers, sizeof(struct urb *), + GFP_KERNEL); if (line6pcm->out.urbs == NULL) return -ENOMEM; diff --git a/techpack/audio/4.0/asoc/codecs/wcd9xxx-core.c b/techpack/audio/4.0/asoc/codecs/wcd9xxx-core.c index 9736c43c365b..03e38e7954ed 100644 --- a/techpack/audio/4.0/asoc/codecs/wcd9xxx-core.c +++ b/techpack/audio/4.0/asoc/codecs/wcd9xxx-core.c @@ -179,7 +179,7 @@ static int wcd9xxx_slim_multi_reg_write(struct wcd9xxx *wcd9xxx, if (num_regs == 0) return -EINVAL; - bulk_reg = kzalloc(num_regs * (sizeof(struct wcd9xxx_reg_val)), + bulk_reg = kcalloc(num_regs, sizeof(struct wcd9xxx_reg_val), GFP_KERNEL); if (!bulk_reg) return -ENOMEM; @@ -484,7 +484,7 @@ int wcd9xxx_slim_bulk_write(struct wcd9xxx *wcd9xxx, return 0; } - msgs = kzalloc(size * (sizeof(struct slim_val_inf)), GFP_KERNEL); + msgs = kcalloc(size, sizeof(struct slim_val_inf), GFP_KERNEL); if (!msgs) { ret = -ENOMEM; goto mem_fail; diff --git a/techpack/audio/4.0/asoc/msm-dai-q6-v2.c b/techpack/audio/4.0/asoc/msm-dai-q6-v2.c index 0ed0dae05b90..d68f6ef49049 100644 --- a/techpack/audio/4.0/asoc/msm-dai-q6-v2.c +++ b/techpack/audio/4.0/asoc/msm-dai-q6-v2.c @@ -4463,9 +4463,9 @@ static int msm_auxpcm_dev_probe(struct platform_device *pdev) } auxpcm_pdata->mode_8k.slot_mapping = - kzalloc(sizeof(uint16_t) * - auxpcm_pdata->mode_8k.num_slots, - GFP_KERNEL); + kcalloc(auxpcm_pdata->mode_8k.num_slots, + sizeof(uint16_t), + GFP_KERNEL); if (!auxpcm_pdata->mode_8k.slot_mapping) { dev_err(&pdev->dev, "%s No mem for mode_8k slot mapping\n", __func__); @@ -4478,9 +4478,9 @@ static int msm_auxpcm_dev_probe(struct platform_device *pdev) (u16)be32_to_cpu(slot_mapping_array[i]); auxpcm_pdata->mode_16k.slot_mapping = - kzalloc(sizeof(uint16_t) * - auxpcm_pdata->mode_16k.num_slots, - GFP_KERNEL); + kcalloc(auxpcm_pdata->mode_16k.num_slots, + sizeof(uint16_t), + GFP_KERNEL); if (!auxpcm_pdata->mode_16k.slot_mapping) { dev_err(&pdev->dev, "%s No mem for mode_16k slot mapping\n", diff --git a/techpack/audio/4.0/asoc/msm-lsm-client.c b/techpack/audio/4.0/asoc/msm-lsm-client.c index d6fd86cc97a2..9bcda9bf0fa5 100644 --- a/techpack/audio/4.0/asoc/msm-lsm-client.c +++ b/techpack/audio/4.0/asoc/msm-lsm-client.c @@ -2576,7 +2576,7 @@ static int msm_lsm_send_ch_mix_config(struct snd_pcm_substream *substream) return 0; } - ch_wght_coeff = kzalloc(in_params->num_chs * pp_ch_cnt * sizeof(int), + ch_wght_coeff = kcalloc(in_params->num_chs * pp_ch_cnt, sizeof(int), GFP_KERNEL); if (!ch_wght_coeff) return -ENOMEM; diff --git a/techpack/audio/4.0/dsp/q6asm.c b/techpack/audio/4.0/dsp/q6asm.c index a71ef087aa31..8acd2330b84b 100644 --- a/techpack/audio/4.0/dsp/q6asm.c +++ b/techpack/audio/4.0/dsp/q6asm.c @@ -8472,7 +8472,7 @@ static int q6asm_memory_map_regions(struct audio_client *ac, int dir, return -EINVAL; } - buffer_node = kzalloc(sizeof(struct asm_buffer_node) * bufcnt, + buffer_node = kcalloc(bufcnt, sizeof(struct asm_buffer_node), GFP_KERNEL); if (!buffer_node) return -ENOMEM; diff --git a/techpack/audio/4.0/dsp/q6lsm.c b/techpack/audio/4.0/dsp/q6lsm.c index 8ad6ed624002..ca149618c8aa 100644 --- a/techpack/audio/4.0/dsp/q6lsm.c +++ b/techpack/audio/4.0/dsp/q6lsm.c @@ -2554,8 +2554,9 @@ int q6lsm_lab_buffer_alloc(struct lsm_client *client, bool alloc) out_params->buf_sz; allocate_size = PAGE_ALIGN(allocate_size); client->lab_buffer = - kzalloc(sizeof(struct lsm_lab_buffer) * - out_params->period_count, GFP_KERNEL); + kcalloc(out_params->period_count, + sizeof(struct lsm_lab_buffer), + GFP_KERNEL); if (!client->lab_buffer) { pr_err("%s: memory allocation for lab buffer failed count %d\n" , __func__, diff --git a/techpack/audio/4.0/dsp/q6usm.c b/techpack/audio/4.0/dsp/q6usm.c index cd024fce8139..94a88afe2aef 100644 --- a/techpack/audio/4.0/dsp/q6usm.c +++ b/techpack/audio/4.0/dsp/q6usm.c @@ -306,7 +306,7 @@ struct us_client *q6usm_us_client_alloc( if (usc == NULL) return NULL; - p_mem_handle = kzalloc(sizeof(uint32_t) * 4, GFP_KERNEL); + p_mem_handle = kcalloc(4, sizeof(uint32_t), GFP_KERNEL); if (p_mem_handle == NULL) { kfree(usc); return NULL; diff --git a/techpack/audio/asoc/codecs/wcd9xxx-core.c b/techpack/audio/asoc/codecs/wcd9xxx-core.c index f1b34b047251..312373339ad3 100644 --- a/techpack/audio/asoc/codecs/wcd9xxx-core.c +++ b/techpack/audio/asoc/codecs/wcd9xxx-core.c @@ -129,7 +129,7 @@ static int wcd9xxx_slim_multi_reg_write(struct wcd9xxx *wcd9xxx, if (num_regs == 0) return -EINVAL; - bulk_reg = kzalloc(num_regs * (sizeof(struct wcd9xxx_reg_val)), + bulk_reg = kcalloc(num_regs, sizeof(struct wcd9xxx_reg_val), GFP_KERNEL); if (!bulk_reg) return -ENOMEM; @@ -435,7 +435,7 @@ int wcd9xxx_slim_bulk_write(struct wcd9xxx *wcd9xxx, return 0; } - msgs = kzalloc(size * (sizeof(struct slim_val_inf)), GFP_KERNEL); + msgs = kcalloc(size, sizeof(struct slim_val_inf), GFP_KERNEL); if (!msgs) { ret = -ENOMEM; goto mem_fail; diff --git a/techpack/audio/asoc/msm-dai-q6-v2.c b/techpack/audio/asoc/msm-dai-q6-v2.c index 4c043edafc27..b79bdc23b740 100644 --- a/techpack/audio/asoc/msm-dai-q6-v2.c +++ b/techpack/audio/asoc/msm-dai-q6-v2.c @@ -4140,9 +4140,9 @@ static int msm_auxpcm_dev_probe(struct platform_device *pdev) } auxpcm_pdata->mode_8k.slot_mapping = - kzalloc(sizeof(uint16_t) * - auxpcm_pdata->mode_8k.num_slots, - GFP_KERNEL); + kcalloc(auxpcm_pdata->mode_8k.num_slots, + sizeof(uint16_t), + GFP_KERNEL); if (!auxpcm_pdata->mode_8k.slot_mapping) { dev_err(&pdev->dev, "%s No mem for mode_8k slot mapping\n", __func__); @@ -4155,9 +4155,9 @@ static int msm_auxpcm_dev_probe(struct platform_device *pdev) (u16)be32_to_cpu(slot_mapping_array[i]); auxpcm_pdata->mode_16k.slot_mapping = - kzalloc(sizeof(uint16_t) * - auxpcm_pdata->mode_16k.num_slots, - GFP_KERNEL); + kcalloc(auxpcm_pdata->mode_16k.num_slots, + sizeof(uint16_t), + GFP_KERNEL); if (!auxpcm_pdata->mode_16k.slot_mapping) { dev_err(&pdev->dev, "%s No mem for mode_16k slot mapping\n", diff --git a/techpack/audio/asoc/msm-lsm-client.c b/techpack/audio/asoc/msm-lsm-client.c index 6cc8d43575c9..db355ec679f6 100644 --- a/techpack/audio/asoc/msm-lsm-client.c +++ b/techpack/audio/asoc/msm-lsm-client.c @@ -2535,7 +2535,7 @@ static int msm_lsm_send_ch_mix_config(struct snd_pcm_substream *substream) return 0; } - ch_wght_coeff = kzalloc(in_params->num_chs * pp_ch_cnt * sizeof(int), + ch_wght_coeff = kcalloc(in_params->num_chs * pp_ch_cnt, sizeof(int), GFP_KERNEL); if (!ch_wght_coeff) return -ENOMEM; diff --git a/techpack/audio/dsp/elliptic/elliptic.c b/techpack/audio/dsp/elliptic/elliptic.c index 4d018c1b8abc..8cb5f9d219c5 100755 --- a/techpack/audio/dsp/elliptic/elliptic.c +++ b/techpack/audio/dsp/elliptic/elliptic.c @@ -726,7 +726,7 @@ int __init elliptic_driver_init(void) goto fail; elliptic_devices = (struct elliptic_device *) - kzalloc(sizeof(struct elliptic_device) * ELLIPTIC_NUM_DEVICES, + kcalloc(ELLIPTIC_NUM_DEVICES, sizeof(struct elliptic_device), GFP_KERNEL); if (elliptic_devices == NULL) { diff --git a/techpack/audio/dsp/q6asm.c b/techpack/audio/dsp/q6asm.c index 6e4fb70f5f3f..34cf5768745e 100644 --- a/techpack/audio/dsp/q6asm.c +++ b/techpack/audio/dsp/q6asm.c @@ -8328,7 +8328,7 @@ static int q6asm_memory_map_regions(struct audio_client *ac, int dir, return -EINVAL; } - buffer_node = kzalloc(sizeof(struct asm_buffer_node) * bufcnt, + buffer_node = kcalloc(bufcnt, sizeof(struct asm_buffer_node), GFP_KERNEL); if (!buffer_node) return -ENOMEM; diff --git a/techpack/audio/dsp/q6lsm.c b/techpack/audio/dsp/q6lsm.c index aa864ddbee7b..dd6801af4e5e 100644 --- a/techpack/audio/dsp/q6lsm.c +++ b/techpack/audio/dsp/q6lsm.c @@ -2476,8 +2476,9 @@ int q6lsm_lab_buffer_alloc(struct lsm_client *client, bool alloc) out_params->buf_sz; allocate_size = PAGE_ALIGN(allocate_size); client->lab_buffer = - kzalloc(sizeof(struct lsm_lab_buffer) * - out_params->period_count, GFP_KERNEL); + kcalloc(out_params->period_count, + sizeof(struct lsm_lab_buffer), + GFP_KERNEL); if (!client->lab_buffer) { pr_err("%s: memory allocation for lab buffer failed count %d\n" , __func__, diff --git a/techpack/audio/dsp/q6usm.c b/techpack/audio/dsp/q6usm.c index 61e3bb96596b..e6d5a6779d80 100644 --- a/techpack/audio/dsp/q6usm.c +++ b/techpack/audio/dsp/q6usm.c @@ -314,7 +314,7 @@ struct us_client *q6usm_us_client_alloc( if (usc == NULL) return NULL; - p_mem_handle = kzalloc(sizeof(uint32_t) * 4, GFP_KERNEL); + p_mem_handle = kcalloc(4, sizeof(uint32_t), GFP_KERNEL); if (p_mem_handle == NULL) { kfree(usc); return NULL; diff --git a/techpack/data/drivers/emac-dwc-eqos/DWC_ETH_QOS_desc.c b/techpack/data/drivers/emac-dwc-eqos/DWC_ETH_QOS_desc.c index 3ee861820615..c9ae8247729e 100644 --- a/techpack/data/drivers/emac-dwc-eqos/DWC_ETH_QOS_desc.c +++ b/techpack/data/drivers/emac-dwc-eqos/DWC_ETH_QOS_desc.c @@ -127,8 +127,9 @@ static int DWC_ETH_QOS_alloc_rx_queue_struct(struct DWC_ETH_QOS_prv_data *pdata) DBGPR("rx_queue_cnt = %d\n", pdata->rx_queue_cnt); pdata->rx_queue = - kzalloc(sizeof(struct DWC_ETH_QOS_rx_queue) * pdata->rx_queue_cnt, - GFP_KERNEL); + kcalloc(pdata->rx_queue_cnt, + sizeof(struct DWC_ETH_QOS_rx_queue), + GFP_KERNEL); if (pdata->rx_queue == NULL) { IPCERR_RL("ERROR: Unable to allocate Rx queue structure\n"); ret = -ENOMEM; @@ -144,7 +145,8 @@ static int DWC_ETH_QOS_alloc_rx_queue_struct(struct DWC_ETH_QOS_prv_data *pdata) /* Alocate rx_desc_ptrs */ rx_desc_data->rx_desc_ptrs = - kzalloc(sizeof(struct s_RX_NORMAL_DESC *) * pdata->rx_queue[chInx].desc_cnt, + kcalloc(pdata->rx_queue[chInx].desc_cnt, + sizeof(struct s_RX_NORMAL_DESC *), GFP_KERNEL); if (rx_desc_data->rx_desc_ptrs == NULL) { IPCERR_RL("ERROR: Unable to allocate Rx Desc ptrs\n"); @@ -159,7 +161,8 @@ static int DWC_ETH_QOS_alloc_rx_queue_struct(struct DWC_ETH_QOS_prv_data *pdata) /* Alocate rx_desc_dma_addrs */ rx_desc_data->rx_desc_dma_addrs = - kzalloc(sizeof(dma_addr_t) *pdata->rx_queue[chInx].desc_cnt, + kcalloc(pdata->rx_queue[chInx].desc_cnt, + sizeof(dma_addr_t), GFP_KERNEL); if (rx_desc_data->rx_desc_dma_addrs == NULL) { IPCERR_RL("ERROR: Unable to allocate Rx Desc dma addr\n"); @@ -174,7 +177,8 @@ static int DWC_ETH_QOS_alloc_rx_queue_struct(struct DWC_ETH_QOS_prv_data *pdata) /* Alocate rx_buf_ptrs */ rx_desc_data->rx_buf_ptrs = - kzalloc(sizeof(struct DWC_ETH_QOS_rx_buffer *) * pdata->rx_queue[chInx].desc_cnt, + kcalloc(pdata->rx_queue[chInx].desc_cnt, + sizeof(struct DWC_ETH_QOS_rx_buffer *), GFP_KERNEL); if (rx_desc_data->rx_buf_ptrs == NULL) { IPCERR_RL("ERROR: Unable to allocate Rx Desc dma addr\n"); @@ -190,7 +194,9 @@ static int DWC_ETH_QOS_alloc_rx_queue_struct(struct DWC_ETH_QOS_prv_data *pdata) if (pdata->ipa_enabled) { /* Allocate ipa_rx_buff_pool_va_addrs_base */ rx_desc_data->ipa_rx_buff_pool_va_addrs_base = - kzalloc(sizeof(void *) * pdata->rx_queue[chInx].desc_cnt, GFP_KERNEL); + kcalloc(pdata->rx_queue[chInx].desc_cnt, + sizeof(void *), + GFP_KERNEL); if (rx_desc_data->ipa_rx_buff_pool_va_addrs_base == NULL) { IPCERR_RL("ERROR: Unable to allocate Rx ipa buff addrs\n"); ret = -ENOMEM; @@ -271,8 +277,9 @@ static int DWC_ETH_QOS_alloc_tx_queue_struct(struct DWC_ETH_QOS_prv_data *pdata) DBGPR("tx_queue_cnt = %d", pdata->tx_queue_cnt); pdata->tx_queue = - kzalloc(sizeof(struct DWC_ETH_QOS_tx_queue) * pdata->tx_queue_cnt, - GFP_KERNEL); + kcalloc(pdata->tx_queue_cnt, + sizeof(struct DWC_ETH_QOS_tx_queue), + GFP_KERNEL); if (pdata->tx_queue == NULL) { IPCERR_RL("ERROR: Unable to allocate Tx queue structure\n"); ret = -ENOMEM; @@ -288,7 +295,8 @@ static int DWC_ETH_QOS_alloc_tx_queue_struct(struct DWC_ETH_QOS_prv_data *pdata) /* Allocate tx_desc_ptrs */ tx_desc_data->tx_desc_ptrs = - kzalloc(sizeof(struct s_TX_NORMAL_DESC *) * pdata->tx_queue[chInx].desc_cnt, + kcalloc(pdata->tx_queue[chInx].desc_cnt, + sizeof(struct s_TX_NORMAL_DESC *), GFP_KERNEL); if (tx_desc_data->tx_desc_ptrs == NULL) { IPCERR_RL("ERROR: Unable to allocate Tx Desc ptrs\n"); @@ -302,7 +310,8 @@ static int DWC_ETH_QOS_alloc_tx_queue_struct(struct DWC_ETH_QOS_prv_data *pdata) /* Allocate tx_desc_dma_addrs */ tx_desc_data->tx_desc_dma_addrs = - kzalloc(sizeof(dma_addr_t) * pdata->tx_queue[chInx].desc_cnt, + kcalloc(pdata->tx_queue[chInx].desc_cnt, + sizeof(dma_addr_t), GFP_KERNEL); if (tx_desc_data->tx_desc_dma_addrs == NULL) { IPCERR_RL("ERROR: Unable to allocate Tx Desc dma addrs\n"); @@ -316,7 +325,8 @@ static int DWC_ETH_QOS_alloc_tx_queue_struct(struct DWC_ETH_QOS_prv_data *pdata) /* Allocate tx_buf_ptrs */ tx_desc_data->tx_buf_ptrs = - kzalloc(sizeof(struct DWC_ETH_QOS_tx_buffer *) * pdata->tx_queue[chInx].desc_cnt, + kcalloc(pdata->tx_queue[chInx].desc_cnt, + sizeof(struct DWC_ETH_QOS_tx_buffer *), GFP_KERNEL); if (tx_desc_data->tx_buf_ptrs == NULL) { IPCERR_RL("ERROR: Unable to allocate Tx buff ptrs\n"); @@ -331,7 +341,9 @@ static int DWC_ETH_QOS_alloc_tx_queue_struct(struct DWC_ETH_QOS_prv_data *pdata) if (pdata->ipa_enabled) { /* Allocate ipa_tx_buff_pool_va_addrs_base */ tx_desc_data->ipa_tx_buff_pool_va_addrs_base = - kzalloc(sizeof(void *) * pdata->tx_queue[chInx].desc_cnt,GFP_KERNEL); + kcalloc(pdata->tx_queue[chInx].desc_cnt, + sizeof(void *), + GFP_KERNEL); if (tx_desc_data->ipa_tx_buff_pool_va_addrs_base == NULL) { IPCERR_RL("ERROR: Unable to allocate Tx ipa buff addrs\n"); ret = -ENOMEM; From 99d27d6fb6638203416cbb15047f7056f7d91bcc Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 12 Jun 2018 14:04:20 -0700 Subject: [PATCH 575/592] treewide: kzalloc_node() -> kcalloc_node() The kzalloc_node() function has a 2-factor argument form, kcalloc_node(). This patch replaces cases of: kzalloc_node(a * b, gfp, node) with: kcalloc_node(a * b, gfp, node) as well as handling cases of: kzalloc_node(a * b * c, gfp, node) with: kzalloc_node(array3_size(a, b, c), gfp, node) as it's slightly less ugly than: kcalloc_node(array_size(a, b), c, gfp, node) This does, however, attempt to ignore constant size factors like: kzalloc_node(4 * 1024, gfp, node) though any constants defined via macros get caught up in the conversion. Any factors with a sizeof() of "unsigned char", "char", and "u8" were dropped, since they're redundant. The Coccinelle script used for this was: // Fix redundant parens around sizeof(). @@ type TYPE; expression THING, E; @@ ( kzalloc_node( - (sizeof(TYPE)) * E + sizeof(TYPE) * E , ...) | kzalloc_node( - (sizeof(THING)) * E + sizeof(THING) * E , ...) ) // Drop single-byte sizes and redundant parens. @@ expression COUNT; typedef u8; typedef __u8; @@ ( kzalloc_node( - sizeof(u8) * (COUNT) + COUNT , ...) | kzalloc_node( - sizeof(__u8) * (COUNT) + COUNT , ...) | kzalloc_node( - sizeof(char) * (COUNT) + COUNT , ...) | kzalloc_node( - sizeof(unsigned char) * (COUNT) + COUNT , ...) | kzalloc_node( - sizeof(u8) * COUNT + COUNT , ...) | kzalloc_node( - sizeof(__u8) * COUNT + COUNT , ...) | kzalloc_node( - sizeof(char) * COUNT + COUNT , ...) | kzalloc_node( - sizeof(unsigned char) * COUNT + COUNT , ...) ) // 2-factor product with sizeof(type/expression) and identifier or constant. @@ type TYPE; expression THING; identifier COUNT_ID; constant COUNT_CONST; @@ ( - kzalloc_node + kcalloc_node ( - sizeof(TYPE) * (COUNT_ID) + COUNT_ID, sizeof(TYPE) , ...) | - kzalloc_node + kcalloc_node ( - sizeof(TYPE) * COUNT_ID + COUNT_ID, sizeof(TYPE) , ...) | - kzalloc_node + kcalloc_node ( - sizeof(TYPE) * (COUNT_CONST) + COUNT_CONST, sizeof(TYPE) , ...) | - kzalloc_node + kcalloc_node ( - sizeof(TYPE) * COUNT_CONST + COUNT_CONST, sizeof(TYPE) , ...) | - kzalloc_node + kcalloc_node ( - sizeof(THING) * (COUNT_ID) + COUNT_ID, sizeof(THING) , ...) | - kzalloc_node + kcalloc_node ( - sizeof(THING) * COUNT_ID + COUNT_ID, sizeof(THING) , ...) | - kzalloc_node + kcalloc_node ( - sizeof(THING) * (COUNT_CONST) + COUNT_CONST, sizeof(THING) , ...) | - kzalloc_node + kcalloc_node ( - sizeof(THING) * COUNT_CONST + COUNT_CONST, sizeof(THING) , ...) ) // 2-factor product, only identifiers. @@ identifier SIZE, COUNT; @@ - kzalloc_node + kcalloc_node ( - SIZE * COUNT + COUNT, SIZE , ...) // 3-factor product with 1 sizeof(type) or sizeof(expression), with // redundant parens removed. @@ expression THING; identifier STRIDE, COUNT; type TYPE; @@ ( kzalloc_node( - sizeof(TYPE) * (COUNT) * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | kzalloc_node( - sizeof(TYPE) * (COUNT) * STRIDE + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | kzalloc_node( - sizeof(TYPE) * COUNT * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | kzalloc_node( - sizeof(TYPE) * COUNT * STRIDE + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | kzalloc_node( - sizeof(THING) * (COUNT) * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) | kzalloc_node( - sizeof(THING) * (COUNT) * STRIDE + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) | kzalloc_node( - sizeof(THING) * COUNT * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) | kzalloc_node( - sizeof(THING) * COUNT * STRIDE + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) ) // 3-factor product with 2 sizeof(variable), with redundant parens removed. @@ expression THING1, THING2; identifier COUNT; type TYPE1, TYPE2; @@ ( kzalloc_node( - sizeof(TYPE1) * sizeof(TYPE2) * COUNT + array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2)) , ...) | kzalloc_node( - sizeof(TYPE1) * sizeof(THING2) * (COUNT) + array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2)) , ...) | kzalloc_node( - sizeof(THING1) * sizeof(THING2) * COUNT + array3_size(COUNT, sizeof(THING1), sizeof(THING2)) , ...) | kzalloc_node( - sizeof(THING1) * sizeof(THING2) * (COUNT) + array3_size(COUNT, sizeof(THING1), sizeof(THING2)) , ...) | kzalloc_node( - sizeof(TYPE1) * sizeof(THING2) * COUNT + array3_size(COUNT, sizeof(TYPE1), sizeof(THING2)) , ...) | kzalloc_node( - sizeof(TYPE1) * sizeof(THING2) * (COUNT) + array3_size(COUNT, sizeof(TYPE1), sizeof(THING2)) , ...) ) // 3-factor product, only identifiers, with redundant parens removed. @@ identifier STRIDE, SIZE, COUNT; @@ ( kzalloc_node( - (COUNT) * STRIDE * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) | kzalloc_node( - COUNT * (STRIDE) * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) | kzalloc_node( - COUNT * STRIDE * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | kzalloc_node( - (COUNT) * (STRIDE) * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) | kzalloc_node( - COUNT * (STRIDE) * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | kzalloc_node( - (COUNT) * STRIDE * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | kzalloc_node( - (COUNT) * (STRIDE) * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | kzalloc_node( - COUNT * STRIDE * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) ) // Any remaining multi-factor products, first at least 3-factor products, // when they're not all constants... @@ expression E1, E2, E3; constant C1, C2, C3; @@ ( kzalloc_node(C1 * C2 * C3, ...) | kzalloc_node( - (E1) * E2 * E3 + array3_size(E1, E2, E3) , ...) | kzalloc_node( - (E1) * (E2) * E3 + array3_size(E1, E2, E3) , ...) | kzalloc_node( - (E1) * (E2) * (E3) + array3_size(E1, E2, E3) , ...) | kzalloc_node( - E1 * E2 * E3 + array3_size(E1, E2, E3) , ...) ) // And then all remaining 2 factors products when they're not all constants, // keeping sizeof() as the second factor argument. @@ expression THING, E1, E2; type TYPE; constant C1, C2, C3; @@ ( kzalloc_node(sizeof(THING) * C2, ...) | kzalloc_node(sizeof(TYPE) * C2, ...) | kzalloc_node(C1 * C2 * C3, ...) | kzalloc_node(C1 * C2, ...) | - kzalloc_node + kcalloc_node ( - sizeof(TYPE) * (E2) + E2, sizeof(TYPE) , ...) | - kzalloc_node + kcalloc_node ( - sizeof(TYPE) * E2 + E2, sizeof(TYPE) , ...) | - kzalloc_node + kcalloc_node ( - sizeof(THING) * (E2) + E2, sizeof(THING) , ...) | - kzalloc_node + kcalloc_node ( - sizeof(THING) * E2 + E2, sizeof(THING) , ...) | - kzalloc_node + kcalloc_node ( - (E1) * E2 + E1, E2 , ...) | - kzalloc_node + kcalloc_node ( - (E1) * (E2) + E1, E2 , ...) | - kzalloc_node + kcalloc_node ( - E1 * E2 + E1, E2 , ...) ) Signed-off-by: Kees Cook Signed-off-by: Adam W. Willis Signed-off-by: UtsavBalar1231 --- block/blk-mq.c | 16 ++++++++-------- drivers/crypto/cavium/nitrox/nitrox_isr.c | 2 +- drivers/crypto/qat/qat_common/adf_isr.c | 2 +- drivers/crypto/virtio/virtio_crypto_algs.c | 2 +- drivers/infiniband/hw/hfi1/init.c | 15 +++++++-------- drivers/infiniband/hw/hfi1/pio.c | 11 ++++++----- drivers/infiniband/hw/qib/qib_init.c | 4 ++-- drivers/infiniband/sw/rdmavt/qp.c | 9 ++++----- drivers/net/ethernet/chelsio/cxgb4/sge.c | 2 +- .../net/ethernet/mellanox/mlx5/core/en_main.c | 16 ++++++++-------- drivers/ntb/hw/amd/ntb_hw_amd.c | 4 ++-- drivers/ntb/hw/intel/ntb_hw_intel.c | 4 ++-- drivers/ntb/ntb_transport.c | 4 ++-- drivers/nvme/host/pci.c | 3 ++- drivers/staging/lustre/lustre/ptlrpc/service.c | 6 +++--- kernel/events/ring_buffer.c | 3 ++- lib/sbitmap.c | 2 +- 17 files changed, 53 insertions(+), 52 deletions(-) diff --git a/block/blk-mq.c b/block/blk-mq.c index 2992376e64c9..4d3264644d98 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -1815,7 +1815,7 @@ struct blk_mq_tags *blk_mq_alloc_rq_map(struct blk_mq_tag_set *set, if (!tags) return NULL; - tags->rqs = kzalloc_node(nr_tags * sizeof(struct request *), + tags->rqs = kcalloc_node(nr_tags, sizeof(struct request *), GFP_NOIO | __GFP_NOWARN | __GFP_NORETRY, node); if (!tags->rqs) { @@ -1823,9 +1823,9 @@ struct blk_mq_tags *blk_mq_alloc_rq_map(struct blk_mq_tag_set *set, return NULL; } - tags->static_rqs = kzalloc_node(nr_tags * sizeof(struct request *), - GFP_NOIO | __GFP_NOWARN | __GFP_NORETRY, - node); + tags->static_rqs = kcalloc_node(nr_tags, sizeof(struct request *), + GFP_NOIO | __GFP_NOWARN | __GFP_NORETRY, + node); if (!tags->static_rqs) { kfree(tags->rqs); blk_mq_free_tags(tags); @@ -2421,7 +2421,7 @@ struct request_queue *blk_mq_init_allocated_queue(struct blk_mq_tag_set *set, /* init q->mq_kobj and sw queues' kobjects */ blk_mq_sysfs_init(q); - q->queue_hw_ctx = kzalloc_node(nr_cpu_ids * sizeof(*(q->queue_hw_ctx)), + q->queue_hw_ctx = kcalloc_node(nr_cpu_ids, sizeof(*(q->queue_hw_ctx)), GFP_KERNEL, set->numa_node); if (!q->queue_hw_ctx) goto err_percpu; @@ -2636,14 +2636,14 @@ int blk_mq_alloc_tag_set(struct blk_mq_tag_set *set) if (set->nr_hw_queues > nr_cpu_ids) set->nr_hw_queues = nr_cpu_ids; - set->tags = kzalloc_node(nr_cpu_ids * sizeof(struct blk_mq_tags *), + set->tags = kcalloc_node(nr_cpu_ids, sizeof(struct blk_mq_tags *), GFP_KERNEL, set->numa_node); if (!set->tags) return -ENOMEM; ret = -ENOMEM; - set->mq_map = kzalloc_node(sizeof(*set->mq_map) * nr_cpu_ids, - GFP_KERNEL, set->numa_node); + set->mq_map = kcalloc_node(nr_cpu_ids, sizeof(*set->mq_map), + GFP_KERNEL, set->numa_node); if (!set->mq_map) goto out_free_tags; diff --git a/drivers/crypto/cavium/nitrox/nitrox_isr.c b/drivers/crypto/cavium/nitrox/nitrox_isr.c index dbead5f45df3..ee0d70ba25d5 100644 --- a/drivers/crypto/cavium/nitrox/nitrox_isr.c +++ b/drivers/crypto/cavium/nitrox/nitrox_isr.c @@ -254,7 +254,7 @@ static int nitrox_enable_msix(struct nitrox_device *ndev) * Entry 192: NPS_CORE_INT_ACTIVE */ nr_entries = (ndev->nr_queues * NR_RING_VECTORS) + 1; - entries = kzalloc_node(nr_entries * sizeof(struct msix_entry), + entries = kcalloc_node(nr_entries, sizeof(struct msix_entry), GFP_KERNEL, ndev->node); if (!entries) return -ENOMEM; diff --git a/drivers/crypto/qat/qat_common/adf_isr.c b/drivers/crypto/qat/qat_common/adf_isr.c index 06d49017a52b..cd1cdf5305bc 100644 --- a/drivers/crypto/qat/qat_common/adf_isr.c +++ b/drivers/crypto/qat/qat_common/adf_isr.c @@ -238,7 +238,7 @@ static int adf_isr_alloc_msix_entry_table(struct adf_accel_dev *accel_dev) if (!accel_dev->pf.vf_info) msix_num_entries += hw_data->num_banks; - entries = kzalloc_node(msix_num_entries * sizeof(*entries), + entries = kcalloc_node(msix_num_entries, sizeof(*entries), GFP_KERNEL, dev_to_node(&GET_DEV(accel_dev))); if (!entries) return -ENOMEM; diff --git a/drivers/crypto/virtio/virtio_crypto_algs.c b/drivers/crypto/virtio/virtio_crypto_algs.c index e6b889ce395e..7205c05324fe 100644 --- a/drivers/crypto/virtio/virtio_crypto_algs.c +++ b/drivers/crypto/virtio/virtio_crypto_algs.c @@ -373,7 +373,7 @@ __virtio_crypto_ablkcipher_do_req(struct virtio_crypto_sym_request *vc_sym_req, /* Why 3? outhdr + iv + inhdr */ sg_total = src_nents + dst_nents + 3; - sgs = kzalloc_node(sg_total * sizeof(*sgs), GFP_ATOMIC, + sgs = kcalloc_node(sg_total, sizeof(*sgs), GFP_ATOMIC, dev_to_node(&vcrypto->vdev->dev)); if (!sgs) return -ENOMEM; diff --git a/drivers/infiniband/hw/hfi1/init.c b/drivers/infiniband/hw/hfi1/init.c index 27e7de4c4a34..c9b73c339665 100644 --- a/drivers/infiniband/hw/hfi1/init.c +++ b/drivers/infiniband/hw/hfi1/init.c @@ -174,7 +174,7 @@ int hfi1_create_kctxts(struct hfi1_devdata *dd) u16 i; int ret; - dd->rcd = kzalloc_node(dd->num_rcv_contexts * sizeof(*dd->rcd), + dd->rcd = kcalloc_node(dd->num_rcv_contexts, sizeof(*dd->rcd), GFP_KERNEL, dd->node); if (!dd->rcd) return -ENOMEM; @@ -424,15 +424,14 @@ int hfi1_create_ctxtdata(struct hfi1_pportdata *ppd, int numa, * The resulting value will be rounded down to the closest * multiple of dd->rcv_entries.group_size. */ - rcd->egrbufs.buffers = kzalloc_node( - rcd->egrbufs.count * sizeof(*rcd->egrbufs.buffers), - GFP_KERNEL, numa); + rcd->egrbufs.buffers = kcalloc_node(rcd->egrbufs.count, + sizeof(*rcd->egrbufs.buffers), + GFP_KERNEL, numa); if (!rcd->egrbufs.buffers) goto bail; - rcd->egrbufs.rcvtids = kzalloc_node( - rcd->egrbufs.count * - sizeof(*rcd->egrbufs.rcvtids), - GFP_KERNEL, numa); + rcd->egrbufs.rcvtids = kcalloc_node(rcd->egrbufs.count, + sizeof(*rcd->egrbufs.rcvtids), + GFP_KERNEL, numa); if (!rcd->egrbufs.rcvtids) goto bail; rcd->egrbufs.size = eager_buffer_size; diff --git a/drivers/infiniband/hw/hfi1/pio.c b/drivers/infiniband/hw/hfi1/pio.c index 07bf282fd8aa..f90d0f8244d8 100644 --- a/drivers/infiniband/hw/hfi1/pio.c +++ b/drivers/infiniband/hw/hfi1/pio.c @@ -876,8 +876,9 @@ struct send_context *sc_alloc(struct hfi1_devdata *dd, int type, * so head == tail can mean empty. */ sc->sr_size = sci->credits + 1; - sc->sr = kzalloc_node(sizeof(union pio_shadow_ring) * - sc->sr_size, GFP_KERNEL, numa); + sc->sr = kcalloc_node(sc->sr_size, + sizeof(union pio_shadow_ring), + GFP_KERNEL, numa); if (!sc->sr) { sc_free(sc); return NULL; @@ -2030,9 +2031,9 @@ int init_pervl_scs(struct hfi1_devdata *dd) hfi1_init_ctxt(dd->vld[15].sc); dd->vld[15].mtu = enum_to_mtu(OPA_MTU_2048); - dd->kernel_send_context = kzalloc_node(dd->num_send_contexts * - sizeof(struct send_context *), - GFP_KERNEL, dd->node); + dd->kernel_send_context = kcalloc_node(dd->num_send_contexts, + sizeof(struct send_context *), + GFP_KERNEL, dd->node); if (!dd->kernel_send_context) goto freesc15; diff --git a/drivers/infiniband/hw/qib/qib_init.c b/drivers/infiniband/hw/qib/qib_init.c index adfd6852a870..9e1d9435d865 100644 --- a/drivers/infiniband/hw/qib/qib_init.c +++ b/drivers/infiniband/hw/qib/qib_init.c @@ -1680,8 +1680,8 @@ int qib_setup_eagerbufs(struct qib_ctxtdata *rcd) size = rcd->rcvegrbuf_size; if (!rcd->rcvegrbuf) { rcd->rcvegrbuf = - kzalloc_node(chunk * sizeof(rcd->rcvegrbuf[0]), - GFP_KERNEL, rcd->node_id); + kcalloc_node(chunk, sizeof(rcd->rcvegrbuf[0]), + GFP_KERNEL, rcd->node_id); if (!rcd->rcvegrbuf) goto bail; } diff --git a/drivers/infiniband/sw/rdmavt/qp.c b/drivers/infiniband/sw/rdmavt/qp.c index b13cd11c39ca..071496dac63e 100644 --- a/drivers/infiniband/sw/rdmavt/qp.c +++ b/drivers/infiniband/sw/rdmavt/qp.c @@ -837,11 +837,10 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd, RCU_INIT_POINTER(qp->next, NULL); if (init_attr->qp_type == IB_QPT_RC) { qp->s_ack_queue = - kzalloc_node( - sizeof(*qp->s_ack_queue) * - rvt_max_atomic(rdi), - GFP_KERNEL, - rdi->dparms.node); + kcalloc_node(rvt_max_atomic(rdi), + sizeof(*qp->s_ack_queue), + GFP_KERNEL, + rdi->dparms.node); if (!qp->s_ack_queue) goto bail_qp; } diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c index 006f8b8aaa7d..66ae40df1aea 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c @@ -708,7 +708,7 @@ static void *alloc_ring(struct device *dev, size_t nelem, size_t elem_size, if (!p) return NULL; if (sw_size) { - s = kzalloc_node(nelem * sw_size, GFP_KERNEL, node); + s = kcalloc_node(sw_size, nelem, GFP_KERNEL, node); if (!s) { dma_free_coherent(dev, len, p, *phys); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 14bab8a5550d..65820fca1361 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -449,14 +449,14 @@ static int mlx5e_rq_alloc_mpwqe_info(struct mlx5e_rq *rq, int mtt_alloc = mtt_sz + MLX5_UMR_ALIGN - 1; int i; - rq->mpwqe.info = kzalloc_node(wq_sz * sizeof(*rq->mpwqe.info), + rq->mpwqe.info = kcalloc_node(wq_sz, sizeof(*rq->mpwqe.info), GFP_KERNEL, cpu_to_node(c->cpu)); if (!rq->mpwqe.info) goto err_out; /* We allocate more than mtt_sz as we will align the pointer */ - rq->mpwqe.mtt_no_align = kzalloc_node(mtt_alloc * wq_sz, GFP_KERNEL, - cpu_to_node(c->cpu)); + rq->mpwqe.mtt_no_align = kcalloc_node(wq_sz, mtt_alloc, GFP_KERNEL, + cpu_to_node(c->cpu)); if (unlikely(!rq->mpwqe.mtt_no_align)) goto err_free_wqe_info; @@ -629,7 +629,7 @@ static int mlx5e_alloc_rq(struct mlx5e_channel *c, break; default: /* MLX5_WQ_TYPE_LINKED_LIST */ rq->wqe.frag_info = - kzalloc_node(wq_sz * sizeof(*rq->wqe.frag_info), + kcalloc_node(wq_sz, sizeof(*rq->wqe.frag_info), GFP_KERNEL, cpu_to_node(c->cpu)); if (!rq->wqe.frag_info) { err = -ENOMEM; @@ -975,7 +975,7 @@ static int mlx5e_alloc_xdpsq_db(struct mlx5e_xdpsq *sq, int numa) { int wq_sz = mlx5_wq_cyc_get_size(&sq->wq); - sq->db.di = kzalloc_node(sizeof(*sq->db.di) * wq_sz, + sq->db.di = kcalloc_node(wq_sz, sizeof(*sq->db.di), GFP_KERNEL, numa); if (!sq->db.di) { mlx5e_free_xdpsq_db(sq); @@ -1033,7 +1033,7 @@ static int mlx5e_alloc_icosq_db(struct mlx5e_icosq *sq, int numa) { u8 wq_sz = mlx5_wq_cyc_get_size(&sq->wq); - sq->db.ico_wqe = kzalloc_node(sizeof(*sq->db.ico_wqe) * wq_sz, + sq->db.ico_wqe = kcalloc_node(wq_sz, sizeof(*sq->db.ico_wqe), GFP_KERNEL, numa); if (!sq->db.ico_wqe) return -ENOMEM; @@ -1090,9 +1090,9 @@ static int mlx5e_alloc_txqsq_db(struct mlx5e_txqsq *sq, int numa) int wq_sz = mlx5_wq_cyc_get_size(&sq->wq); int df_sz = wq_sz * MLX5_SEND_WQEBB_NUM_DS; - sq->db.dma_fifo = kzalloc_node(df_sz * sizeof(*sq->db.dma_fifo), + sq->db.dma_fifo = kcalloc_node(df_sz, sizeof(*sq->db.dma_fifo), GFP_KERNEL, numa); - sq->db.wqe_info = kzalloc_node(wq_sz * sizeof(*sq->db.wqe_info), + sq->db.wqe_info = kcalloc_node(wq_sz, sizeof(*sq->db.wqe_info), GFP_KERNEL, numa); if (!sq->db.dma_fifo || !sq->db.wqe_info) { mlx5e_free_txqsq_db(sq); diff --git a/drivers/ntb/hw/amd/ntb_hw_amd.c b/drivers/ntb/hw/amd/ntb_hw_amd.c index f0788aae05c9..16c10dfe0919 100644 --- a/drivers/ntb/hw/amd/ntb_hw_amd.c +++ b/drivers/ntb/hw/amd/ntb_hw_amd.c @@ -592,12 +592,12 @@ static int ndev_init_isr(struct amd_ntb_dev *ndev, ndev->db_mask = ndev->db_valid_mask; /* Try to set up msix irq */ - ndev->vec = kzalloc_node(msix_max * sizeof(*ndev->vec), + ndev->vec = kcalloc_node(msix_max, sizeof(*ndev->vec), GFP_KERNEL, node); if (!ndev->vec) goto err_msix_vec_alloc; - ndev->msix = kzalloc_node(msix_max * sizeof(*ndev->msix), + ndev->msix = kcalloc_node(msix_max, sizeof(*ndev->msix), GFP_KERNEL, node); if (!ndev->msix) goto err_msix_alloc; diff --git a/drivers/ntb/hw/intel/ntb_hw_intel.c b/drivers/ntb/hw/intel/ntb_hw_intel.c index 58068f1447bb..156707195fad 100644 --- a/drivers/ntb/hw/intel/ntb_hw_intel.c +++ b/drivers/ntb/hw/intel/ntb_hw_intel.c @@ -463,12 +463,12 @@ static int ndev_init_isr(struct intel_ntb_dev *ndev, /* Try to set up msix irq */ - ndev->vec = kzalloc_node(msix_max * sizeof(*ndev->vec), + ndev->vec = kcalloc_node(msix_max, sizeof(*ndev->vec), GFP_KERNEL, node); if (!ndev->vec) goto err_msix_vec_alloc; - ndev->msix = kzalloc_node(msix_max * sizeof(*ndev->msix), + ndev->msix = kcalloc_node(msix_max, sizeof(*ndev->msix), GFP_KERNEL, node); if (!ndev->msix) goto err_msix_alloc; diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c index 18339b7e88a4..ad65cb7ddf9d 100644 --- a/drivers/ntb/ntb_transport.c +++ b/drivers/ntb/ntb_transport.c @@ -1097,7 +1097,7 @@ static int ntb_transport_probe(struct ntb_client *self, struct ntb_dev *ndev) max_mw_count_for_spads = (spad_count - MW0_SZ_HIGH) / 2; nt->mw_count = min(mw_count, max_mw_count_for_spads); - nt->mw_vec = kzalloc_node(mw_count * sizeof(*nt->mw_vec), + nt->mw_vec = kcalloc_node(mw_count, sizeof(*nt->mw_vec), GFP_KERNEL, node); if (!nt->mw_vec) { rc = -ENOMEM; @@ -1143,7 +1143,7 @@ static int ntb_transport_probe(struct ntb_client *self, struct ntb_dev *ndev) nt->qp_bitmap = qp_bitmap; nt->qp_bitmap_free = qp_bitmap; - nt->qp_vec = kzalloc_node(qp_count * sizeof(*nt->qp_vec), + nt->qp_vec = kcalloc_node(qp_count, sizeof(*nt->qp_vec), GFP_KERNEL, node); if (!nt->qp_vec) { rc = -ENOMEM; diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index b144c86f5a78..4c0b8e58b2b2 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -2352,7 +2352,8 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (!dev) return -ENOMEM; - dev->queues = kzalloc_node((num_possible_cpus() + 1) * sizeof(struct nvme_queue), + dev->queues = kcalloc_node(num_possible_cpus() + 1, + sizeof(struct nvme_queue), GFP_KERNEL, node); if (!dev->queues) goto free; diff --git a/drivers/staging/lustre/lustre/ptlrpc/service.c b/drivers/staging/lustre/lustre/ptlrpc/service.c index 155f6a45cc8b..e1fffc76be02 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/service.c +++ b/drivers/staging/lustre/lustre/ptlrpc/service.c @@ -491,7 +491,7 @@ ptlrpc_service_part_init(struct ptlrpc_service *svc, /* allocate memory for scp_at_array (ptlrpc_at_array) */ array->paa_reqs_array = - kzalloc_node(sizeof(struct list_head) * size, GFP_NOFS, + kcalloc_node(size, sizeof(struct list_head), GFP_NOFS, cfs_cpt_spread_node(svc->srv_cptable, cpt)); if (!array->paa_reqs_array) return -ENOMEM; @@ -500,7 +500,7 @@ ptlrpc_service_part_init(struct ptlrpc_service *svc, INIT_LIST_HEAD(&array->paa_reqs_array[index]); array->paa_reqs_count = - kzalloc_node(sizeof(__u32) * size, GFP_NOFS, + kcalloc_node(size, sizeof(__u32), GFP_NOFS, cfs_cpt_spread_node(svc->srv_cptable, cpt)); if (!array->paa_reqs_count) goto free_reqs_array; @@ -2540,7 +2540,7 @@ int ptlrpc_hr_init(void) hrp->hrp_nthrs = 1; hrp->hrp_thrs = - kzalloc_node(hrp->hrp_nthrs * sizeof(*hrt), GFP_NOFS, + kcalloc_node(hrp->hrp_nthrs, sizeof(*hrt), GFP_NOFS, cfs_cpt_spread_node(ptlrpc_hr.hr_cpt_table, i)); if (!hrp->hrp_thrs) { diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c index 20f6a50fb40b..2a5ff6e6e02d 100644 --- a/kernel/events/ring_buffer.c +++ b/kernel/events/ring_buffer.c @@ -635,7 +635,8 @@ int rb_alloc_aux(struct ring_buffer *rb, struct perf_event *event, } } - rb->aux_pages = kzalloc_node(nr_pages * sizeof(void *), GFP_KERNEL, node); + rb->aux_pages = kcalloc_node(nr_pages, sizeof(void *), GFP_KERNEL, + node); if (!rb->aux_pages) return -ENOMEM; diff --git a/lib/sbitmap.c b/lib/sbitmap.c index 5abaa9a3ba29..4dadde573b24 100644 --- a/lib/sbitmap.c +++ b/lib/sbitmap.c @@ -52,7 +52,7 @@ int sbitmap_init_node(struct sbitmap *sb, unsigned int depth, int shift, return 0; } - sb->map = kzalloc_node(sb->map_nr * sizeof(*sb->map), flags, node); + sb->map = kcalloc_node(sb->map_nr, sizeof(*sb->map), flags, node); if (!sb->map) return -ENOMEM; From 5c8d620f29f0e07fcb68b7d81ca71b4fc28f81ee Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 12 Jun 2018 14:04:32 -0700 Subject: [PATCH 576/592] treewide: kvmalloc() -> kvmalloc_array() The kvmalloc() function has a 2-factor argument form, kvmalloc_array(). This patch replaces cases of: kvmalloc(a * b, gfp) with: kvmalloc_array(a * b, gfp) as well as handling cases of: kvmalloc(a * b * c, gfp) with: kvmalloc(array3_size(a, b, c), gfp) as it's slightly less ugly than: kvmalloc_array(array_size(a, b), c, gfp) This does, however, attempt to ignore constant size factors like: kvmalloc(4 * 1024, gfp) though any constants defined via macros get caught up in the conversion. Any factors with a sizeof() of "unsigned char", "char", and "u8" were dropped, since they're redundant. The Coccinelle script used for this was: // Fix redundant parens around sizeof(). @@ type TYPE; expression THING, E; @@ ( kvmalloc( - (sizeof(TYPE)) * E + sizeof(TYPE) * E , ...) | kvmalloc( - (sizeof(THING)) * E + sizeof(THING) * E , ...) ) // Drop single-byte sizes and redundant parens. @@ expression COUNT; typedef u8; typedef __u8; @@ ( kvmalloc( - sizeof(u8) * (COUNT) + COUNT , ...) | kvmalloc( - sizeof(__u8) * (COUNT) + COUNT , ...) | kvmalloc( - sizeof(char) * (COUNT) + COUNT , ...) | kvmalloc( - sizeof(unsigned char) * (COUNT) + COUNT , ...) | kvmalloc( - sizeof(u8) * COUNT + COUNT , ...) | kvmalloc( - sizeof(__u8) * COUNT + COUNT , ...) | kvmalloc( - sizeof(char) * COUNT + COUNT , ...) | kvmalloc( - sizeof(unsigned char) * COUNT + COUNT , ...) ) // 2-factor product with sizeof(type/expression) and identifier or constant. @@ type TYPE; expression THING; identifier COUNT_ID; constant COUNT_CONST; @@ ( - kvmalloc + kvmalloc_array ( - sizeof(TYPE) * (COUNT_ID) + COUNT_ID, sizeof(TYPE) , ...) | - kvmalloc + kvmalloc_array ( - sizeof(TYPE) * COUNT_ID + COUNT_ID, sizeof(TYPE) , ...) | - kvmalloc + kvmalloc_array ( - sizeof(TYPE) * (COUNT_CONST) + COUNT_CONST, sizeof(TYPE) , ...) | - kvmalloc + kvmalloc_array ( - sizeof(TYPE) * COUNT_CONST + COUNT_CONST, sizeof(TYPE) , ...) | - kvmalloc + kvmalloc_array ( - sizeof(THING) * (COUNT_ID) + COUNT_ID, sizeof(THING) , ...) | - kvmalloc + kvmalloc_array ( - sizeof(THING) * COUNT_ID + COUNT_ID, sizeof(THING) , ...) | - kvmalloc + kvmalloc_array ( - sizeof(THING) * (COUNT_CONST) + COUNT_CONST, sizeof(THING) , ...) | - kvmalloc + kvmalloc_array ( - sizeof(THING) * COUNT_CONST + COUNT_CONST, sizeof(THING) , ...) ) // 2-factor product, only identifiers. @@ identifier SIZE, COUNT; @@ - kvmalloc + kvmalloc_array ( - SIZE * COUNT + COUNT, SIZE , ...) // 3-factor product with 1 sizeof(type) or sizeof(expression), with // redundant parens removed. @@ expression THING; identifier STRIDE, COUNT; type TYPE; @@ ( kvmalloc( - sizeof(TYPE) * (COUNT) * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | kvmalloc( - sizeof(TYPE) * (COUNT) * STRIDE + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | kvmalloc( - sizeof(TYPE) * COUNT * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | kvmalloc( - sizeof(TYPE) * COUNT * STRIDE + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | kvmalloc( - sizeof(THING) * (COUNT) * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) | kvmalloc( - sizeof(THING) * (COUNT) * STRIDE + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) | kvmalloc( - sizeof(THING) * COUNT * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) | kvmalloc( - sizeof(THING) * COUNT * STRIDE + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) ) // 3-factor product with 2 sizeof(variable), with redundant parens removed. @@ expression THING1, THING2; identifier COUNT; type TYPE1, TYPE2; @@ ( kvmalloc( - sizeof(TYPE1) * sizeof(TYPE2) * COUNT + array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2)) , ...) | kvmalloc( - sizeof(TYPE1) * sizeof(THING2) * (COUNT) + array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2)) , ...) | kvmalloc( - sizeof(THING1) * sizeof(THING2) * COUNT + array3_size(COUNT, sizeof(THING1), sizeof(THING2)) , ...) | kvmalloc( - sizeof(THING1) * sizeof(THING2) * (COUNT) + array3_size(COUNT, sizeof(THING1), sizeof(THING2)) , ...) | kvmalloc( - sizeof(TYPE1) * sizeof(THING2) * COUNT + array3_size(COUNT, sizeof(TYPE1), sizeof(THING2)) , ...) | kvmalloc( - sizeof(TYPE1) * sizeof(THING2) * (COUNT) + array3_size(COUNT, sizeof(TYPE1), sizeof(THING2)) , ...) ) // 3-factor product, only identifiers, with redundant parens removed. @@ identifier STRIDE, SIZE, COUNT; @@ ( kvmalloc( - (COUNT) * STRIDE * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) | kvmalloc( - COUNT * (STRIDE) * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) | kvmalloc( - COUNT * STRIDE * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | kvmalloc( - (COUNT) * (STRIDE) * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) | kvmalloc( - COUNT * (STRIDE) * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | kvmalloc( - (COUNT) * STRIDE * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | kvmalloc( - (COUNT) * (STRIDE) * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | kvmalloc( - COUNT * STRIDE * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) ) // Any remaining multi-factor products, first at least 3-factor products, // when they're not all constants... @@ expression E1, E2, E3; constant C1, C2, C3; @@ ( kvmalloc(C1 * C2 * C3, ...) | kvmalloc( - (E1) * E2 * E3 + array3_size(E1, E2, E3) , ...) | kvmalloc( - (E1) * (E2) * E3 + array3_size(E1, E2, E3) , ...) | kvmalloc( - (E1) * (E2) * (E3) + array3_size(E1, E2, E3) , ...) | kvmalloc( - E1 * E2 * E3 + array3_size(E1, E2, E3) , ...) ) // And then all remaining 2 factors products when they're not all constants, // keeping sizeof() as the second factor argument. @@ expression THING, E1, E2; type TYPE; constant C1, C2, C3; @@ ( kvmalloc(sizeof(THING) * C2, ...) | kvmalloc(sizeof(TYPE) * C2, ...) | kvmalloc(C1 * C2 * C3, ...) | kvmalloc(C1 * C2, ...) | - kvmalloc + kvmalloc_array ( - sizeof(TYPE) * (E2) + E2, sizeof(TYPE) , ...) | - kvmalloc + kvmalloc_array ( - sizeof(TYPE) * E2 + E2, sizeof(TYPE) , ...) | - kvmalloc + kvmalloc_array ( - sizeof(THING) * (E2) + E2, sizeof(THING) , ...) | - kvmalloc + kvmalloc_array ( - sizeof(THING) * E2 + E2, sizeof(THING) , ...) | - kvmalloc + kvmalloc_array ( - (E1) * E2 + E1, E2 , ...) | - kvmalloc + kvmalloc_array ( - (E1) * (E2) + E1, E2 , ...) | - kvmalloc + kvmalloc_array ( - E1 * E2 + E1, E2 , ...) ) Signed-off-by: Kees Cook Signed-off-by: Adam W. Willis Signed-off-by: UtsavBalar1231 --- block/blk-zoned.c | 4 ++-- drivers/acpi/apei/erst.c | 3 ++- drivers/md/dm-integrity.c | 15 +++++++++++---- drivers/xen/evtchn.c | 2 +- fs/ceph/file.c | 2 +- ipc/sem.c | 2 +- lib/rhashtable.c | 3 ++- mm/list_lru.c | 4 ++-- net/ipv6/ila/ila_xlat.c | 3 ++- .../src/compat/ptr_ring/include/linux/ptr_ring.h | 2 +- 10 files changed, 25 insertions(+), 15 deletions(-) diff --git a/block/blk-zoned.c b/block/blk-zoned.c index 77fce6f09f78..5fa41d42bf53 100644 --- a/block/blk-zoned.c +++ b/block/blk-zoned.c @@ -289,8 +289,8 @@ int blkdev_report_zones_ioctl(struct block_device *bdev, fmode_t mode, if (rep.nr_zones > INT_MAX / sizeof(struct blk_zone)) return -ERANGE; - zones = kvmalloc(rep.nr_zones * sizeof(struct blk_zone), - GFP_KERNEL | __GFP_ZERO); + zones = kvmalloc_array(rep.nr_zones, sizeof(struct blk_zone), + GFP_KERNEL | __GFP_ZERO); if (!zones) return -ENOMEM; diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c index 5b149d2d52f4..7115562de78e 100644 --- a/drivers/acpi/apei/erst.c +++ b/drivers/acpi/apei/erst.c @@ -524,7 +524,8 @@ retry: pr_warn(FW_WARN "too many record IDs!\n"); return 0; } - new_entries = kvmalloc(new_size * sizeof(entries[0]), GFP_KERNEL); + new_entries = kvmalloc_array(new_size, sizeof(entries[0]), + GFP_KERNEL); if (!new_entries) return -ENOMEM; memcpy(new_entries, entries, diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c index 4c436b7de827..fcb0c33fc629 100644 --- a/drivers/md/dm-integrity.c +++ b/drivers/md/dm-integrity.c @@ -2448,7 +2448,9 @@ static struct scatterlist **dm_integrity_alloc_journal_scatterlist(struct dm_int struct scatterlist **sl; unsigned i; - sl = kvmalloc(ic->journal_sections * sizeof(struct scatterlist *), GFP_KERNEL | __GFP_ZERO); + sl = kvmalloc_array(ic->journal_sections, + sizeof(struct scatterlist *), + GFP_KERNEL | __GFP_ZERO); if (!sl) return NULL; @@ -2464,7 +2466,8 @@ static struct scatterlist **dm_integrity_alloc_journal_scatterlist(struct dm_int n_pages = (end_index - start_index + 1); - s = kvmalloc(n_pages * sizeof(struct scatterlist), GFP_KERNEL); + s = kvmalloc_array(n_pages, sizeof(struct scatterlist), + GFP_KERNEL); if (!s) { dm_integrity_free_journal_scatterlist(ic, sl); return NULL; @@ -2643,7 +2646,9 @@ static int create_journal(struct dm_integrity_c *ic, char **error) goto bad; } - sg = kvmalloc((ic->journal_pages + 1) * sizeof(struct scatterlist), GFP_KERNEL); + sg = kvmalloc_array(ic->journal_pages + 1, + sizeof(struct scatterlist), + GFP_KERNEL); if (!sg) { *error = "Unable to allocate sg list"; r = -ENOMEM; @@ -2709,7 +2714,9 @@ static int create_journal(struct dm_integrity_c *ic, char **error) r = -ENOMEM; goto bad; } - ic->sk_requests = kvmalloc(ic->journal_sections * sizeof(struct skcipher_request *), GFP_KERNEL | __GFP_ZERO); + ic->sk_requests = kvmalloc_array(ic->journal_sections, + sizeof(struct skcipher_request *), + GFP_KERNEL | __GFP_ZERO); if (!ic->sk_requests) { *error = "Unable to allocate sk requests"; r = -ENOMEM; diff --git a/drivers/xen/evtchn.c b/drivers/xen/evtchn.c index 055123f48039..0f4ce6c09763 100644 --- a/drivers/xen/evtchn.c +++ b/drivers/xen/evtchn.c @@ -322,7 +322,7 @@ static int evtchn_resize_ring(struct per_user_data *u) else new_size = 2 * u->ring_size; - new_ring = kvmalloc(new_size * sizeof(*new_ring), GFP_KERNEL); + new_ring = kvmalloc_array(new_size, sizeof(*new_ring), GFP_KERNEL); if (!new_ring) return -ENOMEM; diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 6d653235e323..d20598614ace 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -107,7 +107,7 @@ dio_get_pages_alloc(const struct iov_iter *it, size_t nbytes, align = (unsigned long)(it->iov->iov_base + it->iov_offset) & (PAGE_SIZE - 1); npages = calc_pages_for(align, nbytes); - pages = kvmalloc(sizeof(*pages) * npages, GFP_KERNEL); + pages = kvmalloc_array(npages, sizeof(*pages), GFP_KERNEL); if (!pages) return ERR_PTR(-ENOMEM); diff --git a/ipc/sem.c b/ipc/sem.c index 6adc245f3e02..a6edae020250 100644 --- a/ipc/sem.c +++ b/ipc/sem.c @@ -1878,7 +1878,7 @@ static long do_semtimedop(int semid, struct sembuf __user *tsops, if (nsops > ns->sc_semopm) return -E2BIG; if (nsops > SEMOPM_FAST) { - sops = kvmalloc(sizeof(*sops)*nsops, GFP_KERNEL); + sops = kvmalloc_array(nsops, sizeof(*sops), GFP_KERNEL); if (sops == NULL) return -ENOMEM; } diff --git a/lib/rhashtable.c b/lib/rhashtable.c index cb577ca65fa9..5300fd900e12 100644 --- a/lib/rhashtable.c +++ b/lib/rhashtable.c @@ -87,7 +87,8 @@ static int alloc_bucket_locks(struct rhashtable *ht, struct bucket_table *tbl, if (sizeof(spinlock_t) != 0) { if (gfpflags_allow_blocking(gfp)) - tbl->locks = kvmalloc(size * sizeof(spinlock_t), gfp); + tbl->locks = kvmalloc_array(size, sizeof(spinlock_t), + gfp); else tbl->locks = kmalloc_array(size, sizeof(spinlock_t), gfp); diff --git a/mm/list_lru.c b/mm/list_lru.c index d67348afd1dc..b7bb34c2be8f 100644 --- a/mm/list_lru.c +++ b/mm/list_lru.c @@ -321,7 +321,7 @@ static int memcg_init_list_lru_node(struct list_lru_node *nlru) { int size = memcg_nr_cache_ids; - nlru->memcg_lrus = kvmalloc(size * sizeof(void *), GFP_KERNEL); + nlru->memcg_lrus = kvmalloc_array(size, sizeof(void *), GFP_KERNEL); if (!nlru->memcg_lrus) return -ENOMEM; @@ -347,7 +347,7 @@ static int memcg_update_list_lru_node(struct list_lru_node *nlru, BUG_ON(old_size > new_size); old = nlru->memcg_lrus; - new = kvmalloc(new_size * sizeof(void *), GFP_KERNEL); + new = kvmalloc_array(new_size, sizeof(void *), GFP_KERNEL); if (!new) return -ENOMEM; diff --git a/net/ipv6/ila/ila_xlat.c b/net/ipv6/ila/ila_xlat.c index 3123b9de91b5..536872f4152e 100644 --- a/net/ipv6/ila/ila_xlat.c +++ b/net/ipv6/ila/ila_xlat.c @@ -42,7 +42,8 @@ static int alloc_ila_locks(struct ila_net *ilan) size = roundup_pow_of_two(nr_pcpus * LOCKS_PER_CPU); if (sizeof(spinlock_t) != 0) { - ilan->locks = kvmalloc(size * sizeof(spinlock_t), GFP_KERNEL); + ilan->locks = kvmalloc_array(size, sizeof(spinlock_t), + GFP_KERNEL); if (!ilan->locks) return -ENOMEM; for (i = 0; i < size; i++) diff --git a/net/wireguard/src/compat/ptr_ring/include/linux/ptr_ring.h b/net/wireguard/src/compat/ptr_ring/include/linux/ptr_ring.h index 9d514bac1388..32aed2b21b33 100644 --- a/net/wireguard/src/compat/ptr_ring/include/linux/ptr_ring.h +++ b/net/wireguard/src/compat/ptr_ring/include/linux/ptr_ring.h @@ -468,7 +468,7 @@ static inline void **__ptr_ring_init_queue_alloc(unsigned int size, gfp_t gfp) { if (size > KMALLOC_MAX_SIZE / sizeof(void *)) return NULL; - return kvmalloc(size * sizeof(void *), gfp | __GFP_ZERO); + return kvmalloc_array(size, sizeof(void *), gfp | __GFP_ZERO); } static inline void __ptr_ring_set_size(struct ptr_ring *r, int size) From df9bb5bce8fa2e8382460c2372635c233fffb42f Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 12 Jun 2018 14:04:48 -0700 Subject: [PATCH 577/592] treewide: kvzalloc() -> kvcalloc() The kvzalloc() function has a 2-factor argument form, kvcalloc(). This patch replaces cases of: kvzalloc(a * b, gfp) with: kvcalloc(a * b, gfp) as well as handling cases of: kvzalloc(a * b * c, gfp) with: kvzalloc(array3_size(a, b, c), gfp) as it's slightly less ugly than: kvcalloc(array_size(a, b), c, gfp) This does, however, attempt to ignore constant size factors like: kvzalloc(4 * 1024, gfp) though any constants defined via macros get caught up in the conversion. Any factors with a sizeof() of "unsigned char", "char", and "u8" were dropped, since they're redundant. The Coccinelle script used for this was: // Fix redundant parens around sizeof(). @@ type TYPE; expression THING, E; @@ ( kvzalloc( - (sizeof(TYPE)) * E + sizeof(TYPE) * E , ...) | kvzalloc( - (sizeof(THING)) * E + sizeof(THING) * E , ...) ) // Drop single-byte sizes and redundant parens. @@ expression COUNT; typedef u8; typedef __u8; @@ ( kvzalloc( - sizeof(u8) * (COUNT) + COUNT , ...) | kvzalloc( - sizeof(__u8) * (COUNT) + COUNT , ...) | kvzalloc( - sizeof(char) * (COUNT) + COUNT , ...) | kvzalloc( - sizeof(unsigned char) * (COUNT) + COUNT , ...) | kvzalloc( - sizeof(u8) * COUNT + COUNT , ...) | kvzalloc( - sizeof(__u8) * COUNT + COUNT , ...) | kvzalloc( - sizeof(char) * COUNT + COUNT , ...) | kvzalloc( - sizeof(unsigned char) * COUNT + COUNT , ...) ) // 2-factor product with sizeof(type/expression) and identifier or constant. @@ type TYPE; expression THING; identifier COUNT_ID; constant COUNT_CONST; @@ ( - kvzalloc + kvcalloc ( - sizeof(TYPE) * (COUNT_ID) + COUNT_ID, sizeof(TYPE) , ...) | - kvzalloc + kvcalloc ( - sizeof(TYPE) * COUNT_ID + COUNT_ID, sizeof(TYPE) , ...) | - kvzalloc + kvcalloc ( - sizeof(TYPE) * (COUNT_CONST) + COUNT_CONST, sizeof(TYPE) , ...) | - kvzalloc + kvcalloc ( - sizeof(TYPE) * COUNT_CONST + COUNT_CONST, sizeof(TYPE) , ...) | - kvzalloc + kvcalloc ( - sizeof(THING) * (COUNT_ID) + COUNT_ID, sizeof(THING) , ...) | - kvzalloc + kvcalloc ( - sizeof(THING) * COUNT_ID + COUNT_ID, sizeof(THING) , ...) | - kvzalloc + kvcalloc ( - sizeof(THING) * (COUNT_CONST) + COUNT_CONST, sizeof(THING) , ...) | - kvzalloc + kvcalloc ( - sizeof(THING) * COUNT_CONST + COUNT_CONST, sizeof(THING) , ...) ) // 2-factor product, only identifiers. @@ identifier SIZE, COUNT; @@ - kvzalloc + kvcalloc ( - SIZE * COUNT + COUNT, SIZE , ...) // 3-factor product with 1 sizeof(type) or sizeof(expression), with // redundant parens removed. @@ expression THING; identifier STRIDE, COUNT; type TYPE; @@ ( kvzalloc( - sizeof(TYPE) * (COUNT) * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | kvzalloc( - sizeof(TYPE) * (COUNT) * STRIDE + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | kvzalloc( - sizeof(TYPE) * COUNT * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | kvzalloc( - sizeof(TYPE) * COUNT * STRIDE + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | kvzalloc( - sizeof(THING) * (COUNT) * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) | kvzalloc( - sizeof(THING) * (COUNT) * STRIDE + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) | kvzalloc( - sizeof(THING) * COUNT * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) | kvzalloc( - sizeof(THING) * COUNT * STRIDE + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) ) // 3-factor product with 2 sizeof(variable), with redundant parens removed. @@ expression THING1, THING2; identifier COUNT; type TYPE1, TYPE2; @@ ( kvzalloc( - sizeof(TYPE1) * sizeof(TYPE2) * COUNT + array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2)) , ...) | kvzalloc( - sizeof(TYPE1) * sizeof(THING2) * (COUNT) + array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2)) , ...) | kvzalloc( - sizeof(THING1) * sizeof(THING2) * COUNT + array3_size(COUNT, sizeof(THING1), sizeof(THING2)) , ...) | kvzalloc( - sizeof(THING1) * sizeof(THING2) * (COUNT) + array3_size(COUNT, sizeof(THING1), sizeof(THING2)) , ...) | kvzalloc( - sizeof(TYPE1) * sizeof(THING2) * COUNT + array3_size(COUNT, sizeof(TYPE1), sizeof(THING2)) , ...) | kvzalloc( - sizeof(TYPE1) * sizeof(THING2) * (COUNT) + array3_size(COUNT, sizeof(TYPE1), sizeof(THING2)) , ...) ) // 3-factor product, only identifiers, with redundant parens removed. @@ identifier STRIDE, SIZE, COUNT; @@ ( kvzalloc( - (COUNT) * STRIDE * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) | kvzalloc( - COUNT * (STRIDE) * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) | kvzalloc( - COUNT * STRIDE * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | kvzalloc( - (COUNT) * (STRIDE) * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) | kvzalloc( - COUNT * (STRIDE) * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | kvzalloc( - (COUNT) * STRIDE * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | kvzalloc( - (COUNT) * (STRIDE) * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | kvzalloc( - COUNT * STRIDE * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) ) // Any remaining multi-factor products, first at least 3-factor products, // when they're not all constants... @@ expression E1, E2, E3; constant C1, C2, C3; @@ ( kvzalloc(C1 * C2 * C3, ...) | kvzalloc( - (E1) * E2 * E3 + array3_size(E1, E2, E3) , ...) | kvzalloc( - (E1) * (E2) * E3 + array3_size(E1, E2, E3) , ...) | kvzalloc( - (E1) * (E2) * (E3) + array3_size(E1, E2, E3) , ...) | kvzalloc( - E1 * E2 * E3 + array3_size(E1, E2, E3) , ...) ) // And then all remaining 2 factors products when they're not all constants, // keeping sizeof() as the second factor argument. @@ expression THING, E1, E2; type TYPE; constant C1, C2, C3; @@ ( kvzalloc(sizeof(THING) * C2, ...) | kvzalloc(sizeof(TYPE) * C2, ...) | kvzalloc(C1 * C2 * C3, ...) | kvzalloc(C1 * C2, ...) | - kvzalloc + kvcalloc ( - sizeof(TYPE) * (E2) + E2, sizeof(TYPE) , ...) | - kvzalloc + kvcalloc ( - sizeof(TYPE) * E2 + E2, sizeof(TYPE) , ...) | - kvzalloc + kvcalloc ( - sizeof(THING) * (E2) + E2, sizeof(THING) , ...) | - kvzalloc + kvcalloc ( - sizeof(THING) * E2 + E2, sizeof(THING) , ...) | - kvzalloc + kvcalloc ( - (E1) * E2 + E1, E2 , ...) | - kvzalloc + kvcalloc ( - (E1) * (E2) + E1, E2 , ...) | - kvzalloc + kvcalloc ( - E1 * E2 + E1, E2 , ...) ) Signed-off-by: Kees Cook Signed-off-by: Adam W. Willis Signed-off-by: UtsavBalar1231 --- arch/x86/kvm/page_track.c | 5 +++-- arch/x86/kvm/x86.c | 5 +++-- drivers/infiniband/hw/mlx5/srq.c | 4 ++-- drivers/md/dm-verity-target.c | 5 +++-- drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c | 2 +- drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c | 3 ++- drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c | 10 ++++++---- drivers/scsi/libiscsi.c | 2 +- mm/swap_slots.c | 4 ++-- mm/swap_state.c | 2 +- mm/swapfile.c | 5 +++-- net/sched/sch_fq_codel.c | 7 ++++--- net/sched/sch_hhf.c | 9 +++++---- net/wireguard/src/ratelimiter.c | 4 ++-- 14 files changed, 38 insertions(+), 29 deletions(-) diff --git a/arch/x86/kvm/page_track.c b/arch/x86/kvm/page_track.c index ea67dc876316..9f93cdc10779 100644 --- a/arch/x86/kvm/page_track.c +++ b/arch/x86/kvm/page_track.c @@ -40,8 +40,9 @@ int kvm_page_track_create_memslot(struct kvm_memory_slot *slot, int i; for (i = 0; i < KVM_PAGE_TRACK_MAX; i++) { - slot->arch.gfn_track[i] = kvzalloc(npages * - sizeof(*slot->arch.gfn_track[i]), GFP_KERNEL); + slot->arch.gfn_track[i] = kvcalloc(npages, + sizeof(*slot->arch.gfn_track[i]), + GFP_KERNEL); if (!slot->arch.gfn_track[i]) goto track_free; } diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 3aed03942d7d..c8ec2de41edf 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -8575,13 +8575,14 @@ int kvm_arch_create_memslot(struct kvm *kvm, struct kvm_memory_slot *slot, slot->base_gfn, level) + 1; slot->arch.rmap[i] = - kvzalloc(lpages * sizeof(*slot->arch.rmap[i]), GFP_KERNEL); + kvcalloc(lpages, sizeof(*slot->arch.rmap[i]), + GFP_KERNEL); if (!slot->arch.rmap[i]) goto out_free; if (i == 0) continue; - linfo = kvzalloc(lpages * sizeof(*linfo), GFP_KERNEL); + linfo = kvcalloc(lpages, sizeof(*linfo), GFP_KERNEL); if (!linfo) goto out_free; diff --git a/drivers/infiniband/hw/mlx5/srq.c b/drivers/infiniband/hw/mlx5/srq.c index 93d67d97c279..f5de5adc9b1a 100644 --- a/drivers/infiniband/hw/mlx5/srq.c +++ b/drivers/infiniband/hw/mlx5/srq.c @@ -127,7 +127,7 @@ static int create_srq_user(struct ib_pd *pd, struct mlx5_ib_srq *srq, goto err_umem; } - in->pas = kvzalloc(sizeof(*in->pas) * ncont, GFP_KERNEL); + in->pas = kvcalloc(ncont, sizeof(*in->pas), GFP_KERNEL); if (!in->pas) { err = -ENOMEM; goto err_umem; @@ -189,7 +189,7 @@ static int create_srq_kernel(struct mlx5_ib_dev *dev, struct mlx5_ib_srq *srq, } mlx5_ib_dbg(dev, "srq->buf.page_shift = %d\n", srq->buf.page_shift); - in->pas = kvzalloc(sizeof(*in->pas) * srq->buf.npages, GFP_KERNEL); + in->pas = kvcalloc(srq->buf.npages, sizeof(*in->pas), GFP_KERNEL); if (!in->pas) { err = -ENOMEM; goto err_buf; diff --git a/drivers/md/dm-verity-target.c b/drivers/md/dm-verity-target.c index 23399c7131ee..d29d5012b0a4 100644 --- a/drivers/md/dm-verity-target.c +++ b/drivers/md/dm-verity-target.c @@ -865,8 +865,9 @@ static int verity_alloc_most_once(struct dm_verity *v) return -E2BIG; } - v->validated_blocks = kvzalloc(BITS_TO_LONGS(v->data_blocks) * - sizeof(unsigned long), GFP_KERNEL); + v->validated_blocks = kvcalloc(BITS_TO_LONGS(v->data_blocks), + sizeof(unsigned long), + GFP_KERNEL); if (!v->validated_blocks) { ti->error = "failed to allocate bitset for check_at_most_once"; return -ENOMEM; diff --git a/drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c b/drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c index 3103ef9b561d..778376eecc28 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c +++ b/drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c @@ -305,7 +305,7 @@ struct clip_tbl *t4_init_clip_tbl(unsigned int clipt_start, for (i = 0; i < ctbl->clipt_size; ++i) INIT_LIST_HEAD(&ctbl->hash_list[i]); - cl_list = kvzalloc(clipt_size*sizeof(struct clip_entry), GFP_KERNEL); + cl_list = kvcalloc(clipt_size, sizeof(struct clip_entry), GFP_KERNEL); if (!cl_list) { kvfree(ctbl); return NULL; diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c index de5804ddefbd..00e8967abc3c 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c @@ -457,7 +457,8 @@ struct cxgb4_tc_u32_table *cxgb4_init_tc_u32(struct adapter *adap) unsigned int bmap_size; bmap_size = BITS_TO_LONGS(max_tids); - link->tid_map = kvzalloc(sizeof(unsigned long) * bmap_size, GFP_KERNEL); + link->tid_map = kvcalloc(bmap_size, sizeof(unsigned long), + GFP_KERNEL); if (!link->tid_map) goto out_no_mem; bitmap_zero(link->tid_map, max_tids); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c b/drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c index 5212428031a4..6f27cd31d73c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c @@ -551,15 +551,17 @@ static int mlx5_fpga_conn_create_qp(struct mlx5_fpga_conn *conn, if (err) goto out; - conn->qp.rq.bufs = kvzalloc(sizeof(conn->qp.rq.bufs[0]) * - conn->qp.rq.size, GFP_KERNEL); + conn->qp.rq.bufs = kvcalloc(conn->qp.rq.size, + sizeof(conn->qp.rq.bufs[0]), + GFP_KERNEL); if (!conn->qp.rq.bufs) { err = -ENOMEM; goto err_wq; } - conn->qp.sq.bufs = kvzalloc(sizeof(conn->qp.sq.bufs[0]) * - conn->qp.sq.size, GFP_KERNEL); + conn->qp.sq.bufs = kvcalloc(conn->qp.sq.size, + sizeof(conn->qp.sq.bufs[0]), + GFP_KERNEL); if (!conn->qp.sq.bufs) { err = -ENOMEM; goto err_rq_bufs; diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 662df16b07a4..66169d1881d1 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -2584,7 +2584,7 @@ iscsi_pool_init(struct iscsi_pool *q, int max, void ***items, int item_size) * the array. */ if (items) num_arrays++; - q->pool = kvzalloc(num_arrays * max * sizeof(void*), GFP_KERNEL); + q->pool = kvcalloc(num_arrays * max, sizeof(void *), GFP_KERNEL); if (q->pool == NULL) return -ENOMEM; diff --git a/mm/swap_slots.c b/mm/swap_slots.c index f778aa38127e..652d5f760d6c 100644 --- a/mm/swap_slots.c +++ b/mm/swap_slots.c @@ -124,12 +124,12 @@ static int alloc_swap_slot_cache(unsigned int cpu) * as kvzalloc could trigger reclaim and get_swap_page, * which can lock swap_slots_cache_mutex. */ - slots = kvzalloc(sizeof(swp_entry_t) * SWAP_SLOTS_CACHE_SIZE, + slots = kvcalloc(SWAP_SLOTS_CACHE_SIZE, sizeof(swp_entry_t), GFP_KERNEL); if (!slots) return -ENOMEM; - slots_ret = kvzalloc(sizeof(swp_entry_t) * SWAP_SLOTS_CACHE_SIZE, + slots_ret = kvcalloc(SWAP_SLOTS_CACHE_SIZE, sizeof(swp_entry_t), GFP_KERNEL); if (!slots_ret) { kvfree(slots); diff --git a/mm/swap_state.c b/mm/swap_state.c index 8787c1b675bb..a1a3a81d489e 100644 --- a/mm/swap_state.c +++ b/mm/swap_state.c @@ -626,7 +626,7 @@ int init_swap_address_space(unsigned int type, unsigned long nr_pages) unsigned int i, nr; nr = DIV_ROUND_UP(nr_pages, SWAP_ADDRESS_SPACE_PAGES); - spaces = kvzalloc(sizeof(struct address_space) * nr, GFP_KERNEL); + spaces = kvcalloc(nr, sizeof(struct address_space), GFP_KERNEL); if (!spaces) return -ENOMEM; for (i = 0; i < nr; i++) { diff --git a/mm/swapfile.c b/mm/swapfile.c index 72c0a28a0e10..bfd75fe3f2db 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -3235,7 +3235,7 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) p->cluster_next = 1 + (prandom_u32() % p->highest_bit); nr_cluster = DIV_ROUND_UP(maxpages, SWAPFILE_CLUSTER); - cluster_info = kvzalloc(nr_cluster * sizeof(*cluster_info), + cluster_info = kvcalloc(nr_cluster, sizeof(*cluster_info), GFP_KERNEL); if (!cluster_info) { error = -ENOMEM; @@ -3270,7 +3270,8 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) } /* frontswap enabled? set up bit-per-page map for frontswap */ if (IS_ENABLED(CONFIG_FRONTSWAP)) - frontswap_map = kvzalloc(BITS_TO_LONGS(maxpages) * sizeof(long), + frontswap_map = kvcalloc(BITS_TO_LONGS(maxpages), + sizeof(long), GFP_KERNEL); if (p->bdev &&(swap_flags & SWAP_FLAG_DISCARD) && swap_discardable(p)) { diff --git a/net/sched/sch_fq_codel.c b/net/sched/sch_fq_codel.c index 4faa631139af..490ca6d366fb 100644 --- a/net/sched/sch_fq_codel.c +++ b/net/sched/sch_fq_codel.c @@ -486,11 +486,12 @@ static int fq_codel_init(struct Qdisc *sch, struct nlattr *opt) return err; if (!q->flows) { - q->flows = kvzalloc(q->flows_cnt * - sizeof(struct fq_codel_flow), GFP_KERNEL); + q->flows = kvcalloc(q->flows_cnt, + sizeof(struct fq_codel_flow), + GFP_KERNEL); if (!q->flows) return -ENOMEM; - q->backlogs = kvzalloc(q->flows_cnt * sizeof(u32), GFP_KERNEL); + q->backlogs = kvcalloc(q->flows_cnt, sizeof(u32), GFP_KERNEL); if (!q->backlogs) return -ENOMEM; for (i = 0; i < q->flows_cnt; i++) { diff --git a/net/sched/sch_hhf.c b/net/sched/sch_hhf.c index c73475c3a464..b9b77ad65a7e 100644 --- a/net/sched/sch_hhf.c +++ b/net/sched/sch_hhf.c @@ -597,8 +597,8 @@ static int hhf_init(struct Qdisc *sch, struct nlattr *opt) if (!q->hh_flows) { /* Initialize heavy-hitter flow table. */ - q->hh_flows = kvzalloc(HH_FLOWS_CNT * - sizeof(struct list_head), GFP_KERNEL); + q->hh_flows = kvcalloc(HH_FLOWS_CNT, sizeof(struct list_head), + GFP_KERNEL); if (!q->hh_flows) return -ENOMEM; for (i = 0; i < HH_FLOWS_CNT; i++) @@ -612,8 +612,9 @@ static int hhf_init(struct Qdisc *sch, struct nlattr *opt) /* Initialize heavy-hitter filter arrays. */ for (i = 0; i < HHF_ARRAYS_CNT; i++) { - q->hhf_arrays[i] = kvzalloc(HHF_ARRAYS_LEN * - sizeof(u32), GFP_KERNEL); + q->hhf_arrays[i] = kvcalloc(HHF_ARRAYS_LEN, + sizeof(u32), + GFP_KERNEL); if (!q->hhf_arrays[i]) { /* Note: hhf_destroy() will be called * by our caller. diff --git a/net/wireguard/src/ratelimiter.c b/net/wireguard/src/ratelimiter.c index e33ec72a9642..ecee41f528a5 100644 --- a/net/wireguard/src/ratelimiter.c +++ b/net/wireguard/src/ratelimiter.c @@ -188,12 +188,12 @@ int wg_ratelimiter_init(void) (1U << 14) / sizeof(struct hlist_head))); max_entries = table_size * 8; - table_v4 = kvzalloc(table_size * sizeof(*table_v4), GFP_KERNEL); + table_v4 = kvcalloc(table_size, sizeof(*table_v4), GFP_KERNEL); if (unlikely(!table_v4)) goto err_kmemcache; #if IS_ENABLED(CONFIG_IPV6) - table_v6 = kvzalloc(table_size * sizeof(*table_v6), GFP_KERNEL); + table_v6 = kvcalloc(table_size, sizeof(*table_v6), GFP_KERNEL); if (unlikely(!table_v6)) { kvfree(table_v4); goto err_kmemcache; From b9863689f79d965b7d5fc1fa08ee73dfb3b14ea1 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 12 Jun 2018 14:04:57 -0700 Subject: [PATCH 578/592] treewide: devm_kmalloc() -> devm_kmalloc_array() The devm_kmalloc() function has a 2-factor argument form, devm_kmalloc_array(). This patch replaces cases of: devm_kmalloc(handle, a * b, gfp) with: devm_kmalloc_array(handle, a * b, gfp) as well as handling cases of: devm_kmalloc(handle, a * b * c, gfp) with: devm_kmalloc(handle, array3_size(a, b, c), gfp) as it's slightly less ugly than: devm_kmalloc_array(handle, array_size(a, b), c, gfp) This does, however, attempt to ignore constant size factors like: devm_kmalloc(handle, 4 * 1024, gfp) though any constants defined via macros get caught up in the conversion. Any factors with a sizeof() of "unsigned char", "char", and "u8" were dropped, since they're redundant. Some manual whitespace fixes were needed in this patch, as Coccinelle really liked to write "=devm_kmalloc..." instead of "= devm_kmalloc...". The Coccinelle script used for this was: // Fix redundant parens around sizeof(). @@ expression HANDLE; type TYPE; expression THING, E; @@ ( devm_kmalloc(HANDLE, - (sizeof(TYPE)) * E + sizeof(TYPE) * E , ...) | devm_kmalloc(HANDLE, - (sizeof(THING)) * E + sizeof(THING) * E , ...) ) // Drop single-byte sizes and redundant parens. @@ expression HANDLE; expression COUNT; typedef u8; typedef __u8; @@ ( devm_kmalloc(HANDLE, - sizeof(u8) * (COUNT) + COUNT , ...) | devm_kmalloc(HANDLE, - sizeof(__u8) * (COUNT) + COUNT , ...) | devm_kmalloc(HANDLE, - sizeof(char) * (COUNT) + COUNT , ...) | devm_kmalloc(HANDLE, - sizeof(unsigned char) * (COUNT) + COUNT , ...) | devm_kmalloc(HANDLE, - sizeof(u8) * COUNT + COUNT , ...) | devm_kmalloc(HANDLE, - sizeof(__u8) * COUNT + COUNT , ...) | devm_kmalloc(HANDLE, - sizeof(char) * COUNT + COUNT , ...) | devm_kmalloc(HANDLE, - sizeof(unsigned char) * COUNT + COUNT , ...) ) // 2-factor product with sizeof(type/expression) and identifier or constant. @@ expression HANDLE; type TYPE; expression THING; identifier COUNT_ID; constant COUNT_CONST; @@ ( - devm_kmalloc + devm_kmalloc_array (HANDLE, - sizeof(TYPE) * (COUNT_ID) + COUNT_ID, sizeof(TYPE) , ...) | - devm_kmalloc + devm_kmalloc_array (HANDLE, - sizeof(TYPE) * COUNT_ID + COUNT_ID, sizeof(TYPE) , ...) | - devm_kmalloc + devm_kmalloc_array (HANDLE, - sizeof(TYPE) * (COUNT_CONST) + COUNT_CONST, sizeof(TYPE) , ...) | - devm_kmalloc + devm_kmalloc_array (HANDLE, - sizeof(TYPE) * COUNT_CONST + COUNT_CONST, sizeof(TYPE) , ...) | - devm_kmalloc + devm_kmalloc_array (HANDLE, - sizeof(THING) * (COUNT_ID) + COUNT_ID, sizeof(THING) , ...) | - devm_kmalloc + devm_kmalloc_array (HANDLE, - sizeof(THING) * COUNT_ID + COUNT_ID, sizeof(THING) , ...) | - devm_kmalloc + devm_kmalloc_array (HANDLE, - sizeof(THING) * (COUNT_CONST) + COUNT_CONST, sizeof(THING) , ...) | - devm_kmalloc + devm_kmalloc_array (HANDLE, - sizeof(THING) * COUNT_CONST + COUNT_CONST, sizeof(THING) , ...) ) // 2-factor product, only identifiers. @@ expression HANDLE; identifier SIZE, COUNT; @@ - devm_kmalloc + devm_kmalloc_array (HANDLE, - SIZE * COUNT + COUNT, SIZE , ...) // 3-factor product with 1 sizeof(type) or sizeof(expression), with // redundant parens removed. @@ expression HANDLE; expression THING; identifier STRIDE, COUNT; type TYPE; @@ ( devm_kmalloc(HANDLE, - sizeof(TYPE) * (COUNT) * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | devm_kmalloc(HANDLE, - sizeof(TYPE) * (COUNT) * STRIDE + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | devm_kmalloc(HANDLE, - sizeof(TYPE) * COUNT * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | devm_kmalloc(HANDLE, - sizeof(TYPE) * COUNT * STRIDE + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | devm_kmalloc(HANDLE, - sizeof(THING) * (COUNT) * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) | devm_kmalloc(HANDLE, - sizeof(THING) * (COUNT) * STRIDE + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) | devm_kmalloc(HANDLE, - sizeof(THING) * COUNT * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) | devm_kmalloc(HANDLE, - sizeof(THING) * COUNT * STRIDE + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) ) // 3-factor product with 2 sizeof(variable), with redundant parens removed. @@ expression HANDLE; expression THING1, THING2; identifier COUNT; type TYPE1, TYPE2; @@ ( devm_kmalloc(HANDLE, - sizeof(TYPE1) * sizeof(TYPE2) * COUNT + array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2)) , ...) | devm_kmalloc(HANDLE, - sizeof(TYPE1) * sizeof(THING2) * (COUNT) + array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2)) , ...) | devm_kmalloc(HANDLE, - sizeof(THING1) * sizeof(THING2) * COUNT + array3_size(COUNT, sizeof(THING1), sizeof(THING2)) , ...) | devm_kmalloc(HANDLE, - sizeof(THING1) * sizeof(THING2) * (COUNT) + array3_size(COUNT, sizeof(THING1), sizeof(THING2)) , ...) | devm_kmalloc(HANDLE, - sizeof(TYPE1) * sizeof(THING2) * COUNT + array3_size(COUNT, sizeof(TYPE1), sizeof(THING2)) , ...) | devm_kmalloc(HANDLE, - sizeof(TYPE1) * sizeof(THING2) * (COUNT) + array3_size(COUNT, sizeof(TYPE1), sizeof(THING2)) , ...) ) // 3-factor product, only identifiers, with redundant parens removed. @@ expression HANDLE; identifier STRIDE, SIZE, COUNT; @@ ( devm_kmalloc(HANDLE, - (COUNT) * STRIDE * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) | devm_kmalloc(HANDLE, - COUNT * (STRIDE) * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) | devm_kmalloc(HANDLE, - COUNT * STRIDE * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | devm_kmalloc(HANDLE, - (COUNT) * (STRIDE) * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) | devm_kmalloc(HANDLE, - COUNT * (STRIDE) * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | devm_kmalloc(HANDLE, - (COUNT) * STRIDE * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | devm_kmalloc(HANDLE, - (COUNT) * (STRIDE) * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | devm_kmalloc(HANDLE, - COUNT * STRIDE * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) ) // Any remaining multi-factor products, first at least 3-factor products, // when they're not all constants... @@ expression HANDLE; expression E1, E2, E3; constant C1, C2, C3; @@ ( devm_kmalloc(HANDLE, C1 * C2 * C3, ...) | devm_kmalloc(HANDLE, - (E1) * E2 * E3 + array3_size(E1, E2, E3) , ...) | devm_kmalloc(HANDLE, - (E1) * (E2) * E3 + array3_size(E1, E2, E3) , ...) | devm_kmalloc(HANDLE, - (E1) * (E2) * (E3) + array3_size(E1, E2, E3) , ...) | devm_kmalloc(HANDLE, - E1 * E2 * E3 + array3_size(E1, E2, E3) , ...) ) // And then all remaining 2 factors products when they're not all constants, // keeping sizeof() as the second factor argument. @@ expression HANDLE; expression THING, E1, E2; type TYPE; constant C1, C2, C3; @@ ( devm_kmalloc(HANDLE, sizeof(THING) * C2, ...) | devm_kmalloc(HANDLE, sizeof(TYPE) * C2, ...) | devm_kmalloc(HANDLE, C1 * C2 * C3, ...) | devm_kmalloc(HANDLE, C1 * C2, ...) | - devm_kmalloc + devm_kmalloc_array (HANDLE, - sizeof(TYPE) * (E2) + E2, sizeof(TYPE) , ...) | - devm_kmalloc + devm_kmalloc_array (HANDLE, - sizeof(TYPE) * E2 + E2, sizeof(TYPE) , ...) | - devm_kmalloc + devm_kmalloc_array (HANDLE, - sizeof(THING) * (E2) + E2, sizeof(THING) , ...) | - devm_kmalloc + devm_kmalloc_array (HANDLE, - sizeof(THING) * E2 + E2, sizeof(THING) , ...) | - devm_kmalloc + devm_kmalloc_array (HANDLE, - (E1) * E2 + E1, E2 , ...) | - devm_kmalloc + devm_kmalloc_array (HANDLE, - (E1) * (E2) + E1, E2 , ...) | - devm_kmalloc + devm_kmalloc_array (HANDLE, - E1 * E2 + E1, E2 , ...) ) Signed-off-by: Kees Cook Signed-off-by: Adam W. Willis Signed-off-by: UtsavBalar1231 --- drivers/iio/adc/max1027.c | 4 ++-- drivers/iommu/arm-smmu.c | 7 ++++--- drivers/nfc/fdp/i2c.c | 4 ++-- drivers/pinctrl/freescale/pinctrl-imx.c | 5 +++-- drivers/pinctrl/mvebu/pinctrl-armada-xp.c | 4 ++-- drivers/regulator/s2mps11.c | 4 ++-- 6 files changed, 15 insertions(+), 13 deletions(-) diff --git a/drivers/iio/adc/max1027.c b/drivers/iio/adc/max1027.c index 03af02769370..728230b6f127 100644 --- a/drivers/iio/adc/max1027.c +++ b/drivers/iio/adc/max1027.c @@ -424,8 +424,8 @@ static int max1027_probe(struct spi_device *spi) indio_dev->num_channels = st->info->num_channels; indio_dev->available_scan_masks = st->info->available_scan_masks; - st->buffer = devm_kmalloc(&indio_dev->dev, - indio_dev->num_channels * 2, + st->buffer = devm_kmalloc_array(&indio_dev->dev, + indio_dev->num_channels, 2, GFP_KERNEL); if (st->buffer == NULL) { dev_err(&indio_dev->dev, "Can't allocate buffer\n"); diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 01c7f73b7714..77d67eaca378 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -4539,13 +4539,14 @@ static int arm_smmu_parse_impl_def_registers(struct arm_smmu_device *smmu) return -EINVAL; } - regs = devm_kmalloc( - dev, sizeof(*smmu->impl_def_attach_registers) * ntuples, + regs = devm_kmalloc_array( + dev, ntuples, sizeof(*smmu->impl_def_attach_registers), GFP_KERNEL); if (!regs) return -ENOMEM; - tuples = devm_kmalloc(dev, sizeof(u32) * ntuples * 2, GFP_KERNEL); + tuples = devm_kmalloc(dev, array3_size(sizeof(u32), ntuples, 2), + GFP_KERNEL); if (!tuples) return -ENOMEM; diff --git a/drivers/nfc/fdp/i2c.c b/drivers/nfc/fdp/i2c.c index b86c8447df89..159dc9ed0bad 100644 --- a/drivers/nfc/fdp/i2c.c +++ b/drivers/nfc/fdp/i2c.c @@ -269,8 +269,8 @@ static void fdp_nci_i2c_read_device_properties(struct device *dev, /* Add 1 to the length to inclue the length byte itself */ len++; - *fw_vsc_cfg = devm_kmalloc(dev, - len * sizeof(**fw_vsc_cfg), + *fw_vsc_cfg = devm_kmalloc_array(dev, + len, sizeof(**fw_vsc_cfg), GFP_KERNEL); r = device_property_read_u8_array(dev, FDP_DP_FW_VSC_CFG_NAME, diff --git a/drivers/pinctrl/freescale/pinctrl-imx.c b/drivers/pinctrl/freescale/pinctrl-imx.c index 071980dba20e..e088648b3bd4 100644 --- a/drivers/pinctrl/freescale/pinctrl-imx.c +++ b/drivers/pinctrl/freescale/pinctrl-imx.c @@ -691,8 +691,9 @@ int imx_pinctrl_probe(struct platform_device *pdev, if (!ipctl) return -ENOMEM; - info->pin_regs = devm_kmalloc(&pdev->dev, sizeof(*info->pin_regs) * - info->npins, GFP_KERNEL); + info->pin_regs = devm_kmalloc_array(&pdev->dev, + info->npins, sizeof(*info->pin_regs), + GFP_KERNEL); if (!info->pin_regs) return -ENOMEM; diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-xp.c b/drivers/pinctrl/mvebu/pinctrl-armada-xp.c index b854f1ee5de5..924de31ca133 100644 --- a/drivers/pinctrl/mvebu/pinctrl-armada-xp.c +++ b/drivers/pinctrl/mvebu/pinctrl-armada-xp.c @@ -630,8 +630,8 @@ static int armada_xp_pinctrl_probe(struct platform_device *pdev) nregs = DIV_ROUND_UP(soc->nmodes, MVEBU_MPPS_PER_REG); - mpp_saved_regs = devm_kmalloc(&pdev->dev, nregs * sizeof(u32), - GFP_KERNEL); + mpp_saved_regs = devm_kmalloc_array(&pdev->dev, nregs, sizeof(u32), + GFP_KERNEL); if (!mpp_saved_regs) return -ENOMEM; diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index c3a664e64307..5193146bfbbe 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -1139,8 +1139,8 @@ static int s2mps11_pmic_probe(struct platform_device *pdev) return -EINVAL; } - s2mps11->ext_control_gpio = devm_kmalloc(&pdev->dev, - sizeof(*s2mps11->ext_control_gpio) * rdev_num, + s2mps11->ext_control_gpio = devm_kmalloc_array(&pdev->dev, + rdev_num, sizeof(*s2mps11->ext_control_gpio), GFP_KERNEL); if (!s2mps11->ext_control_gpio) return -ENOMEM; From 7076e86f97c1f06a930b0564de6b66fb7ff8613b Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 12 Jun 2018 14:07:58 -0700 Subject: [PATCH 579/592] treewide: devm_kzalloc() -> devm_kcalloc() The devm_kzalloc() function has a 2-factor argument form, devm_kcalloc(). This patch replaces cases of: devm_kzalloc(handle, a * b, gfp) with: devm_kcalloc(handle, a * b, gfp) as well as handling cases of: devm_kzalloc(handle, a * b * c, gfp) with: devm_kzalloc(handle, array3_size(a, b, c), gfp) as it's slightly less ugly than: devm_kcalloc(handle, array_size(a, b), c, gfp) This does, however, attempt to ignore constant size factors like: devm_kzalloc(handle, 4 * 1024, gfp) though any constants defined via macros get caught up in the conversion. Any factors with a sizeof() of "unsigned char", "char", and "u8" were dropped, since they're redundant. Some manual whitespace fixes were needed in this patch, as Coccinelle really liked to write "=devm_kcalloc..." instead of "= devm_kcalloc...". The Coccinelle script used for this was: // Fix redundant parens around sizeof(). @@ expression HANDLE; type TYPE; expression THING, E; @@ ( devm_kzalloc(HANDLE, - (sizeof(TYPE)) * E + sizeof(TYPE) * E , ...) | devm_kzalloc(HANDLE, - (sizeof(THING)) * E + sizeof(THING) * E , ...) ) // Drop single-byte sizes and redundant parens. @@ expression HANDLE; expression COUNT; typedef u8; typedef __u8; @@ ( devm_kzalloc(HANDLE, - sizeof(u8) * (COUNT) + COUNT , ...) | devm_kzalloc(HANDLE, - sizeof(__u8) * (COUNT) + COUNT , ...) | devm_kzalloc(HANDLE, - sizeof(char) * (COUNT) + COUNT , ...) | devm_kzalloc(HANDLE, - sizeof(unsigned char) * (COUNT) + COUNT , ...) | devm_kzalloc(HANDLE, - sizeof(u8) * COUNT + COUNT , ...) | devm_kzalloc(HANDLE, - sizeof(__u8) * COUNT + COUNT , ...) | devm_kzalloc(HANDLE, - sizeof(char) * COUNT + COUNT , ...) | devm_kzalloc(HANDLE, - sizeof(unsigned char) * COUNT + COUNT , ...) ) // 2-factor product with sizeof(type/expression) and identifier or constant. @@ expression HANDLE; type TYPE; expression THING; identifier COUNT_ID; constant COUNT_CONST; @@ ( - devm_kzalloc + devm_kcalloc (HANDLE, - sizeof(TYPE) * (COUNT_ID) + COUNT_ID, sizeof(TYPE) , ...) | - devm_kzalloc + devm_kcalloc (HANDLE, - sizeof(TYPE) * COUNT_ID + COUNT_ID, sizeof(TYPE) , ...) | - devm_kzalloc + devm_kcalloc (HANDLE, - sizeof(TYPE) * (COUNT_CONST) + COUNT_CONST, sizeof(TYPE) , ...) | - devm_kzalloc + devm_kcalloc (HANDLE, - sizeof(TYPE) * COUNT_CONST + COUNT_CONST, sizeof(TYPE) , ...) | - devm_kzalloc + devm_kcalloc (HANDLE, - sizeof(THING) * (COUNT_ID) + COUNT_ID, sizeof(THING) , ...) | - devm_kzalloc + devm_kcalloc (HANDLE, - sizeof(THING) * COUNT_ID + COUNT_ID, sizeof(THING) , ...) | - devm_kzalloc + devm_kcalloc (HANDLE, - sizeof(THING) * (COUNT_CONST) + COUNT_CONST, sizeof(THING) , ...) | - devm_kzalloc + devm_kcalloc (HANDLE, - sizeof(THING) * COUNT_CONST + COUNT_CONST, sizeof(THING) , ...) ) // 2-factor product, only identifiers. @@ expression HANDLE; identifier SIZE, COUNT; @@ - devm_kzalloc + devm_kcalloc (HANDLE, - SIZE * COUNT + COUNT, SIZE , ...) // 3-factor product with 1 sizeof(type) or sizeof(expression), with // redundant parens removed. @@ expression HANDLE; expression THING; identifier STRIDE, COUNT; type TYPE; @@ ( devm_kzalloc(HANDLE, - sizeof(TYPE) * (COUNT) * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | devm_kzalloc(HANDLE, - sizeof(TYPE) * (COUNT) * STRIDE + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | devm_kzalloc(HANDLE, - sizeof(TYPE) * COUNT * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | devm_kzalloc(HANDLE, - sizeof(TYPE) * COUNT * STRIDE + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | devm_kzalloc(HANDLE, - sizeof(THING) * (COUNT) * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) | devm_kzalloc(HANDLE, - sizeof(THING) * (COUNT) * STRIDE + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) | devm_kzalloc(HANDLE, - sizeof(THING) * COUNT * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) | devm_kzalloc(HANDLE, - sizeof(THING) * COUNT * STRIDE + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) ) // 3-factor product with 2 sizeof(variable), with redundant parens removed. @@ expression HANDLE; expression THING1, THING2; identifier COUNT; type TYPE1, TYPE2; @@ ( devm_kzalloc(HANDLE, - sizeof(TYPE1) * sizeof(TYPE2) * COUNT + array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2)) , ...) | devm_kzalloc(HANDLE, - sizeof(TYPE1) * sizeof(THING2) * (COUNT) + array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2)) , ...) | devm_kzalloc(HANDLE, - sizeof(THING1) * sizeof(THING2) * COUNT + array3_size(COUNT, sizeof(THING1), sizeof(THING2)) , ...) | devm_kzalloc(HANDLE, - sizeof(THING1) * sizeof(THING2) * (COUNT) + array3_size(COUNT, sizeof(THING1), sizeof(THING2)) , ...) | devm_kzalloc(HANDLE, - sizeof(TYPE1) * sizeof(THING2) * COUNT + array3_size(COUNT, sizeof(TYPE1), sizeof(THING2)) , ...) | devm_kzalloc(HANDLE, - sizeof(TYPE1) * sizeof(THING2) * (COUNT) + array3_size(COUNT, sizeof(TYPE1), sizeof(THING2)) , ...) ) // 3-factor product, only identifiers, with redundant parens removed. @@ expression HANDLE; identifier STRIDE, SIZE, COUNT; @@ ( devm_kzalloc(HANDLE, - (COUNT) * STRIDE * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) | devm_kzalloc(HANDLE, - COUNT * (STRIDE) * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) | devm_kzalloc(HANDLE, - COUNT * STRIDE * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | devm_kzalloc(HANDLE, - (COUNT) * (STRIDE) * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) | devm_kzalloc(HANDLE, - COUNT * (STRIDE) * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | devm_kzalloc(HANDLE, - (COUNT) * STRIDE * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | devm_kzalloc(HANDLE, - (COUNT) * (STRIDE) * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | devm_kzalloc(HANDLE, - COUNT * STRIDE * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) ) // Any remaining multi-factor products, first at least 3-factor products, // when they're not all constants... @@ expression HANDLE; expression E1, E2, E3; constant C1, C2, C3; @@ ( devm_kzalloc(HANDLE, C1 * C2 * C3, ...) | devm_kzalloc(HANDLE, - (E1) * E2 * E3 + array3_size(E1, E2, E3) , ...) | devm_kzalloc(HANDLE, - (E1) * (E2) * E3 + array3_size(E1, E2, E3) , ...) | devm_kzalloc(HANDLE, - (E1) * (E2) * (E3) + array3_size(E1, E2, E3) , ...) | devm_kzalloc(HANDLE, - E1 * E2 * E3 + array3_size(E1, E2, E3) , ...) ) // And then all remaining 2 factors products when they're not all constants, // keeping sizeof() as the second factor argument. @@ expression HANDLE; expression THING, E1, E2; type TYPE; constant C1, C2, C3; @@ ( devm_kzalloc(HANDLE, sizeof(THING) * C2, ...) | devm_kzalloc(HANDLE, sizeof(TYPE) * C2, ...) | devm_kzalloc(HANDLE, C1 * C2 * C3, ...) | devm_kzalloc(HANDLE, C1 * C2, ...) | - devm_kzalloc + devm_kcalloc (HANDLE, - sizeof(TYPE) * (E2) + E2, sizeof(TYPE) , ...) | - devm_kzalloc + devm_kcalloc (HANDLE, - sizeof(TYPE) * E2 + E2, sizeof(TYPE) , ...) | - devm_kzalloc + devm_kcalloc (HANDLE, - sizeof(THING) * (E2) + E2, sizeof(THING) , ...) | - devm_kzalloc + devm_kcalloc (HANDLE, - sizeof(THING) * E2 + E2, sizeof(THING) , ...) | - devm_kzalloc + devm_kcalloc (HANDLE, - (E1) * E2 + E1, E2 , ...) | - devm_kzalloc + devm_kcalloc (HANDLE, - (E1) * (E2) + E1, E2 , ...) | - devm_kzalloc + devm_kcalloc (HANDLE, - E1 * E2 + E1, E2 , ...) ) Signed-off-by: Kees Cook Signed-off-by: Adam W. Willis Signed-off-by: UtsavBalar1231 --- drivers/acpi/fan.c | 4 +- drivers/acpi/nfit/core.c | 7 +- drivers/ata/sata_mv.c | 8 +- drivers/char/tpm/tpm2-cmd.c | 2 +- drivers/clk/bcm/clk-bcm2835.c | 4 +- drivers/clk/msm/clock-a7.c | 8 +- drivers/clk/msm/clock-local2.c | 10 +-- drivers/clk/msm/gdsc.c | 8 +- drivers/clk/msm/msm-clock-controller.c | 15 ++-- drivers/clk/qcom/clk-cpu-qcs405.c | 11 +-- drivers/clk/qcom/clk-cpu-sdxprairie.c | 11 +-- drivers/clk/qcom/clk-rcg2.c | 5 +- drivers/clk/qcom/debugcc-atoll.c | 4 +- drivers/clk/qcom/debugcc-sdmmagpie.c | 4 +- drivers/clk/qcom/gdsc-regulator.c | 10 +-- drivers/clk/qcom/mdss/mdss-pll-util.c | 9 ++- drivers/clk/ti/adpll.c | 6 +- drivers/cpufreq/brcmstb-avs-cpufreq.c | 2 +- drivers/cpufreq/imx6q-cpufreq.c | 3 +- drivers/cpufreq/qcom-cpufreq.c | 4 +- drivers/cpuidle/lpm-levels-of.c | 14 ++-- drivers/crypto/marvell/cesa.c | 2 +- drivers/crypto/msm/ice.c | 2 +- drivers/devfreq/arm-memlat-mon.c | 12 ++- drivers/devfreq/bimc-bwmon.c | 2 +- drivers/devfreq/devfreq.c | 8 +- drivers/devfreq/devfreq_simple_dev.c | 4 +- drivers/devfreq/event/exynos-ppmu.c | 2 +- drivers/devfreq/governor_memlat.c | 4 +- drivers/dma/k3dma.c | 8 +- drivers/dma/mv_xor_v2.c | 5 +- drivers/dma/qcom/gpi.c | 4 +- drivers/dma/s3c24xx-dma.c | 6 +- drivers/dma/zx_dma.c | 8 +- drivers/edac/qcom_llcc_edac.c | 4 +- drivers/extcon/extcon.c | 4 +- drivers/firmware/arm_scpi.c | 2 +- drivers/firmware/ti_sci.c | 6 +- drivers/gpio/gpio-adnp.c | 2 +- drivers/gpio/gpio-bcm-kona.c | 7 +- drivers/gpio/gpio-davinci.c | 4 +- drivers/gpio/gpio-etraxfs.c | 3 +- drivers/gpio/gpio-htc-egpio.c | 4 +- drivers/gpio/gpio-thunderx.c | 9 ++- drivers/gpu/drm/bridge/lt9611.c | 6 +- drivers/gpu/drm/exynos/exynos_drm_dsi.c | 4 +- drivers/gpu/drm/exynos/exynos_hdmi.c | 2 +- drivers/gpu/drm/msm/dp/dp_parser.c | 28 +++---- drivers/gpu/drm/msm/dsi-staging/dsi_parser.c | 2 +- drivers/gpu/drm/msm/hdmi/hdmi.c | 24 ++++-- drivers/gpu/drm/msm/hdmi/hdmi_phy.c | 4 +- drivers/gpu/drm/msm/sde_power_handle.c | 9 ++- drivers/gpu/drm/msm/shp/shp_drm.c | 4 +- drivers/hid/hid-sensor-hub.c | 3 +- drivers/hid/intel-ish-hid/ishtp-hid-client.c | 4 +- drivers/hid/wacom_sys.c | 4 +- drivers/hwmon/aspeed-pwm-tacho.c | 2 +- drivers/hwmon/gpio-fan.c | 6 +- drivers/hwmon/ibmpowernv.c | 9 ++- drivers/hwmon/iio_hwmon.c | 4 +- drivers/hwmon/nct6683.c | 4 +- drivers/hwmon/nct6775.c | 4 +- drivers/hwmon/pmbus/pmbus_core.c | 4 +- drivers/hwmon/pwm-fan.c | 2 +- drivers/hwtracing/coresight/coresight-etb10.c | 4 +- .../hwtracing/coresight/coresight-hwevent.c | 9 ++- drivers/hwtracing/coresight/coresight-tgu.c | 35 +++++---- drivers/hwtracing/coresight/coresight-tpdm.c | 6 +- drivers/hwtracing/coresight/of_coresight.c | 29 ++++--- drivers/i2c/busses/i2c-msm-v2.c | 4 +- drivers/i2c/busses/i2c-qup.c | 8 +- drivers/i2c/muxes/i2c-mux-gpio.c | 9 ++- drivers/i2c/muxes/i2c-mux-reg.c | 4 +- drivers/iio/adc/at91_adc.c | 7 +- drivers/iio/adc/max1363.c | 4 +- drivers/iio/adc/twl6030-gpadc.c | 7 +- drivers/iio/dac/ad5592r-base.c | 5 +- drivers/iio/multiplexer/iio-mux.c | 7 +- drivers/input/keyboard/clps711x-keypad.c | 4 +- drivers/input/keyboard/matrix_keypad.c | 6 +- drivers/input/keyboard/samsung-keypad.c | 2 +- drivers/input/matrix-keymap.c | 4 +- drivers/input/misc/rotary_encoder.c | 4 +- drivers/input/rmi4/rmi_driver.c | 9 ++- drivers/input/rmi4/rmi_f11.c | 15 ++-- drivers/input/rmi4/rmi_f12.c | 15 ++-- drivers/input/rmi4/rmi_f54.c | 2 +- drivers/input/rmi4/rmi_spi.c | 9 ++- drivers/iommu/arm-smmu.c | 14 ++-- drivers/iommu/rockchip-iommu.c | 2 +- drivers/irqchip/irq-imgpdc.c | 2 +- drivers/irqchip/irq-mvebu-gicp.c | 8 +- drivers/leds/leds-adp5520.c | 2 +- drivers/leds/leds-da9052.c | 4 +- drivers/leds/leds-lp5521.c | 4 +- drivers/leds/leds-lp5523.c | 4 +- drivers/leds/leds-lp5562.c | 4 +- drivers/leds/leds-lp55xx-common.c | 2 +- drivers/leds/leds-lp8501.c | 4 +- drivers/leds/leds-lt3593.c | 4 +- drivers/leds/leds-mc13783.c | 4 +- drivers/leds/leds-mlxcpld.c | 6 +- drivers/leds/leds-netxbig.c | 16 ++-- drivers/leds/leds-ns2.c | 7 +- drivers/leds/leds-pca955x.c | 8 +- drivers/leds/leds-pca963x.c | 6 +- drivers/leds/leds-pca9956b.c | 5 +- drivers/leds/leds-tca6507.c | 4 +- drivers/mailbox/hi6220-mailbox.c | 8 +- drivers/mailbox/mailbox-sti.c | 4 +- drivers/mailbox/msm_qmp.c | 3 +- drivers/mailbox/omap-mailbox.c | 10 +-- drivers/mailbox/qcom-rpmh-mailbox.c | 7 +- drivers/mailbox/ti-msgmgr.c | 4 +- drivers/media/i2c/s5k5baf.c | 2 +- drivers/media/platform/am437x/am437x-vpfe.c | 6 +- drivers/media/platform/davinci/vpif_capture.c | 10 ++- .../platform/msm/ais/cam_smmu/cam_smmu_api.c | 4 +- .../msm/camera/cam_smmu/cam_smmu_api.c | 4 +- .../msm/camera_v2/common/cam_hw_ops.c | 16 ++-- .../msm/camera_v2/common/cam_smmu_api.c | 4 +- .../msm/sde/rotator/sde_rotator_core.c | 13 ++-- .../msm/sde/rotator/sde_rotator_smmu.c | 4 +- .../platform/msm/vidc/msm_vidc_res_parse.c | 38 ++++++---- .../platform/qcom/camss-8x16/camss-csid.c | 8 +- .../platform/qcom/camss-8x16/camss-csiphy.c | 11 ++- .../platform/qcom/camss-8x16/camss-ispif.c | 9 ++- .../platform/qcom/camss-8x16/camss-vfe.c | 8 +- .../media/platform/qcom/camss-8x16/camss.c | 3 +- drivers/media/platform/vsp1/vsp1_entity.c | 3 +- drivers/media/platform/xilinx/xilinx-vipp.c | 2 +- .../media/v4l2-core/v4l2-flash-led-class.c | 7 +- drivers/memory/of_memory.c | 4 +- drivers/mfd/ab8500-debugfs.c | 12 +-- drivers/mfd/htc-i2cpld.c | 4 +- drivers/mfd/motorola-cpcap.c | 4 +- drivers/mfd/omap-usb-tll.c | 2 +- drivers/mfd/twl-core.c | 5 +- drivers/mfd/wm8994-core.c | 7 +- drivers/misc/memory_state_time.c | 17 +++-- drivers/misc/sram.c | 4 +- drivers/mmc/host/sdhci-msm.c | 8 +- drivers/mtd/devices/docg3.c | 2 +- drivers/mtd/nand/qcom_nandc.c | 4 +- drivers/mtd/nand/s3c2410.c | 2 +- drivers/net/dsa/b53/b53_common.c | 8 +- drivers/net/ethernet/amazon/ena/ena_ethtool.c | 8 +- drivers/net/ethernet/ethoc.c | 3 +- .../net/ethernet/freescale/dpaa/dpaa_eth.c | 2 +- .../hisilicon/hns3/hns3pf/hns3_enet.c | 4 +- drivers/net/ethernet/ti/cpsw.c | 9 ++- drivers/net/ethernet/ti/netcp_ethss.c | 24 +++--- drivers/net/phy/phy_led_triggers.c | 6 +- drivers/net/wireless/cnss2/pci.c | 14 ++-- drivers/pci/dwc/pci-dra7xx.c | 4 +- drivers/pci/dwc/pcie-designware-ep.c | 8 +- drivers/pci/host/pci-msm.c | 5 +- drivers/pinctrl/berlin/berlin.c | 10 ++- drivers/pinctrl/freescale/pinctrl-imx.c | 10 ++- drivers/pinctrl/freescale/pinctrl-imx1-core.c | 20 ++--- drivers/pinctrl/freescale/pinctrl-mxs.c | 18 +++-- drivers/pinctrl/mvebu/pinctrl-armada-37xx.c | 21 +++-- drivers/pinctrl/mvebu/pinctrl-mvebu.c | 16 ++-- drivers/pinctrl/pinctrl-at91-pio4.c | 39 ++++++---- drivers/pinctrl/pinctrl-at91.c | 34 ++++++--- drivers/pinctrl/pinctrl-digicolor.c | 5 +- drivers/pinctrl/pinctrl-ingenic.c | 4 +- drivers/pinctrl/pinctrl-lpc18xx.c | 5 +- drivers/pinctrl/pinctrl-rockchip.c | 24 +++--- drivers/pinctrl/pinctrl-single.c | 26 ++++--- drivers/pinctrl/pinctrl-st.c | 31 ++++---- drivers/pinctrl/pinctrl-xway.c | 4 +- drivers/pinctrl/qcom/pinctrl-sm6150.c | 9 ++- drivers/pinctrl/qcom/pinctrl-sm8150.c | 9 ++- drivers/pinctrl/samsung/pinctrl-exynos.c | 5 +- drivers/pinctrl/samsung/pinctrl-exynos5440.c | 19 +++-- drivers/pinctrl/samsung/pinctrl-samsung.c | 16 ++-- drivers/pinctrl/sh-pfc/core.c | 6 +- drivers/pinctrl/sh-pfc/gpio.c | 7 +- drivers/pinctrl/sh-pfc/pinctrl.c | 8 +- drivers/pinctrl/spear/pinctrl-plgpio.c | 4 +- drivers/pinctrl/sprd/pinctrl-sprd.c | 19 +++-- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 18 +++-- drivers/pinctrl/tegra/pinctrl-tegra.c | 6 +- drivers/pinctrl/ti/pinctrl-ti-iodelay.c | 6 +- drivers/pinctrl/zte/pinctrl-zx.c | 6 +- drivers/platform/msm/gsi/gsi.c | 4 +- drivers/platform/msm/qcom-geni-se.c | 6 +- drivers/platform/msm/usb_bam.c | 14 ++-- drivers/platform/x86/mlxcpld-hotplug.c | 3 +- drivers/power/supply/charger-manager.c | 28 ++++--- drivers/power/supply/power_supply_core.c | 4 +- drivers/pwm/pwm-lp3943.c | 2 +- drivers/regulator/act8865-regulator.c | 7 +- drivers/regulator/as3711-regulator.c | 6 +- drivers/regulator/bcm590xx-regulator.c | 6 +- drivers/regulator/cpr-regulator.c | 76 ++++++++++--------- drivers/regulator/da9063-regulator.c | 4 +- drivers/regulator/gpio-regulator.c | 10 +-- drivers/regulator/max1586.c | 6 +- drivers/regulator/max8660.c | 6 +- drivers/regulator/max8997-regulator.c | 5 +- drivers/regulator/max8998.c | 5 +- drivers/regulator/mc13xxx-regulator-core.c | 2 +- drivers/regulator/mem-acc-regulator.c | 14 ++-- drivers/regulator/pbias-regulator.c | 5 +- drivers/regulator/rc5t583-regulator.c | 6 +- drivers/regulator/s5m8767.c | 10 ++- drivers/regulator/ti-abb-regulator.c | 4 +- drivers/regulator/tps65090-regulator.c | 10 ++- drivers/regulator/tps65217-regulator.c | 5 +- drivers/regulator/tps65218-regulator.c | 5 +- drivers/regulator/tps65910-regulator.c | 18 +++-- drivers/regulator/tps80031-regulator.c | 4 +- drivers/reset/reset-ti-syscon.c | 3 +- drivers/scsi/isci/init.c | 8 +- drivers/scsi/ufs/ufshcd-pltfrm.c | 4 +- drivers/scsi/ufs/ufshcd.c | 4 +- drivers/soc/bcm/raspberrypi-power.c | 6 +- drivers/soc/mediatek/mtk-scpsys.c | 8 +- drivers/soc/qcom/gladiator_hang_detect.c | 6 +- drivers/soc/qcom/glink_pkt.c | 2 +- drivers/soc/qcom/jtagv8-etm.c | 4 +- drivers/soc/qcom/msm_bus/msm_bus_arb_adhoc.c | 6 +- drivers/soc/qcom/msm_bus/msm_bus_arb_rpmh.c | 12 +-- .../soc/qcom/msm_bus/msm_bus_fabric_adhoc.c | 27 ++++--- .../soc/qcom/msm_bus/msm_bus_fabric_rpmh.c | 51 ++++++------- drivers/soc/qcom/msm_bus/msm_bus_of.c | 11 ++- drivers/soc/qcom/msm_bus/msm_bus_of_adhoc.c | 11 +-- drivers/soc/qcom/msm_bus/msm_bus_of_rpmh.c | 11 +-- drivers/soc/qcom/qsee_ipc_irq.c | 2 +- drivers/soc/qcom/rpm_master_stat.c | 4 +- drivers/soc/qcom/subsys-pil-tz.c | 4 +- drivers/soc/qcom/subsystem_restart.c | 8 +- drivers/soc/ti/knav_qmss_acc.c | 6 +- drivers/spi/spi-davinci.c | 7 +- drivers/spi/spi-ep93xx.c | 4 +- drivers/spi/spi-imx.c | 4 +- drivers/spi/spi-oc-tiny.c | 4 +- drivers/spi/spi-pl022.c | 2 +- drivers/spi/spi.c | 2 +- drivers/staging/fsl-mc/bus/fsl-mc-allocator.c | 6 +- drivers/staging/greybus/audio_topology.c | 2 +- .../atomisp/pci/atomisp2/atomisp_subdev.c | 6 +- drivers/thermal/tegra/soctherm.c | 8 +- drivers/thermal/thermal-generic-adc.c | 5 +- drivers/tty/serial/rp2.c | 2 +- drivers/usb/dwc3/dwc3-msm.c | 4 +- drivers/usb/gadget/udc/atmel_usba_udc.c | 4 +- drivers/usb/gadget/udc/renesas_usb3.c | 3 +- drivers/usb/phy/phy-msm-usb.c | 4 +- drivers/video/backlight/adp8860_bl.c | 2 +- drivers/video/backlight/adp8870_bl.c | 2 +- drivers/video/backlight/lp855x_bl.c | 2 +- drivers/video/fbdev/au1100fb.c | 2 +- drivers/video/fbdev/bf537-lq035.c | 4 +- drivers/video/fbdev/bf54x-lq043fb.c | 2 +- drivers/video/fbdev/msm/dsi_v2.c | 5 +- drivers/video/fbdev/msm/mdp3_ctrl.c | 10 +-- drivers/video/fbdev/msm/mdss_dsi.c | 5 +- drivers/video/fbdev/msm/mdss_fb.c | 4 +- drivers/video/fbdev/msm/mdss_hdmi_tx.c | 25 +++--- drivers/video/fbdev/msm/mdss_mdp.c | 44 ++++++----- drivers/video/fbdev/msm/mdss_mdp_ctl.c | 16 ++-- drivers/video/fbdev/msm/mdss_mdp_intf_video.c | 4 +- drivers/video/fbdev/msm/mdss_mdp_pp.c | 12 +-- drivers/video/fbdev/msm/mdss_rotator.c | 9 ++- drivers/video/fbdev/msm/mdss_smmu.c | 4 +- drivers/video/fbdev/msm/mdss_spi_panel.c | 10 ++- drivers/video/fbdev/msm/msm_dba/adv7533.c | 7 +- drivers/video/fbdev/mxsfb.c | 2 +- drivers/video/fbdev/omap2/omapfb/vrfb.c | 4 +- drivers/vservices/transport/axon.c | 4 +- sound/soc/au1x/dbdma2.c | 4 +- sound/soc/codecs/hdmi-codec.c | 2 +- sound/soc/codecs/rt5645.c | 5 +- sound/soc/codecs/tfa98xx.c | 4 +- sound/soc/codecs/wm8994.c | 4 +- sound/soc/davinci/davinci-mcasp.c | 14 ++-- sound/soc/generic/audio-graph-card.c | 4 +- sound/soc/generic/audio-graph-scu-card.c | 4 +- sound/soc/generic/simple-card.c | 8 +- sound/soc/generic/simple-scu-card.c | 4 +- sound/soc/intel/skylake/skl-topology.c | 12 ++- sound/soc/pxa/mmp-sspa.c | 4 +- sound/soc/sh/rcar/cmd.c | 2 +- sound/soc/sh/rcar/core.c | 4 +- sound/soc/sh/rcar/ctu.c | 2 +- sound/soc/sh/rcar/dvc.c | 2 +- sound/soc/sh/rcar/mix.c | 2 +- sound/soc/sh/rcar/src.c | 2 +- sound/soc/sh/rcar/ssi.c | 2 +- sound/soc/sh/rcar/ssiu.c | 2 +- sound/soc/soc-core.c | 6 +- .../audio/4.0/asoc/codecs/bolero/bolero-cdc.c | 7 +- .../4.0/asoc/codecs/bolero/bolero-clk-rsc.c | 2 +- techpack/audio/4.0/asoc/msm-dai-slim.c | 8 +- techpack/audio/4.0/dsp/adsp-loader.c | 8 +- techpack/audio/4.0/soc/pinctrl-wcd.c | 3 +- techpack/audio/4.0/soc/swr-mstr-ctrl.c | 4 +- .../audio/asoc/codecs/bolero/bolero-cdc.c | 7 +- .../asoc/codecs/sdm660_cdc/msm-analog-cdc.c | 4 +- techpack/audio/asoc/msm-dai-slim.c | 8 +- techpack/audio/soc/pinctrl-wcd.c | 3 +- 304 files changed, 1284 insertions(+), 1053 deletions(-) diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index 6cf4988206f2..774b7d4a12d8 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -298,8 +298,8 @@ static int acpi_fan_get_fps(struct acpi_device *device) } fan->fps_count = obj->package.count - 1; /* minus revision field */ - fan->fps = devm_kzalloc(&device->dev, - fan->fps_count * sizeof(struct acpi_fan_fps), + fan->fps = devm_kcalloc(&device->dev, + fan->fps_count, sizeof(struct acpi_fan_fps), GFP_KERNEL); if (!fan->fps) { dev_err(&device->dev, "Not enough memory\n"); diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c index 1872dc01be13..f8694680e5db 100644 --- a/drivers/acpi/nfit/core.c +++ b/drivers/acpi/nfit/core.c @@ -866,9 +866,10 @@ static int __nfit_mem_init(struct acpi_nfit_desc *acpi_desc, continue; nfit_mem->nfit_flush = nfit_flush; flush = nfit_flush->flush; - nfit_mem->flush_wpq = devm_kzalloc(acpi_desc->dev, - flush->hint_count - * sizeof(struct resource), GFP_KERNEL); + nfit_mem->flush_wpq = devm_kcalloc(acpi_desc->dev, + flush->hint_count, + sizeof(struct resource), + GFP_KERNEL); if (!nfit_mem->flush_wpq) return -ENOMEM; for (i = 0; i < flush->hint_count; i++) { diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 3b2246dded74..8c10c3e43880 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -4116,13 +4116,13 @@ static int mv_platform_probe(struct platform_device *pdev) if (!host || !hpriv) return -ENOMEM; - hpriv->port_clks = devm_kzalloc(&pdev->dev, - sizeof(struct clk *) * n_ports, + hpriv->port_clks = devm_kcalloc(&pdev->dev, + n_ports, sizeof(struct clk *), GFP_KERNEL); if (!hpriv->port_clks) return -ENOMEM; - hpriv->port_phys = devm_kzalloc(&pdev->dev, - sizeof(struct phy *) * n_ports, + hpriv->port_phys = devm_kcalloc(&pdev->dev, + n_ports, sizeof(struct phy *), GFP_KERNEL); if (!hpriv->port_phys) return -ENOMEM; diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index dd64b3b37400..7cf613ba13bf 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c @@ -1027,7 +1027,7 @@ static int tpm2_get_cc_attrs_tbl(struct tpm_chip *chip) goto out; } - chip->cc_attrs_tbl = devm_kzalloc(&chip->dev, 4 * nr_commands, + chip->cc_attrs_tbl = devm_kcalloc(&chip->dev, 4, nr_commands, GFP_KERNEL); if (!chip->cc_attrs_tbl) { rc = -ENOMEM; diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c index 6db4204e5d5d..5518a164bdd1 100644 --- a/drivers/clk/bcm/clk-bcm2835.c +++ b/drivers/clk/bcm/clk-bcm2835.c @@ -768,7 +768,7 @@ static int bcm2835_pll_debug_init(struct clk_hw *hw, const struct bcm2835_pll_data *data = pll->data; struct debugfs_reg32 *regs; - regs = devm_kzalloc(cprman->dev, 7 * sizeof(*regs), GFP_KERNEL); + regs = devm_kcalloc(cprman->dev, 7, sizeof(*regs), GFP_KERNEL); if (!regs) return -ENOMEM; @@ -899,7 +899,7 @@ static int bcm2835_pll_divider_debug_init(struct clk_hw *hw, const struct bcm2835_pll_divider_data *data = divider->data; struct debugfs_reg32 *regs; - regs = devm_kzalloc(cprman->dev, 7 * sizeof(*regs), GFP_KERNEL); + regs = devm_kcalloc(cprman->dev, 7, sizeof(*regs), GFP_KERNEL); if (!regs) return -ENOMEM; diff --git a/drivers/clk/msm/clock-a7.c b/drivers/clk/msm/clock-a7.c index 679ecd29c0e4..4b6a39e5fa50 100644 --- a/drivers/clk/msm/clock-a7.c +++ b/drivers/clk/msm/clock-a7.c @@ -196,23 +196,23 @@ static int of_get_fmax_vdd_class(struct platform_device *pdev, struct clk *c, } prop_len /= 2; - vdd->level_votes = devm_kzalloc(&pdev->dev, prop_len * sizeof(int), + vdd->level_votes = devm_kcalloc(&pdev->dev, prop_len, sizeof(int), GFP_KERNEL); if (!vdd->level_votes) return -ENOMEM; - vdd->vdd_uv = devm_kzalloc(&pdev->dev, prop_len * sizeof(int), + vdd->vdd_uv = devm_kcalloc(&pdev->dev, prop_len, sizeof(int), GFP_KERNEL); if (!vdd->vdd_uv) return -ENOMEM; - c->fmax = devm_kzalloc(&pdev->dev, prop_len * sizeof(unsigned long), + c->fmax = devm_kcalloc(&pdev->dev, prop_len, sizeof(unsigned long), GFP_KERNEL); if (!c->fmax) return -ENOMEM; array = devm_kzalloc(&pdev->dev, - prop_len * sizeof(u32) * 2, GFP_KERNEL); + array3_size(prop_len, sizeof(u32), 2), GFP_KERNEL); if (!array) return -ENOMEM; diff --git a/drivers/clk/msm/clock-local2.c b/drivers/clk/msm/clock-local2.c index 3721865fbc09..4aa9db362945 100644 --- a/drivers/clk/msm/clock-local2.c +++ b/drivers/clk/msm/clock-local2.c @@ -2485,7 +2485,7 @@ struct clk_src *msmclk_parse_clk_src(struct device *dev, } num_parents = prop_len / len; - clks = devm_kzalloc(dev, sizeof(*clks) * num_parents, GFP_KERNEL); + clks = devm_kcalloc(dev, num_parents, sizeof(*clks), GFP_KERNEL); if (!clks) return ERR_PTR(-ENOMEM); @@ -2538,8 +2538,8 @@ static int rcg_parse_freq_tbl(struct device *dev, num_rows = prop_len / 6; /* Array is null terminated. */ - rcg->freq_tbl = devm_kzalloc(dev, - sizeof(*rcg->freq_tbl) * (num_rows + 1), + rcg->freq_tbl = devm_kcalloc(dev, + num_rows + 1, sizeof(*rcg->freq_tbl), GFP_KERNEL); if (!rcg->freq_tbl) { @@ -2646,8 +2646,8 @@ static int parse_rec_parents(struct device *dev, if (mux->num_rec_parents <= 0) return 0; - mux->rec_parents = devm_kzalloc(dev, - sizeof(*mux->rec_parents) * mux->num_rec_parents, + mux->rec_parents = devm_kcalloc(dev, + mux->num_rec_parents, sizeof(*mux->rec_parents), GFP_KERNEL); if (!mux->rec_parents) { diff --git a/drivers/clk/msm/gdsc.c b/drivers/clk/msm/gdsc.c index 0614cd86eeea..ecf76698aa36 100644 --- a/drivers/clk/msm/gdsc.c +++ b/drivers/clk/msm/gdsc.c @@ -530,8 +530,8 @@ static int gdsc_probe(struct platform_device *pdev) return -EINVAL; } - sc->clocks = devm_kzalloc(&pdev->dev, - sizeof(struct clk *) * sc->clock_count, GFP_KERNEL); + sc->clocks = devm_kcalloc(&pdev->dev, + sc->clock_count, sizeof(struct clk *), GFP_KERNEL); if (!sc->clocks) return -ENOMEM; @@ -616,9 +616,9 @@ static int gdsc_probe(struct platform_device *pdev) return -EINVAL; } - sc->reset_clocks = devm_kzalloc(&pdev->dev, - sizeof(struct reset_control *) * + sc->reset_clocks = devm_kcalloc(&pdev->dev, sc->reset_count, + sizeof(struct reset_control *), GFP_KERNEL); if (!sc->reset_clocks) return -ENOMEM; diff --git a/drivers/clk/msm/msm-clock-controller.c b/drivers/clk/msm/msm-clock-controller.c index 88f2e0b143e7..08ad7754bf6c 100644 --- a/drivers/clk/msm/msm-clock-controller.c +++ b/drivers/clk/msm/msm-clock-controller.c @@ -75,8 +75,8 @@ static int generic_vdd_parse_regulators(struct device *dev, return -EINVAL; } - vdd->regulator = devm_kzalloc(dev, - sizeof(*vdd->regulator) * num_regulators, + vdd->regulator = devm_kcalloc(dev, + num_regulators, sizeof(*vdd->regulator), GFP_KERNEL); if (!vdd->regulator) { dt_err(np, "memory alloc failure\n"); @@ -121,10 +121,10 @@ static int generic_vdd_parse_levels(struct device *dev, } vdd->num_levels = len / vdd->num_regulators; - vdd->vdd_uv = devm_kzalloc(dev, len * sizeof(*vdd->vdd_uv), + vdd->vdd_uv = devm_kcalloc(dev, len, sizeof(*vdd->vdd_uv), GFP_KERNEL); - vdd->level_votes = devm_kzalloc(dev, - vdd->num_levels * sizeof(*vdd->level_votes), + vdd->level_votes = devm_kcalloc(dev, + vdd->num_levels, sizeof(*vdd->level_votes), GFP_KERNEL); if (!vdd->vdd_uv || !vdd->level_votes) { @@ -150,7 +150,7 @@ static int generic_vdd_parse_levels(struct device *dev, return -EINVAL; } - vdd->vdd_ua = devm_kzalloc(dev, len * sizeof(*vdd->vdd_ua), + vdd->vdd_ua = devm_kcalloc(dev, len, sizeof(*vdd->vdd_ua), GFP_KERNEL); if (!vdd->vdd_ua) return -ENOMEM; @@ -290,7 +290,8 @@ static int generic_clk_parse_fmax(struct device *dev, struct clk *c, return rc; } - c->fmax = devm_kzalloc(dev, sizeof(*c->fmax) * c->num_fmax, GFP_KERNEL); + c->fmax = devm_kcalloc(dev, c->num_fmax, sizeof(*c->fmax), + GFP_KERNEL); if (!c->fmax) return -ENOMEM; diff --git a/drivers/clk/qcom/clk-cpu-qcs405.c b/drivers/clk/qcom/clk-cpu-qcs405.c index 3623924a1dc4..c71b5f5abee2 100644 --- a/drivers/clk/qcom/clk-cpu-qcs405.c +++ b/drivers/clk/qcom/clk-cpu-qcs405.c @@ -367,23 +367,24 @@ static int cpucc_clk_get_fmax_vdd_class(struct platform_device *pdev, } prop_len /= num; - vdd->level_votes = devm_kzalloc(&pdev->dev, prop_len * sizeof(int), + vdd->level_votes = devm_kcalloc(&pdev->dev, prop_len, sizeof(int), GFP_KERNEL); if (!vdd->level_votes) return -ENOMEM; vdd->vdd_uv = devm_kzalloc(&pdev->dev, - prop_len * sizeof(int) * (num - 1), GFP_KERNEL); + array3_size(prop_len, sizeof(int), (num - 1)), + GFP_KERNEL); if (!vdd->vdd_uv) return -ENOMEM; - clk_intd->rate_max = devm_kzalloc(&pdev->dev, - prop_len * sizeof(unsigned long), GFP_KERNEL); + clk_intd->rate_max = devm_kcalloc(&pdev->dev, + prop_len, sizeof(unsigned long), GFP_KERNEL); if (!clk_intd->rate_max) return -ENOMEM; array = devm_kzalloc(&pdev->dev, - prop_len * sizeof(u32) * num, GFP_KERNEL); + array3_size(prop_len, num, sizeof(u32)), GFP_KERNEL); if (!array) return -ENOMEM; diff --git a/drivers/clk/qcom/clk-cpu-sdxprairie.c b/drivers/clk/qcom/clk-cpu-sdxprairie.c index be011b4021ee..038a14e7cbc8 100644 --- a/drivers/clk/qcom/clk-cpu-sdxprairie.c +++ b/drivers/clk/qcom/clk-cpu-sdxprairie.c @@ -326,23 +326,24 @@ static int cpucc_clk_get_fmax_vdd_class(struct platform_device *pdev, } prop_len /= num; - vdd->level_votes = devm_kzalloc(&pdev->dev, prop_len * sizeof(int), + vdd->level_votes = devm_kcalloc(&pdev->dev, prop_len, sizeof(int), GFP_KERNEL); if (!vdd->level_votes) return -ENOMEM; vdd->vdd_uv = devm_kzalloc(&pdev->dev, - prop_len * sizeof(int) * (num - 1), GFP_KERNEL); + array3_size(prop_len, sizeof(int), (num - 1)), + GFP_KERNEL); if (!vdd->vdd_uv) return -ENOMEM; - clk_intd->rate_max = devm_kzalloc(&pdev->dev, - prop_len * sizeof(unsigned long), GFP_KERNEL); + clk_intd->rate_max = devm_kcalloc(&pdev->dev, + prop_len, sizeof(unsigned long), GFP_KERNEL); if (!clk_intd->rate_max) return -ENOMEM; array = devm_kzalloc(&pdev->dev, - prop_len * sizeof(u32) * num, GFP_KERNEL); + array3_size(prop_len, num, sizeof(u32)), GFP_KERNEL); if (!array) return -ENOMEM; diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c index 9fc98819321a..c601d002f13c 100644 --- a/drivers/clk/qcom/clk-rcg2.c +++ b/drivers/clk/qcom/clk-rcg2.c @@ -1620,8 +1620,9 @@ int clk_rcg2_get_dfs_clock_rate(struct clk_rcg2 *clk, struct device *dev, if (!(val & SE_CMD_DFS_EN)) return ret; - dfs_freq_tbl = devm_kzalloc(dev, MAX_PERF_LEVEL * - sizeof(struct freq_tbl), GFP_KERNEL); + dfs_freq_tbl = devm_kcalloc(dev, + MAX_PERF_LEVEL, sizeof(struct freq_tbl), + GFP_KERNEL); if (!dfs_freq_tbl) return -ENOMEM; diff --git a/drivers/clk/qcom/debugcc-atoll.c b/drivers/clk/qcom/debugcc-atoll.c index 81a92cc30df2..076769c53deb 100644 --- a/drivers/clk/qcom/debugcc-atoll.c +++ b/drivers/clk/qcom/debugcc-atoll.c @@ -738,8 +738,8 @@ static int clk_debug_atoll_probe(struct platform_device *pdev) return -EINVAL; } - gcc_debug_mux.regmap = devm_kzalloc(&pdev->dev, - sizeof(struct regmap *) * count, GFP_KERNEL); + gcc_debug_mux.regmap = devm_kcalloc(&pdev->dev, + count, sizeof(struct regmap *), GFP_KERNEL); if (!gcc_debug_mux.regmap) return -ENOMEM; diff --git a/drivers/clk/qcom/debugcc-sdmmagpie.c b/drivers/clk/qcom/debugcc-sdmmagpie.c index 7f9c9701138e..8c4378784485 100644 --- a/drivers/clk/qcom/debugcc-sdmmagpie.c +++ b/drivers/clk/qcom/debugcc-sdmmagpie.c @@ -789,8 +789,8 @@ static int clk_debug_sdmmagpie_probe(struct platform_device *pdev) return -EINVAL; } - gcc_debug_mux.regmap = devm_kzalloc(&pdev->dev, - sizeof(struct regmap *) * count, GFP_KERNEL); + gcc_debug_mux.regmap = devm_kcalloc(&pdev->dev, + count, sizeof(struct regmap *), GFP_KERNEL); if (!gcc_debug_mux.regmap) return -ENOMEM; diff --git a/drivers/clk/qcom/gdsc-regulator.c b/drivers/clk/qcom/gdsc-regulator.c index f689661cfc3d..dc585123dcd1 100644 --- a/drivers/clk/qcom/gdsc-regulator.c +++ b/drivers/clk/qcom/gdsc-regulator.c @@ -772,8 +772,8 @@ static int gdsc_probe(struct platform_device *pdev) return -EINVAL; } - sc->clocks = devm_kzalloc(&pdev->dev, - sizeof(struct clk *) * sc->clock_count, GFP_KERNEL); + sc->clocks = devm_kcalloc(&pdev->dev, + sc->clock_count, sizeof(struct clk *), GFP_KERNEL); if (!sc->clocks) return -ENOMEM; @@ -938,9 +938,9 @@ static int gdsc_probe(struct platform_device *pdev) goto err; } - sc->reset_clocks = devm_kzalloc(&pdev->dev, - sizeof(struct reset_control *) * sc->reset_count, - GFP_KERNEL); + sc->reset_clocks = devm_kcalloc(&pdev->dev, + sc->reset_count, sizeof(struct reset_control *), + GFP_KERNEL); if (!sc->reset_clocks) { ret = -ENOMEM; goto err; diff --git a/drivers/clk/qcom/mdss/mdss-pll-util.c b/drivers/clk/qcom/mdss/mdss-pll-util.c index 3e60d93f08f4..fa2209f47517 100644 --- a/drivers/clk/qcom/mdss/mdss-pll-util.c +++ b/drivers/clk/qcom/mdss/mdss-pll-util.c @@ -172,8 +172,9 @@ static int mdss_pll_util_parse_dt_supply(struct platform_device *pdev, } pr_debug("vreg found. count=%d\n", mp->num_vreg); - mp->vreg_config = devm_kzalloc(&pdev->dev, sizeof(struct dss_vreg) * - mp->num_vreg, GFP_KERNEL); + mp->vreg_config = devm_kcalloc(&pdev->dev, + mp->num_vreg, sizeof(struct dss_vreg), + GFP_KERNEL); if (!mp->vreg_config) { rc = -ENOMEM; return rc; @@ -299,8 +300,8 @@ static int mdss_pll_util_parse_dt_clock(struct platform_device *pdev, goto clk_err; } - mp->clk_config = devm_kzalloc(&pdev->dev, - sizeof(struct dss_clk) * mp->num_clk, GFP_KERNEL); + mp->clk_config = devm_kcalloc(&pdev->dev, + mp->num_clk, sizeof(struct dss_clk), GFP_KERNEL); if (!mp->clk_config) { rc = -ENOMEM; mp->num_clk = 0; diff --git a/drivers/clk/ti/adpll.c b/drivers/clk/ti/adpll.c index d6036c788fab..688e403333b9 100644 --- a/drivers/clk/ti/adpll.c +++ b/drivers/clk/ti/adpll.c @@ -501,8 +501,9 @@ static int ti_adpll_init_dco(struct ti_adpll_data *d) const char *postfix; int width, err; - d->outputs.clks = devm_kzalloc(d->dev, sizeof(struct clk *) * + d->outputs.clks = devm_kcalloc(d->dev, MAX_ADPLL_OUTPUTS, + sizeof(struct clk *), GFP_KERNEL); if (!d->outputs.clks) return -ENOMEM; @@ -915,8 +916,9 @@ static int ti_adpll_probe(struct platform_device *pdev) if (err) return err; - d->clocks = devm_kzalloc(d->dev, sizeof(struct ti_adpll_clock) * + d->clocks = devm_kcalloc(d->dev, TI_ADPLL_NR_CLOCKS, + sizeof(struct ti_adpll_clock), GFP_KERNEL); if (!d->clocks) return -ENOMEM; diff --git a/drivers/cpufreq/brcmstb-avs-cpufreq.c b/drivers/cpufreq/brcmstb-avs-cpufreq.c index 39c462711eae..267416966e93 100644 --- a/drivers/cpufreq/brcmstb-avs-cpufreq.c +++ b/drivers/cpufreq/brcmstb-avs-cpufreq.c @@ -494,7 +494,7 @@ brcm_avs_get_freq_table(struct device *dev, struct private_data *priv) if (ret) return ERR_PTR(ret); - table = devm_kzalloc(dev, (AVS_PSTATE_MAX + 1) * sizeof(*table), + table = devm_kcalloc(dev, AVS_PSTATE_MAX + 1, sizeof(*table), GFP_KERNEL); if (!table) return ERR_PTR(-ENOMEM); diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c index 63d28323a29c..88ecfda4eecf 100644 --- a/drivers/cpufreq/imx6q-cpufreq.c +++ b/drivers/cpufreq/imx6q-cpufreq.c @@ -288,7 +288,8 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev) } /* Make imx6_soc_volt array's size same as arm opp number */ - imx6_soc_volt = devm_kzalloc(cpu_dev, sizeof(*imx6_soc_volt) * num, GFP_KERNEL); + imx6_soc_volt = devm_kcalloc(cpu_dev, num, sizeof(*imx6_soc_volt), + GFP_KERNEL); if (imx6_soc_volt == NULL) { ret = -ENOMEM; goto free_freq_table; diff --git a/drivers/cpufreq/qcom-cpufreq.c b/drivers/cpufreq/qcom-cpufreq.c index 735db9250a16..07055cd4f9b4 100644 --- a/drivers/cpufreq/qcom-cpufreq.c +++ b/drivers/cpufreq/qcom-cpufreq.c @@ -382,7 +382,7 @@ static struct cpufreq_frequency_table *cpufreq_parse_dt(struct device *dev, if (nf == 0) return ERR_PTR(-EINVAL); - data = devm_kzalloc(dev, nf * sizeof(*data), GFP_KERNEL); + data = devm_kcalloc(dev, nf, sizeof(*data), GFP_KERNEL); if (!data) return ERR_PTR(-ENOMEM); @@ -390,7 +390,7 @@ static struct cpufreq_frequency_table *cpufreq_parse_dt(struct device *dev, if (ret) return ERR_PTR(ret); - ftbl = devm_kzalloc(dev, (nf + 1) * sizeof(*ftbl), GFP_KERNEL); + ftbl = devm_kcalloc(dev, nf + 1, sizeof(*ftbl), GFP_KERNEL); if (!ftbl) return ERR_PTR(-ENOMEM); diff --git a/drivers/cpuidle/lpm-levels-of.c b/drivers/cpuidle/lpm-levels-of.c index f2f0bd4d0023..c8bfecd8f902 100644 --- a/drivers/cpuidle/lpm-levels-of.c +++ b/drivers/cpuidle/lpm-levels-of.c @@ -157,8 +157,8 @@ static int create_lvl_avail_nodes(const char *name, goto failed; } - attr = devm_kzalloc(&lpm_pdev->dev, - sizeof(*attr) * (LPM_TYPE_NR + 1), GFP_KERNEL); + attr = devm_kcalloc(&lpm_pdev->dev, + LPM_TYPE_NR + 1, sizeof(*attr), GFP_KERNEL); if (!attr) { ret = -ENOMEM; goto failed; @@ -218,8 +218,10 @@ static int create_cpu_lvl_nodes(struct lpm_cluster *p, struct kobject *parent) int ret = 0; struct list_head *pos; - cpu_kobj = devm_kzalloc(&lpm_pdev->dev, sizeof(*cpu_kobj) * - cpumask_weight(&p->child_cpus), GFP_KERNEL); + cpu_kobj = devm_kcalloc(&lpm_pdev->dev, + cpumask_weight(&p->child_cpus), + sizeof(*cpu_kobj), + GFP_KERNEL); if (!cpu_kobj) return -ENOMEM; @@ -236,8 +238,8 @@ static int create_cpu_lvl_nodes(struct lpm_cluster *p, struct kobject *parent) goto release_kobj; } - level_list = devm_kzalloc(&lpm_pdev->dev, - lpm_cpu->nlevels * sizeof(*level_list), + level_list = devm_kcalloc(&lpm_pdev->dev, + lpm_cpu->nlevels, sizeof(*level_list), GFP_KERNEL); if (!level_list) { ret = -ENOMEM; diff --git a/drivers/crypto/marvell/cesa.c b/drivers/crypto/marvell/cesa.c index 6e7a5c77a00a..b92424e3178b 100644 --- a/drivers/crypto/marvell/cesa.c +++ b/drivers/crypto/marvell/cesa.c @@ -476,7 +476,7 @@ static int mv_cesa_probe(struct platform_device *pdev) sram_size = CESA_SA_MIN_SRAM_SIZE; cesa->sram_size = sram_size; - cesa->engines = devm_kzalloc(dev, caps->nengines * sizeof(*engines), + cesa->engines = devm_kcalloc(dev, caps->nengines, sizeof(*engines), GFP_KERNEL); if (!cesa->engines) return -ENOMEM; diff --git a/drivers/crypto/msm/ice.c b/drivers/crypto/msm/ice.c index 90238a5299bc..04698dce55bf 100644 --- a/drivers/crypto/msm/ice.c +++ b/drivers/crypto/msm/ice.c @@ -596,7 +596,7 @@ static int qcom_ice_parse_clock_info(struct platform_device *pdev, if (len != cnt) goto out; - clkfreq = devm_kzalloc(dev, len * sizeof(*clkfreq), GFP_KERNEL); + clkfreq = devm_kcalloc(dev, len, sizeof(*clkfreq), GFP_KERNEL); if (!clkfreq) { ret = -ENOMEM; goto out; diff --git a/drivers/devfreq/arm-memlat-mon.c b/drivers/devfreq/arm-memlat-mon.c index 740dc6f8d04f..d4e4a85c9de5 100644 --- a/drivers/devfreq/arm-memlat-mon.c +++ b/drivers/devfreq/arm-memlat-mon.c @@ -308,13 +308,17 @@ static int arm_memlat_mon_driver_probe(struct platform_device *pdev) } hw->num_cores = cpumask_weight(&cpu_grp->cpus); - hw->core_stats = devm_kzalloc(dev, hw->num_cores * - sizeof(*(hw->core_stats)), GFP_KERNEL); + hw->core_stats = devm_kcalloc(dev, + hw->num_cores, + sizeof(*(hw->core_stats)), + GFP_KERNEL); if (!hw->core_stats) return -ENOMEM; - cpu_grp->cpustats = devm_kzalloc(dev, hw->num_cores * - sizeof(*(cpu_grp->cpustats)), GFP_KERNEL); + cpu_grp->cpustats = devm_kcalloc(dev, + hw->num_cores, + sizeof(*(cpu_grp->cpustats)), + GFP_KERNEL); if (!cpu_grp->cpustats) return -ENOMEM; diff --git a/drivers/devfreq/bimc-bwmon.c b/drivers/devfreq/bimc-bwmon.c index 8b924abf781f..db13cc3f7f82 100644 --- a/drivers/devfreq/bimc-bwmon.c +++ b/drivers/devfreq/bimc-bwmon.c @@ -1155,7 +1155,7 @@ static int bimc_bwmon_driver_probe(struct platform_device *pdev) return -EINVAL; } - m->clks = devm_kzalloc(dev, sizeof(struct clk *) * m->nr_clks, + m->clks = devm_kcalloc(dev, m->nr_clks, sizeof(struct clk *), GFP_KERNEL); if (!m->clks) return -ENOMEM; diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index cf000d78e8e9..dc0643a6a55e 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -595,13 +595,11 @@ struct devfreq *devfreq_add_device(struct device *dev, } devfreq->trans_table = devm_kzalloc(&devfreq->dev, - sizeof(unsigned int) * - devfreq->profile->max_state * - devfreq->profile->max_state, + array3_size(sizeof(unsigned int), devfreq->profile->max_state, devfreq->profile->max_state), GFP_KERNEL); - devfreq->time_in_state = devm_kzalloc(&devfreq->dev, - sizeof(unsigned long) * + devfreq->time_in_state = devm_kcalloc(&devfreq->dev, devfreq->profile->max_state, + sizeof(unsigned long), GFP_KERNEL); devfreq->last_stat_updated = jiffies; diff --git a/drivers/devfreq/devfreq_simple_dev.c b/drivers/devfreq/devfreq_simple_dev.c index 8566e98af079..9f49184f4356 100644 --- a/drivers/devfreq/devfreq_simple_dev.c +++ b/drivers/devfreq/devfreq_simple_dev.c @@ -105,11 +105,11 @@ static int parse_freq_table(struct device *dev, struct dev_data *d) d->freq_in_khz = true; len /= sizeof(*data); - data = devm_kzalloc(dev, len * sizeof(*data), GFP_KERNEL); + data = devm_kcalloc(dev, len, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; - p->freq_table = devm_kzalloc(dev, len * sizeof(*p->freq_table), + p->freq_table = devm_kcalloc(dev, len, sizeof(*p->freq_table), GFP_KERNEL); if (!p->freq_table) return -ENOMEM; diff --git a/drivers/devfreq/event/exynos-ppmu.c b/drivers/devfreq/event/exynos-ppmu.c index d96e3dc71cf8..3cd6a184fe7c 100644 --- a/drivers/devfreq/event/exynos-ppmu.c +++ b/drivers/devfreq/event/exynos-ppmu.c @@ -518,7 +518,7 @@ static int of_get_devfreq_events(struct device_node *np, event_ops = exynos_bus_get_ops(np); count = of_get_child_count(events_np); - desc = devm_kzalloc(dev, sizeof(*desc) * count, GFP_KERNEL); + desc = devm_kcalloc(dev, count, sizeof(*desc), GFP_KERNEL); if (!desc) return -ENOMEM; info->num_events = count; diff --git a/drivers/devfreq/governor_memlat.c b/drivers/devfreq/governor_memlat.c index 3b6e6fee0c79..78c5c7718b62 100644 --- a/drivers/devfreq/governor_memlat.c +++ b/drivers/devfreq/governor_memlat.c @@ -447,8 +447,8 @@ static struct core_dev_map *init_core_dev_map(struct device *dev, return NULL; nf = len / NUM_COLS; - tbl = devm_kzalloc(dev, (nf + 1) * sizeof(struct core_dev_map), - GFP_KERNEL); + tbl = devm_kcalloc(dev, nf + 1, sizeof(struct core_dev_map), + GFP_KERNEL); if (!tbl) return NULL; diff --git a/drivers/dma/k3dma.c b/drivers/dma/k3dma.c index 803045c92f3b..6a5f0cc9c8c0 100644 --- a/drivers/dma/k3dma.c +++ b/drivers/dma/k3dma.c @@ -847,8 +847,8 @@ static int k3_dma_probe(struct platform_device *op) return -ENOMEM; /* init phy channel */ - d->phy = devm_kzalloc(&op->dev, - d->dma_channels * sizeof(struct k3_dma_phy), GFP_KERNEL); + d->phy = devm_kcalloc(&op->dev, + d->dma_channels, sizeof(struct k3_dma_phy), GFP_KERNEL); if (d->phy == NULL) return -ENOMEM; @@ -877,8 +877,8 @@ static int k3_dma_probe(struct platform_device *op) d->slave.copy_align = DMAENGINE_ALIGN_8_BYTES; /* init virtual channel */ - d->chans = devm_kzalloc(&op->dev, - d->dma_requests * sizeof(struct k3_dma_chan), GFP_KERNEL); + d->chans = devm_kcalloc(&op->dev, + d->dma_requests, sizeof(struct k3_dma_chan), GFP_KERNEL); if (d->chans == NULL) return -ENOMEM; diff --git a/drivers/dma/mv_xor_v2.c b/drivers/dma/mv_xor_v2.c index 75eef589d0ec..d349fedf4ab2 100644 --- a/drivers/dma/mv_xor_v2.c +++ b/drivers/dma/mv_xor_v2.c @@ -809,8 +809,9 @@ static int mv_xor_v2_probe(struct platform_device *pdev) } /* alloc memory for the SW descriptors */ - xor_dev->sw_desq = devm_kzalloc(&pdev->dev, sizeof(*sw_desc) * - MV_XOR_V2_DESC_NUM, GFP_KERNEL); + xor_dev->sw_desq = devm_kcalloc(&pdev->dev, + MV_XOR_V2_DESC_NUM, sizeof(*sw_desc), + GFP_KERNEL); if (!xor_dev->sw_desq) { ret = -ENOMEM; goto free_hw_desq; diff --git a/drivers/dma/qcom/gpi.c b/drivers/dma/qcom/gpi.c index c09b12fd57bf..6455e21a4d38 100644 --- a/drivers/dma/qcom/gpi.c +++ b/drivers/dma/qcom/gpi.c @@ -2985,8 +2985,8 @@ static int gpi_probe(struct platform_device *pdev) return ret; } - gpi_dev->gpiis = devm_kzalloc(gpi_dev->dev, - sizeof(*gpi_dev->gpiis) * gpi_dev->max_gpii, + gpi_dev->gpiis = devm_kcalloc(gpi_dev->dev, + gpi_dev->max_gpii, sizeof(*gpi_dev->gpiis), GFP_KERNEL); if (!gpi_dev->gpiis) return -ENOMEM; diff --git a/drivers/dma/s3c24xx-dma.c b/drivers/dma/s3c24xx-dma.c index f04c4702d98b..7bd6f6439826 100644 --- a/drivers/dma/s3c24xx-dma.c +++ b/drivers/dma/s3c24xx-dma.c @@ -1216,9 +1216,9 @@ static int s3c24xx_dma_probe(struct platform_device *pdev) if (IS_ERR(s3cdma->base)) return PTR_ERR(s3cdma->base); - s3cdma->phy_chans = devm_kzalloc(&pdev->dev, - sizeof(struct s3c24xx_dma_phy) * - pdata->num_phy_channels, + s3cdma->phy_chans = devm_kcalloc(&pdev->dev, + pdata->num_phy_channels, + sizeof(struct s3c24xx_dma_phy), GFP_KERNEL); if (!s3cdma->phy_chans) return -ENOMEM; diff --git a/drivers/dma/zx_dma.c b/drivers/dma/zx_dma.c index 2bb695315300..2571bc7693df 100644 --- a/drivers/dma/zx_dma.c +++ b/drivers/dma/zx_dma.c @@ -798,8 +798,8 @@ static int zx_dma_probe(struct platform_device *op) return -ENOMEM; /* init phy channel */ - d->phy = devm_kzalloc(&op->dev, - d->dma_channels * sizeof(struct zx_dma_phy), GFP_KERNEL); + d->phy = devm_kcalloc(&op->dev, + d->dma_channels, sizeof(struct zx_dma_phy), GFP_KERNEL); if (!d->phy) return -ENOMEM; @@ -834,8 +834,8 @@ static int zx_dma_probe(struct platform_device *op) d->slave.residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT; /* init virtual channel */ - d->chans = devm_kzalloc(&op->dev, - d->dma_requests * sizeof(struct zx_dma_chan), GFP_KERNEL); + d->chans = devm_kcalloc(&op->dev, + d->dma_requests, sizeof(struct zx_dma_chan), GFP_KERNEL); if (!d->chans) return -ENOMEM; diff --git a/drivers/edac/qcom_llcc_edac.c b/drivers/edac/qcom_llcc_edac.c index ddf6776a2494..ba6946376088 100644 --- a/drivers/edac/qcom_llcc_edac.c +++ b/drivers/edac/qcom_llcc_edac.c @@ -427,8 +427,8 @@ static int qcom_llcc_erp_probe(struct platform_device *pdev) drv->num_banks = num_banks; drv->llcc_map = llcc_map; - drv->llcc_banks = devm_kzalloc(&pdev->dev, - sizeof(u32) * drv->num_banks, GFP_KERNEL); + drv->llcc_banks = devm_kcalloc(&pdev->dev, + drv->num_banks, sizeof(u32), GFP_KERNEL); if (!drv->llcc_banks) { dev_err(dev, "Cannot allocate memory for llcc_banks\n"); diff --git a/drivers/extcon/extcon.c b/drivers/extcon/extcon.c index 3a0089d0735a..427f6d25b3fc 100644 --- a/drivers/extcon/extcon.c +++ b/drivers/extcon/extcon.c @@ -1317,8 +1317,8 @@ int extcon_dev_register(struct extcon_dev *edev) goto err_dev; } - edev->bnh = devm_kzalloc(&edev->dev, - sizeof(*edev->bnh) * edev->max_supported, GFP_KERNEL); + edev->bnh = devm_kcalloc(&edev->dev, + edev->max_supported, sizeof(*edev->bnh), GFP_KERNEL); if (!edev->bnh) { ret = -ENOMEM; goto err_dev; diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c index 7da9f1b83ebe..f17b895e5e32 100644 --- a/drivers/firmware/arm_scpi.c +++ b/drivers/firmware/arm_scpi.c @@ -930,7 +930,7 @@ static int scpi_alloc_xfer_list(struct device *dev, struct scpi_chan *ch) int i; struct scpi_xfer *xfers; - xfers = devm_kzalloc(dev, MAX_SCPI_XFERS * sizeof(*xfers), GFP_KERNEL); + xfers = devm_kcalloc(dev, MAX_SCPI_XFERS, sizeof(*xfers), GFP_KERNEL); if (!xfers) return -ENOMEM; diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c index 1620722115cd..a7e9d4798758 100644 --- a/drivers/firmware/ti_sci.c +++ b/drivers/firmware/ti_sci.c @@ -1862,9 +1862,9 @@ static int ti_sci_probe(struct platform_device *pdev) if (!minfo->xfer_block) return -ENOMEM; - minfo->xfer_alloc_table = devm_kzalloc(dev, - BITS_TO_LONGS(desc->max_msgs) - * sizeof(unsigned long), + minfo->xfer_alloc_table = devm_kcalloc(dev, + BITS_TO_LONGS(desc->max_msgs), + sizeof(unsigned long), GFP_KERNEL); if (!minfo->xfer_alloc_table) return -ENOMEM; diff --git a/drivers/gpio/gpio-adnp.c b/drivers/gpio/gpio-adnp.c index ee923b1b820c..6c1280830b62 100644 --- a/drivers/gpio/gpio-adnp.c +++ b/drivers/gpio/gpio-adnp.c @@ -432,7 +432,7 @@ static int adnp_irq_setup(struct adnp *adnp) * is chosen to match the register layout of the hardware in that * each segment contains the corresponding bits for all interrupts. */ - adnp->irq_enable = devm_kzalloc(chip->parent, num_regs * 6, + adnp->irq_enable = devm_kcalloc(chip->parent, num_regs, 6, GFP_KERNEL); if (!adnp->irq_enable) return -ENOMEM; diff --git a/drivers/gpio/gpio-bcm-kona.c b/drivers/gpio/gpio-bcm-kona.c index dfcf56ee3c61..5e7af55a18ef 100644 --- a/drivers/gpio/gpio-bcm-kona.c +++ b/drivers/gpio/gpio-bcm-kona.c @@ -600,9 +600,10 @@ static int bcm_kona_gpio_probe(struct platform_device *pdev) GPIO_MAX_BANK_NUM); return -ENXIO; } - kona_gpio->banks = devm_kzalloc(dev, - kona_gpio->num_bank * - sizeof(*kona_gpio->banks), GFP_KERNEL); + kona_gpio->banks = devm_kcalloc(dev, + kona_gpio->num_bank, + sizeof(*kona_gpio->banks), + GFP_KERNEL); if (!kona_gpio->banks) return -ENOMEM; diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c index e4b3d7db68c9..72b1847d3ce5 100644 --- a/drivers/gpio/gpio-davinci.c +++ b/drivers/gpio/gpio-davinci.c @@ -197,8 +197,8 @@ static int davinci_gpio_probe(struct platform_device *pdev) ngpio = ARCH_NR_GPIOS; nbank = DIV_ROUND_UP(ngpio, 32); - chips = devm_kzalloc(dev, - nbank * sizeof(struct davinci_gpio_controller), + chips = devm_kcalloc(dev, + nbank, sizeof(struct davinci_gpio_controller), GFP_KERNEL); if (!chips) return -ENOMEM; diff --git a/drivers/gpio/gpio-etraxfs.c b/drivers/gpio/gpio-etraxfs.c index 94db1bf4bfdb..403e7de849e7 100644 --- a/drivers/gpio/gpio-etraxfs.c +++ b/drivers/gpio/gpio-etraxfs.c @@ -380,7 +380,8 @@ static int etraxfs_gpio_probe(struct platform_device *pdev) info = match->data; - chips = devm_kzalloc(dev, sizeof(*chips) * info->num_ports, GFP_KERNEL); + chips = devm_kcalloc(dev, info->num_ports, sizeof(*chips), + GFP_KERNEL); if (!chips) return -ENOMEM; diff --git a/drivers/gpio/gpio-htc-egpio.c b/drivers/gpio/gpio-htc-egpio.c index 271356effb2e..c1e0b2170b3f 100644 --- a/drivers/gpio/gpio-htc-egpio.c +++ b/drivers/gpio/gpio-htc-egpio.c @@ -320,8 +320,8 @@ static int __init egpio_probe(struct platform_device *pdev) platform_set_drvdata(pdev, ei); ei->nchips = pdata->num_chips; - ei->chip = devm_kzalloc(&pdev->dev, - sizeof(struct egpio_chip) * ei->nchips, + ei->chip = devm_kcalloc(&pdev->dev, + ei->nchips, sizeof(struct egpio_chip), GFP_KERNEL); if (!ei->chip) { ret = -ENOMEM; diff --git a/drivers/gpio/gpio-thunderx.c b/drivers/gpio/gpio-thunderx.c index 10523ce00c38..21e4dceb2f23 100644 --- a/drivers/gpio/gpio-thunderx.c +++ b/drivers/gpio/gpio-thunderx.c @@ -517,16 +517,17 @@ static int thunderx_gpio_probe(struct pci_dev *pdev, txgpio->base_msi = (c >> 8) & 0xff; } - txgpio->msix_entries = devm_kzalloc(dev, - sizeof(struct msix_entry) * ngpio, + txgpio->msix_entries = devm_kcalloc(dev, + ngpio, sizeof(struct msix_entry), GFP_KERNEL); if (!txgpio->msix_entries) { err = -ENOMEM; goto out; } - txgpio->line_entries = devm_kzalloc(dev, - sizeof(struct thunderx_line) * ngpio, + txgpio->line_entries = devm_kcalloc(dev, + ngpio, + sizeof(struct thunderx_line), GFP_KERNEL); if (!txgpio->line_entries) { err = -ENOMEM; diff --git a/drivers/gpu/drm/bridge/lt9611.c b/drivers/gpu/drm/bridge/lt9611.c index 443a43d3b128..01072beac003 100644 --- a/drivers/gpu/drm/bridge/lt9611.c +++ b/drivers/gpu/drm/bridge/lt9611.c @@ -1343,8 +1343,10 @@ static int lt9611_get_dt_supply(struct device *dev, } pr_debug("vreg found. count=%d\n", pdata->num_vreg); - pdata->vreg_config = devm_kzalloc(dev, sizeof(struct lt9611_vreg) * - pdata->num_vreg, GFP_KERNEL); + pdata->vreg_config = devm_kcalloc(dev, + pdata->num_vreg, + sizeof(struct lt9611_vreg), + GFP_KERNEL); if (!pdata->vreg_config) return -ENOMEM; diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index 366c975cde5b..9b33809be85b 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -1744,8 +1744,8 @@ static int exynos_dsi_probe(struct platform_device *pdev) return ret; } - dsi->clks = devm_kzalloc(dev, - sizeof(*dsi->clks) * dsi->driver_data->num_clks, + dsi->clks = devm_kcalloc(dev, + dsi->driver_data->num_clks, sizeof(*dsi->clks), GFP_KERNEL); if (!dsi->clks) return -ENOMEM; diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 0109ff40b1db..b730f1b86f05 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -1577,7 +1577,7 @@ static int hdmi_clk_init(struct hdmi_context *hdata) if (!count) return 0; - clks = devm_kzalloc(dev, sizeof(*clks) * count, GFP_KERNEL); + clks = devm_kcalloc(dev, count, sizeof(*clks), GFP_KERNEL); if (!clks) return -ENOMEM; diff --git a/drivers/gpu/drm/msm/dp/dp_parser.c b/drivers/gpu/drm/msm/dp/dp_parser.c index a89a51c5b0ff..cbcf25921d6c 100644 --- a/drivers/gpu/drm/msm/dp/dp_parser.c +++ b/drivers/gpu/drm/msm/dp/dp_parser.c @@ -43,8 +43,8 @@ static int dp_parser_reg(struct dp_parser *parser) } io->len = reg_count; - io->data = devm_kzalloc(dev, sizeof(struct dp_io_data) * reg_count, - GFP_KERNEL); + io->data = devm_kcalloc(dev, reg_count, sizeof(struct dp_io_data), + GFP_KERNEL); if (!io->data) return -ENOMEM; @@ -287,8 +287,8 @@ static int dp_parser_gpio(struct dp_parser *parser) if (of_find_property(of_node, "qcom,dp-gpio-aux-switch", NULL)) parser->gpio_aux_switch = true; - mp->gpio_config = devm_kzalloc(dev, - sizeof(struct dss_gpio) * ARRAY_SIZE(dp_gpios), GFP_KERNEL); + mp->gpio_config = devm_kcalloc(dev, + ARRAY_SIZE(dp_gpios), sizeof(struct dss_gpio), GFP_KERNEL); if (!mp->gpio_config) return -ENOMEM; @@ -354,8 +354,8 @@ static int dp_parser_get_vreg(struct dp_parser *parser, pr_debug("vreg found. count=%d\n", mp->num_vreg); } - mp->vreg_config = devm_kzalloc(&parser->pdev->dev, - sizeof(struct dss_vreg) * mp->num_vreg, GFP_KERNEL); + mp->vreg_config = devm_kcalloc(&parser->pdev->dev, + mp->num_vreg, sizeof(struct dss_vreg), GFP_KERNEL); if (!mp->vreg_config) { rc = -ENOMEM; goto error; @@ -558,8 +558,8 @@ static int dp_parser_init_clk_data(struct dp_parser *parser) } core_power->num_clk = core_clk_count; - core_power->clk_config = devm_kzalloc(dev, - sizeof(struct dss_clk) * core_power->num_clk, + core_power->clk_config = devm_kcalloc(dev, + core_power->num_clk, sizeof(struct dss_clk), GFP_KERNEL); if (!core_power->clk_config) { rc = -EINVAL; @@ -571,8 +571,8 @@ static int dp_parser_init_clk_data(struct dp_parser *parser) pr_debug("no strm0 clocks are defined\n"); } else { strm0_power->num_clk = strm0_clk_count; - strm0_power->clk_config = devm_kzalloc(dev, - sizeof(struct dss_clk) * strm0_power->num_clk, + strm0_power->clk_config = devm_kcalloc(dev, + strm0_power->num_clk, sizeof(struct dss_clk), GFP_KERNEL); if (!strm0_power->clk_config) { strm0_power->num_clk = 0; @@ -586,8 +586,8 @@ static int dp_parser_init_clk_data(struct dp_parser *parser) pr_debug("no strm1 clocks are defined\n"); } else { strm1_power->num_clk = strm1_clk_count; - strm1_power->clk_config = devm_kzalloc(dev, - sizeof(struct dss_clk) * strm1_power->num_clk, + strm1_power->clk_config = devm_kcalloc(dev, + strm1_power->num_clk, sizeof(struct dss_clk), GFP_KERNEL); if (!strm1_power->clk_config) { strm1_power->num_clk = 0; @@ -604,8 +604,8 @@ static int dp_parser_init_clk_data(struct dp_parser *parser) } link_power->num_clk = link_clk_count; - link_power->clk_config = devm_kzalloc(dev, - sizeof(struct dss_clk) * link_power->num_clk, + link_power->clk_config = devm_kcalloc(dev, + link_power->num_clk, sizeof(struct dss_clk), GFP_KERNEL); if (!link_power->clk_config) { link_power->num_clk = 0; diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_parser.c b/drivers/gpu/drm/msm/dsi-staging/dsi_parser.c index c66824ee2259..d6e743754da7 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_parser.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_parser.c @@ -254,7 +254,7 @@ static bool dsi_parser_parse_prop(struct device *dev, if (dsi_parser_get_strings(dev, prop, buf)) goto end; - prop->items = devm_kzalloc(dev, strlen(buf) * 2, GFP_KERNEL); + prop->items = devm_kcalloc(dev, strlen(buf), 2, GFP_KERNEL); if (!prop->items) goto end; diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c index f3509e723c0f..eb53bb9db219 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c @@ -157,8 +157,10 @@ static struct hdmi *msm_hdmi_init(struct platform_device *pdev) hdmi->qfprom_mmio = NULL; } - hdmi->hpd_regs = devm_kzalloc(&pdev->dev, sizeof(hdmi->hpd_regs[0]) * - config->hpd_reg_cnt, GFP_KERNEL); + hdmi->hpd_regs = devm_kcalloc(&pdev->dev, + config->hpd_reg_cnt, + sizeof(hdmi->hpd_regs[0]), + GFP_KERNEL); if (!hdmi->hpd_regs) { ret = -ENOMEM; goto fail; @@ -178,8 +180,10 @@ static struct hdmi *msm_hdmi_init(struct platform_device *pdev) hdmi->hpd_regs[i] = reg; } - hdmi->pwr_regs = devm_kzalloc(&pdev->dev, sizeof(hdmi->pwr_regs[0]) * - config->pwr_reg_cnt, GFP_KERNEL); + hdmi->pwr_regs = devm_kcalloc(&pdev->dev, + config->pwr_reg_cnt, + sizeof(hdmi->pwr_regs[0]), + GFP_KERNEL); if (!hdmi->pwr_regs) { ret = -ENOMEM; goto fail; @@ -199,8 +203,10 @@ static struct hdmi *msm_hdmi_init(struct platform_device *pdev) hdmi->pwr_regs[i] = reg; } - hdmi->hpd_clks = devm_kzalloc(&pdev->dev, sizeof(hdmi->hpd_clks[0]) * - config->hpd_clk_cnt, GFP_KERNEL); + hdmi->hpd_clks = devm_kcalloc(&pdev->dev, + config->hpd_clk_cnt, + sizeof(hdmi->hpd_clks[0]), + GFP_KERNEL); if (!hdmi->hpd_clks) { ret = -ENOMEM; goto fail; @@ -219,8 +225,10 @@ static struct hdmi *msm_hdmi_init(struct platform_device *pdev) hdmi->hpd_clks[i] = clk; } - hdmi->pwr_clks = devm_kzalloc(&pdev->dev, sizeof(hdmi->pwr_clks[0]) * - config->pwr_clk_cnt, GFP_KERNEL); + hdmi->pwr_clks = devm_kcalloc(&pdev->dev, + config->pwr_clk_cnt, + sizeof(hdmi->pwr_clks[0]), + GFP_KERNEL); if (!hdmi->pwr_clks) { ret = -ENOMEM; goto fail; diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_phy.c b/drivers/gpu/drm/msm/hdmi/hdmi_phy.c index 534ce5b49781..16987d8679e0 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_phy.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_phy.c @@ -21,12 +21,12 @@ static int msm_hdmi_phy_resource_init(struct hdmi_phy *phy) struct device *dev = &phy->pdev->dev; int i, ret; - phy->regs = devm_kzalloc(dev, sizeof(phy->regs[0]) * cfg->num_regs, + phy->regs = devm_kcalloc(dev, cfg->num_regs, sizeof(phy->regs[0]), GFP_KERNEL); if (!phy->regs) return -ENOMEM; - phy->clks = devm_kzalloc(dev, sizeof(phy->clks[0]) * cfg->num_clks, + phy->clks = devm_kcalloc(dev, cfg->num_clks, sizeof(phy->clks[0]), GFP_KERNEL); if (!phy->clks) return -ENOMEM; diff --git a/drivers/gpu/drm/msm/sde_power_handle.c b/drivers/gpu/drm/msm/sde_power_handle.c index 2e5f4179a70e..59ead5d82bf1 100644 --- a/drivers/gpu/drm/msm/sde_power_handle.c +++ b/drivers/gpu/drm/msm/sde_power_handle.c @@ -164,8 +164,9 @@ static int sde_power_parse_dt_supply(struct platform_device *pdev, } pr_debug("vreg found. count=%d\n", mp->num_vreg); - mp->vreg_config = devm_kzalloc(&pdev->dev, sizeof(struct dss_vreg) * - mp->num_vreg, GFP_KERNEL); + mp->vreg_config = devm_kcalloc(&pdev->dev, + mp->num_vreg, sizeof(struct dss_vreg), + GFP_KERNEL); if (!mp->vreg_config) { rc = -ENOMEM; return rc; @@ -299,8 +300,8 @@ static int sde_power_parse_dt_clock(struct platform_device *pdev, } mp->num_clk = num_clk; - mp->clk_config = devm_kzalloc(&pdev->dev, - sizeof(struct dss_clk) * num_clk, GFP_KERNEL); + mp->clk_config = devm_kcalloc(&pdev->dev, + num_clk, sizeof(struct dss_clk), GFP_KERNEL); if (!mp->clk_config) { rc = -ENOMEM; mp->num_clk = 0; diff --git a/drivers/gpu/drm/msm/shp/shp_drm.c b/drivers/gpu/drm/msm/shp/shp_drm.c index d2b3ecebf9fb..2a27d1799bb2 100644 --- a/drivers/gpu/drm/msm/shp/shp_drm.c +++ b/drivers/gpu/drm/msm/shp/shp_drm.c @@ -428,8 +428,8 @@ static int shp_parse(struct platform_device *pdev, struct shp_device *shp) system_count = priv->num_planes; total_count = dup_count + system_count; - shp->planes = devm_kzalloc(&pdev->dev, - sizeof(*shp_plane) * total_count, GFP_KERNEL); + shp->planes = devm_kcalloc(&pdev->dev, + total_count, sizeof(*shp_plane), GFP_KERNEL); if (!shp->planes) { rc = -ENOMEM; goto out; diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c index b5bd5cb7d532..4256fdc5cd6d 100644 --- a/drivers/hid/hid-sensor-hub.c +++ b/drivers/hid/hid-sensor-hub.c @@ -653,7 +653,8 @@ static int sensor_hub_probe(struct hid_device *hdev, ret = -EINVAL; goto err_stop_hw; } - sd->hid_sensor_hub_client_devs = devm_kzalloc(&hdev->dev, dev_cnt * + sd->hid_sensor_hub_client_devs = devm_kcalloc(&hdev->dev, + dev_cnt, sizeof(struct mfd_cell), GFP_KERNEL); if (sd->hid_sensor_hub_client_devs == NULL) { diff --git a/drivers/hid/intel-ish-hid/ishtp-hid-client.c b/drivers/hid/intel-ish-hid/ishtp-hid-client.c index 157b44aacdff..295d8fdff342 100644 --- a/drivers/hid/intel-ish-hid/ishtp-hid-client.c +++ b/drivers/hid/intel-ish-hid/ishtp-hid-client.c @@ -121,9 +121,9 @@ static void process_recv(struct ishtp_cl *hid_ishtp_cl, void *recv_buf, } client_data->hid_dev_count = (unsigned int)*payload; if (!client_data->hid_devices) - client_data->hid_devices = devm_kzalloc( + client_data->hid_devices = devm_kcalloc( &client_data->cl_device->dev, - client_data->hid_dev_count * + client_data->hid_dev_count, sizeof(struct device_info), GFP_KERNEL); if (!client_data->hid_devices) { diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index bf8e727988c4..7b531f9feefd 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -1267,7 +1267,7 @@ static int wacom_led_groups_alloc_and_register_one(struct device *dev, if (!devres_open_group(dev, &wacom->led.groups[group_id], GFP_KERNEL)) return -ENOMEM; - leds = devm_kzalloc(dev, sizeof(struct wacom_led) * count, GFP_KERNEL); + leds = devm_kcalloc(dev, count, sizeof(struct wacom_led), GFP_KERNEL); if (!leds) { error = -ENOMEM; goto err; @@ -1367,7 +1367,7 @@ static int wacom_led_groups_allocate(struct wacom *wacom, int count) struct wacom_group_leds *groups; int error; - groups = devm_kzalloc(dev, sizeof(struct wacom_group_leds) * count, + groups = devm_kcalloc(dev, count, sizeof(struct wacom_group_leds), GFP_KERNEL); if (!groups) return -ENOMEM; diff --git a/drivers/hwmon/aspeed-pwm-tacho.c b/drivers/hwmon/aspeed-pwm-tacho.c index e4337e9dda44..f9b0342ef0c8 100644 --- a/drivers/hwmon/aspeed-pwm-tacho.c +++ b/drivers/hwmon/aspeed-pwm-tacho.c @@ -894,7 +894,7 @@ static int aspeed_create_fan(struct device *dev, count = of_property_count_u8_elems(child, "aspeed,fan-tach-ch"); if (count < 1) return -EINVAL; - fan_tach_ch = devm_kzalloc(dev, sizeof(*fan_tach_ch) * count, + fan_tach_ch = devm_kcalloc(dev, count, sizeof(*fan_tach_ch), GFP_KERNEL); if (!fan_tach_ch) return -ENOMEM; diff --git a/drivers/hwmon/gpio-fan.c b/drivers/hwmon/gpio-fan.c index 9c355b9d31c5..bd673ccaf4e9 100644 --- a/drivers/hwmon/gpio-fan.c +++ b/drivers/hwmon/gpio-fan.c @@ -477,7 +477,7 @@ static int gpio_fan_get_of_pdata(struct device *dev, dev_err(dev, "DT properties empty / missing"); return -ENODEV; } - ctrl = devm_kzalloc(dev, pdata->num_ctrl * sizeof(unsigned), + ctrl = devm_kcalloc(dev, pdata->num_ctrl, sizeof(unsigned), GFP_KERNEL); if (!ctrl) return -ENOMEM; @@ -509,8 +509,8 @@ static int gpio_fan_get_of_pdata(struct device *dev, * Speed map is in the form * this needs splitting into pairs to create gpio_fan_speed structs */ - speed = devm_kzalloc(dev, - pdata->num_speed * sizeof(struct gpio_fan_speed), + speed = devm_kcalloc(dev, + pdata->num_speed, sizeof(struct gpio_fan_speed), GFP_KERNEL); if (!speed) return -ENOMEM; diff --git a/drivers/hwmon/ibmpowernv.c b/drivers/hwmon/ibmpowernv.c index b38f4951c94e..f15b286bf111 100644 --- a/drivers/hwmon/ibmpowernv.c +++ b/drivers/hwmon/ibmpowernv.c @@ -322,9 +322,9 @@ static int populate_attr_groups(struct platform_device *pdev) of_node_put(opal); for (type = 0; type < MAX_SENSOR_TYPE; type++) { - sensor_groups[type].group.attrs = devm_kzalloc(&pdev->dev, - sizeof(struct attribute *) * - (sensor_groups[type].attr_count + 1), + sensor_groups[type].group.attrs = devm_kcalloc(&pdev->dev, + sensor_groups[type].attr_count + 1, + sizeof(struct attribute *), GFP_KERNEL); if (!sensor_groups[type].group.attrs) return -ENOMEM; @@ -405,7 +405,8 @@ static int create_device_attrs(struct platform_device *pdev) int err = 0; opal = of_find_node_by_path("/ibm,opal/sensors"); - sdata = devm_kzalloc(&pdev->dev, pdata->sensors_count * sizeof(*sdata), + sdata = devm_kcalloc(&pdev->dev, + pdata->sensors_count, sizeof(*sdata), GFP_KERNEL); if (!sdata) { err = -ENOMEM; diff --git a/drivers/hwmon/iio_hwmon.c b/drivers/hwmon/iio_hwmon.c index f6a76679c650..2eeb52e6fe37 100644 --- a/drivers/hwmon/iio_hwmon.c +++ b/drivers/hwmon/iio_hwmon.c @@ -91,8 +91,8 @@ static int iio_hwmon_probe(struct platform_device *pdev) while (st->channels[st->num_channels].indio_dev) st->num_channels++; - st->attrs = devm_kzalloc(dev, - sizeof(*st->attrs) * (st->num_channels + 1), + st->attrs = devm_kcalloc(dev, + st->num_channels + 1, sizeof(*st->attrs), GFP_KERNEL); if (st->attrs == NULL) { ret = -ENOMEM; diff --git a/drivers/hwmon/nct6683.c b/drivers/hwmon/nct6683.c index 8b0bc4fc06e8..43aa38933d1c 100644 --- a/drivers/hwmon/nct6683.c +++ b/drivers/hwmon/nct6683.c @@ -426,12 +426,12 @@ nct6683_create_attr_group(struct device *dev, if (group == NULL) return ERR_PTR(-ENOMEM); - attrs = devm_kzalloc(dev, sizeof(*attrs) * (repeat * count + 1), + attrs = devm_kcalloc(dev, repeat * count + 1, sizeof(*attrs), GFP_KERNEL); if (attrs == NULL) return ERR_PTR(-ENOMEM); - su = devm_kzalloc(dev, sizeof(*su) * repeat * count, + su = devm_kzalloc(dev, array3_size(repeat, count, sizeof(*su)), GFP_KERNEL); if (su == NULL) return ERR_PTR(-ENOMEM); diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c index 7e14143ed119..42ad3bb2c427 100644 --- a/drivers/hwmon/nct6775.c +++ b/drivers/hwmon/nct6775.c @@ -1149,12 +1149,12 @@ nct6775_create_attr_group(struct device *dev, if (group == NULL) return ERR_PTR(-ENOMEM); - attrs = devm_kzalloc(dev, sizeof(*attrs) * (repeat * count + 1), + attrs = devm_kcalloc(dev, repeat * count + 1, sizeof(*attrs), GFP_KERNEL); if (attrs == NULL) return ERR_PTR(-ENOMEM); - su = devm_kzalloc(dev, sizeof(*su) * repeat * count, + su = devm_kzalloc(dev, array3_size(repeat, count, sizeof(*su)), GFP_KERNEL); if (su == NULL) return ERR_PTR(-ENOMEM); diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c index cb9064ac4977..c8982cb07768 100644 --- a/drivers/hwmon/pmbus/pmbus_core.c +++ b/drivers/hwmon/pmbus/pmbus_core.c @@ -1992,8 +1992,8 @@ static int pmbus_init_debugfs(struct i2c_client *client, } /* Allocate the max possible entries we need. */ - entries = devm_kzalloc(data->dev, - sizeof(*entries) * (data->info->pages * 10), + entries = devm_kcalloc(data->dev, + data->info->pages * 10, sizeof(*entries), GFP_KERNEL); if (!entries) return -ENOMEM; diff --git a/drivers/hwmon/pwm-fan.c b/drivers/hwmon/pwm-fan.c index f981da686d7e..65de80bd63d8 100644 --- a/drivers/hwmon/pwm-fan.c +++ b/drivers/hwmon/pwm-fan.c @@ -180,7 +180,7 @@ static int pwm_fan_of_get_cooling_data(struct device *dev, } num = ret; - ctx->pwm_fan_cooling_levels = devm_kzalloc(dev, num * sizeof(u32), + ctx->pwm_fan_cooling_levels = devm_kcalloc(dev, num, sizeof(u32), GFP_KERNEL); if (!ctx->pwm_fan_cooling_levels) return -ENOMEM; diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c index e1132524f4c8..38f4e49022a7 100644 --- a/drivers/hwtracing/coresight/coresight-etb10.c +++ b/drivers/hwtracing/coresight/coresight-etb10.c @@ -748,8 +748,8 @@ static int etb_probe(struct amba_device *adev, const struct amba_id *id) if (drvdata->buffer_depth & 0x80000000) return -EINVAL; - drvdata->buf = devm_kzalloc(dev, - drvdata->buffer_depth * 4, GFP_KERNEL); + drvdata->buf = devm_kcalloc(dev, + drvdata->buffer_depth, 4, GFP_KERNEL); if (!drvdata->buf) return -ENOMEM; diff --git a/drivers/hwtracing/coresight/coresight-hwevent.c b/drivers/hwtracing/coresight/coresight-hwevent.c index d06fe1d749d1..0ed6b4675bff 100644 --- a/drivers/hwtracing/coresight/coresight-hwevent.c +++ b/drivers/hwtracing/coresight/coresight-hwevent.c @@ -204,7 +204,8 @@ static int hwevent_probe(struct platform_device *pdev) drvdata->nr_hmux = 0; if (drvdata->nr_hmux > 0) { - drvdata->hmux = devm_kzalloc(dev, drvdata->nr_hmux * + drvdata->hmux = devm_kcalloc(dev, + drvdata->nr_hmux, sizeof(*drvdata->hmux), GFP_KERNEL); if (!drvdata->hmux) @@ -236,7 +237,8 @@ static int hwevent_probe(struct platform_device *pdev) "qcom,hwevent-regs"); if (drvdata->nr_hclk > 0) { - drvdata->hclk = devm_kzalloc(dev, drvdata->nr_hclk * + drvdata->hclk = devm_kcalloc(dev, + drvdata->nr_hclk, sizeof(*drvdata->hclk), GFP_KERNEL); if (!drvdata->hclk) @@ -255,7 +257,8 @@ static int hwevent_probe(struct platform_device *pdev) } } if (drvdata->nr_hreg > 0) { - drvdata->hreg = devm_kzalloc(dev, drvdata->nr_hreg * + drvdata->hreg = devm_kcalloc(dev, + drvdata->nr_hreg, sizeof(*drvdata->hreg), GFP_KERNEL); if (!drvdata->hreg) diff --git a/drivers/hwtracing/coresight/coresight-tgu.c b/drivers/hwtracing/coresight/coresight-tgu.c index 31e10b52ac1d..ca17fed4b139 100644 --- a/drivers/hwtracing/coresight/coresight-tgu.c +++ b/drivers/hwtracing/coresight/coresight-tgu.c @@ -458,34 +458,39 @@ static int tgu_probe(struct amba_device *adev, const struct amba_id *id) return -EINVAL; /* Alloc memory for Grps, Conditions and Steps */ - drvdata->grp_data = devm_kzalloc(dev, MAX_GROUP_SETS * - sizeof(*drvdata->grp_data), - GFP_KERNEL); + drvdata->grp_data = devm_kcalloc(dev, + MAX_GROUP_SETS, + sizeof(*drvdata->grp_data), + GFP_KERNEL); if (!drvdata->grp_data) return -ENOMEM; - drvdata->condition_data = devm_kzalloc(dev, MAX_CONDITION_SETS * - sizeof(*drvdata->condition_data), - GFP_KERNEL); + drvdata->condition_data = devm_kcalloc(dev, + MAX_CONDITION_SETS, + sizeof(*drvdata->condition_data), + GFP_KERNEL); if (!drvdata->condition_data) return -ENOMEM; - drvdata->select_data = devm_kzalloc(dev, MAX_CONDITION_SETS * - sizeof(*drvdata->select_data), - GFP_KERNEL); + drvdata->select_data = devm_kcalloc(dev, + MAX_CONDITION_SETS, + sizeof(*drvdata->select_data), + GFP_KERNEL); if (!drvdata->select_data) return -ENOMEM; - drvdata->timer_data = devm_kzalloc(dev, MAX_TIMER_COUNTER_SETS * - sizeof(*drvdata->timer_data), - GFP_KERNEL); + drvdata->timer_data = devm_kcalloc(dev, + MAX_TIMER_COUNTER_SETS, + sizeof(*drvdata->timer_data), + GFP_KERNEL); if (!drvdata->timer_data) return -ENOMEM; - drvdata->counter_data = devm_kzalloc(dev, MAX_TIMER_COUNTER_SETS * - sizeof(*drvdata->counter_data), - GFP_KERNEL); + drvdata->counter_data = devm_kcalloc(dev, + MAX_TIMER_COUNTER_SETS, + sizeof(*drvdata->counter_data), + GFP_KERNEL); if (!drvdata->counter_data) return -ENOMEM; diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index 18c0ce7d84fa..d14a31b00b0f 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -4437,7 +4437,8 @@ static int tpdm_probe(struct amba_device *adev, const struct amba_id *id) drvdata->nr_tclk = of_property_count_strings(adev->dev.of_node, "qcom,tpdm-clks"); if (drvdata->nr_tclk > 0) { - drvdata->tclk = devm_kzalloc(dev, drvdata->nr_tclk * + drvdata->tclk = devm_kcalloc(dev, + drvdata->nr_tclk, sizeof(*drvdata->tclk), GFP_KERNEL); if (!drvdata->tclk) @@ -4459,7 +4460,8 @@ static int tpdm_probe(struct amba_device *adev, const struct amba_id *id) drvdata->nr_treg = of_property_count_strings(adev->dev.of_node, "qcom,tpdm-regs"); if (drvdata->nr_treg > 0) { - drvdata->treg = devm_kzalloc(dev, drvdata->nr_treg * + drvdata->treg = devm_kcalloc(dev, + drvdata->nr_treg, sizeof(*drvdata->treg), GFP_KERNEL); if (!drvdata->treg) diff --git a/drivers/hwtracing/coresight/of_coresight.c b/drivers/hwtracing/coresight/of_coresight.c index 3374394a4df4..d11d0c6292f6 100644 --- a/drivers/hwtracing/coresight/of_coresight.c +++ b/drivers/hwtracing/coresight/of_coresight.c @@ -85,27 +85,31 @@ static int of_coresight_alloc_memory(struct device *dev, struct coresight_platform_data *pdata) { /* List of output port on this component */ - pdata->outports = devm_kzalloc(dev, pdata->nr_outport * + pdata->outports = devm_kcalloc(dev, + pdata->nr_outport, sizeof(*pdata->outports), GFP_KERNEL); if (!pdata->outports) return -ENOMEM; - pdata->source_names = devm_kzalloc(dev, pdata->nr_outport * - sizeof(*pdata->source_names), - GFP_KERNEL); + pdata->source_names = devm_kcalloc(dev, + pdata->nr_outport, + sizeof(*pdata->source_names), + GFP_KERNEL); if (!pdata->source_names) return -ENOMEM; /* Children connected to this component via @outports */ - pdata->child_names = devm_kzalloc(dev, pdata->nr_outport * + pdata->child_names = devm_kcalloc(dev, + pdata->nr_outport, sizeof(*pdata->child_names), GFP_KERNEL); if (!pdata->child_names) return -ENOMEM; /* Port number on the child this component is connected to */ - pdata->child_ports = devm_kzalloc(dev, pdata->nr_outport * + pdata->child_ports = devm_kcalloc(dev, + pdata->nr_outport, sizeof(*pdata->child_ports), GFP_KERNEL); if (!pdata->child_ports) @@ -149,8 +153,9 @@ of_coresight_get_reg_clk(struct device *dev, const struct device_node *node) reg_clk->nr_reg = nr_reg; reg_clk->nr_clk = nr_clk; if (nr_reg > 0) { - reg_clk->reg = devm_kzalloc(dev, nr_reg * - sizeof(reg_clk->reg), GFP_KERNEL); + reg_clk->reg = devm_kcalloc(dev, + nr_reg, sizeof(reg_clk->reg), + GFP_KERNEL); if (!reg_clk->reg) return ERR_PTR(-ENOMEM); @@ -165,8 +170,9 @@ of_coresight_get_reg_clk(struct device *dev, const struct device_node *node) } } if (nr_clk > 0) { - reg_clk->clk = devm_kzalloc(dev, nr_clk * - sizeof(reg_clk->clk), GFP_KERNEL); + reg_clk->clk = devm_kcalloc(dev, + nr_clk, sizeof(reg_clk->clk), + GFP_KERNEL); if (!reg_clk->clk) return ERR_PTR(-ENOMEM); @@ -336,7 +342,8 @@ struct coresight_cti_data *of_get_coresight_cti_data( return ERR_PTR(-EINVAL); if (ctidata->nr_ctis) { - ctidata->names = devm_kzalloc(dev, ctidata->nr_ctis * + ctidata->names = devm_kcalloc(dev, + ctidata->nr_ctis, sizeof(*ctidata->names), GFP_KERNEL); if (!ctidata->names) diff --git a/drivers/i2c/busses/i2c-msm-v2.c b/drivers/i2c/busses/i2c-msm-v2.c index 69c4a71826c0..42ef4f0472c2 100644 --- a/drivers/i2c/busses/i2c-msm-v2.c +++ b/drivers/i2c/busses/i2c-msm-v2.c @@ -1598,11 +1598,11 @@ static int i2c_msm_clk_path_init_structs(struct i2c_msm_ctrl *ctrl) i2c_msm_dbg(ctrl, MSM_PROF, "initializes path clock voting structs\n"); - paths = devm_kzalloc(ctrl->dev, sizeof(*paths) * 2, GFP_KERNEL); + paths = devm_kcalloc(ctrl->dev, 2, sizeof(*paths), GFP_KERNEL); if (!paths) return -ENOMEM; - usecases = devm_kzalloc(ctrl->dev, sizeof(*usecases) * 2, GFP_KERNEL); + usecases = devm_kcalloc(ctrl->dev, 2, sizeof(*usecases), GFP_KERNEL); if (!usecases) goto path_init_err; diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c index 8f6903ec7aec..fa5d8e0068e2 100644 --- a/drivers/i2c/busses/i2c-qup.c +++ b/drivers/i2c/busses/i2c-qup.c @@ -1459,8 +1459,8 @@ static int qup_i2c_probe(struct platform_device *pdev) goto nodma; blocks = (MX_BLOCKS << 1) + 1; - qup->btx.sg = devm_kzalloc(&pdev->dev, - sizeof(*qup->btx.sg) * blocks, + qup->btx.sg = devm_kcalloc(&pdev->dev, + blocks, sizeof(*qup->btx.sg), GFP_KERNEL); if (!qup->btx.sg) { ret = -ENOMEM; @@ -1468,8 +1468,8 @@ static int qup_i2c_probe(struct platform_device *pdev) } sg_init_table(qup->btx.sg, blocks); - qup->brx.sg = devm_kzalloc(&pdev->dev, - sizeof(*qup->brx.sg) * blocks, + qup->brx.sg = devm_kcalloc(&pdev->dev, + blocks, sizeof(*qup->brx.sg), GFP_KERNEL); if (!qup->brx.sg) { ret = -ENOMEM; diff --git a/drivers/i2c/muxes/i2c-mux-gpio.c b/drivers/i2c/muxes/i2c-mux-gpio.c index 1a9973ede443..ddc4bd4ca13b 100644 --- a/drivers/i2c/muxes/i2c-mux-gpio.c +++ b/drivers/i2c/muxes/i2c-mux-gpio.c @@ -88,8 +88,8 @@ static int i2c_mux_gpio_probe_dt(struct gpiomux *mux, mux->data.n_values = of_get_child_count(np); - values = devm_kzalloc(&pdev->dev, - sizeof(*mux->data.values) * mux->data.n_values, + values = devm_kcalloc(&pdev->dev, + mux->data.n_values, sizeof(*mux->data.values), GFP_KERNEL); if (!values) { dev_err(&pdev->dev, "Cannot allocate values array"); @@ -111,8 +111,9 @@ static int i2c_mux_gpio_probe_dt(struct gpiomux *mux, return -EINVAL; } - gpios = devm_kzalloc(&pdev->dev, - sizeof(*mux->data.gpios) * mux->data.n_gpios, GFP_KERNEL); + gpios = devm_kcalloc(&pdev->dev, + mux->data.n_gpios, sizeof(*mux->data.gpios), + GFP_KERNEL); if (!gpios) { dev_err(&pdev->dev, "Cannot allocate gpios array"); return -ENOMEM; diff --git a/drivers/i2c/muxes/i2c-mux-reg.c b/drivers/i2c/muxes/i2c-mux-reg.c index d97031804de8..92af78769600 100644 --- a/drivers/i2c/muxes/i2c-mux-reg.c +++ b/drivers/i2c/muxes/i2c-mux-reg.c @@ -127,8 +127,8 @@ static int i2c_mux_reg_probe_dt(struct regmux *mux, else mux->data.write_only = false; - values = devm_kzalloc(&pdev->dev, - sizeof(*mux->data.values) * mux->data.n_values, + values = devm_kcalloc(&pdev->dev, + mux->data.n_values, sizeof(*mux->data.values), GFP_KERNEL); if (!values) { dev_err(&pdev->dev, "Cannot allocate values array"); diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index 492f6c8ba735..465b7b065ac8 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c @@ -629,8 +629,8 @@ static int at91_adc_trigger_init(struct iio_dev *idev) struct at91_adc_state *st = iio_priv(idev); int i, ret; - st->trig = devm_kzalloc(&idev->dev, - st->trigger_number * sizeof(*st->trig), + st->trig = devm_kcalloc(&idev->dev, + st->trigger_number, sizeof(*st->trig), GFP_KERNEL); if (st->trig == NULL) { @@ -919,7 +919,8 @@ static int at91_adc_probe_dt(struct at91_adc_state *st, st->registers = &st->caps->registers; st->num_channels = st->caps->num_channels; st->trigger_number = of_get_child_count(node); - st->trigger_list = devm_kzalloc(&idev->dev, st->trigger_number * + st->trigger_list = devm_kcalloc(&idev->dev, + st->trigger_number, sizeof(struct at91_adc_trigger), GFP_KERNEL); if (!st->trigger_list) { diff --git a/drivers/iio/adc/max1363.c b/drivers/iio/adc/max1363.c index 80eada4886b3..7f255486bff0 100644 --- a/drivers/iio/adc/max1363.c +++ b/drivers/iio/adc/max1363.c @@ -1455,8 +1455,8 @@ static int max1363_alloc_scan_masks(struct iio_dev *indio_dev) int i; masks = devm_kzalloc(&indio_dev->dev, - BITS_TO_LONGS(MAX1363_MAX_CHANNELS) * sizeof(long) * - (st->chip_info->num_modes + 1), GFP_KERNEL); + array3_size(BITS_TO_LONGS(MAX1363_MAX_CHANNELS), sizeof(long), (st->chip_info->num_modes + 1)), + GFP_KERNEL); if (!masks) return -ENOMEM; diff --git a/drivers/iio/adc/twl6030-gpadc.c b/drivers/iio/adc/twl6030-gpadc.c index bc0e60b9da45..b74a1f410ff8 100644 --- a/drivers/iio/adc/twl6030-gpadc.c +++ b/drivers/iio/adc/twl6030-gpadc.c @@ -899,9 +899,10 @@ static int twl6030_gpadc_probe(struct platform_device *pdev) gpadc = iio_priv(indio_dev); - gpadc->twl6030_cal_tbl = devm_kzalloc(dev, - sizeof(*gpadc->twl6030_cal_tbl) * - pdata->nchannels, GFP_KERNEL); + gpadc->twl6030_cal_tbl = devm_kcalloc(dev, + pdata->nchannels, + sizeof(*gpadc->twl6030_cal_tbl), + GFP_KERNEL); if (!gpadc->twl6030_cal_tbl) return -ENOMEM; diff --git a/drivers/iio/dac/ad5592r-base.c b/drivers/iio/dac/ad5592r-base.c index 69bde5909854..93c9b461c955 100644 --- a/drivers/iio/dac/ad5592r-base.c +++ b/drivers/iio/dac/ad5592r-base.c @@ -537,8 +537,9 @@ static int ad5592r_alloc_channels(struct ad5592r_state *st) st->channel_offstate[reg] = tmp; } - channels = devm_kzalloc(st->dev, - (1 + 2 * num_channels) * sizeof(*channels), GFP_KERNEL); + channels = devm_kcalloc(st->dev, + 1 + 2 * num_channels, sizeof(*channels), + GFP_KERNEL); if (!channels) return -ENOMEM; diff --git a/drivers/iio/multiplexer/iio-mux.c b/drivers/iio/multiplexer/iio-mux.c index 74831fcd0313..805c66517468 100644 --- a/drivers/iio/multiplexer/iio-mux.c +++ b/drivers/iio/multiplexer/iio-mux.c @@ -282,9 +282,10 @@ static int mux_configure_channel(struct device *dev, struct mux *mux, if (!page) return -ENOMEM; } - child->ext_info_cache = devm_kzalloc(dev, - sizeof(*child->ext_info_cache) * - num_ext_info, GFP_KERNEL); + child->ext_info_cache = devm_kcalloc(dev, + num_ext_info, + sizeof(*child->ext_info_cache), + GFP_KERNEL); if (!child->ext_info_cache) return -ENOMEM; diff --git a/drivers/input/keyboard/clps711x-keypad.c b/drivers/input/keyboard/clps711x-keypad.c index 997e3e97f573..e319f745771a 100644 --- a/drivers/input/keyboard/clps711x-keypad.c +++ b/drivers/input/keyboard/clps711x-keypad.c @@ -109,8 +109,8 @@ static int clps711x_keypad_probe(struct platform_device *pdev) if (priv->row_count < 1) return -EINVAL; - priv->gpio_data = devm_kzalloc(dev, - sizeof(*priv->gpio_data) * priv->row_count, + priv->gpio_data = devm_kcalloc(dev, + priv->row_count, sizeof(*priv->gpio_data), GFP_KERNEL); if (!priv->gpio_data) return -ENOMEM; diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c index c04559a232f7..3d1cb7bf5e35 100644 --- a/drivers/input/keyboard/matrix_keypad.c +++ b/drivers/input/keyboard/matrix_keypad.c @@ -443,9 +443,9 @@ matrix_keypad_parse_dt(struct device *dev) of_property_read_u32(np, "col-scan-delay-us", &pdata->col_scan_delay_us); - gpios = devm_kzalloc(dev, - sizeof(unsigned int) * - (pdata->num_row_gpios + pdata->num_col_gpios), + gpios = devm_kcalloc(dev, + pdata->num_row_gpios + pdata->num_col_gpios, + sizeof(unsigned int), GFP_KERNEL); if (!gpios) { dev_err(dev, "could not allocate memory for gpios\n"); diff --git a/drivers/input/keyboard/samsung-keypad.c b/drivers/input/keyboard/samsung-keypad.c index 316414465c77..1fe1aa2adf85 100644 --- a/drivers/input/keyboard/samsung-keypad.c +++ b/drivers/input/keyboard/samsung-keypad.c @@ -281,7 +281,7 @@ samsung_keypad_parse_dt(struct device *dev) key_count = of_get_child_count(np); keymap_data->keymap_size = key_count; - keymap = devm_kzalloc(dev, sizeof(uint32_t) * key_count, GFP_KERNEL); + keymap = devm_kcalloc(dev, key_count, sizeof(uint32_t), GFP_KERNEL); if (!keymap) { dev_err(dev, "could not allocate memory for keymap\n"); return ERR_PTR(-ENOMEM); diff --git a/drivers/input/matrix-keymap.c b/drivers/input/matrix-keymap.c index 8ccefc15c7a4..8b3a5758451e 100644 --- a/drivers/input/matrix-keymap.c +++ b/drivers/input/matrix-keymap.c @@ -170,8 +170,8 @@ int matrix_keypad_build_keymap(const struct matrix_keymap_data *keymap_data, return -EINVAL; if (!keymap) { - keymap = devm_kzalloc(input_dev->dev.parent, - max_keys * sizeof(*keymap), + keymap = devm_kcalloc(input_dev->dev.parent, + max_keys, sizeof(*keymap), GFP_KERNEL); if (!keymap) { dev_err(input_dev->dev.parent, diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c index 1588aecafff7..6d304381fc30 100644 --- a/drivers/input/misc/rotary_encoder.c +++ b/drivers/input/misc/rotary_encoder.c @@ -283,8 +283,8 @@ static int rotary_encoder_probe(struct platform_device *pdev) } encoder->irq = - devm_kzalloc(dev, - sizeof(*encoder->irq) * encoder->gpios->ndescs, + devm_kcalloc(dev, + encoder->gpios->ndescs, sizeof(*encoder->irq), GFP_KERNEL); if (!encoder->irq) return -ENOMEM; diff --git a/drivers/input/rmi4/rmi_driver.c b/drivers/input/rmi4/rmi_driver.c index 30a8d816c45c..e51cf50f3b22 100644 --- a/drivers/input/rmi4/rmi_driver.c +++ b/drivers/input/rmi4/rmi_driver.c @@ -636,9 +636,10 @@ int rmi_read_register_desc(struct rmi_device *d, u16 addr, rdesc->num_registers = bitmap_weight(rdesc->presense_map, RMI_REG_DESC_PRESENSE_BITS); - rdesc->registers = devm_kzalloc(&d->dev, rdesc->num_registers * - sizeof(struct rmi_register_desc_item), - GFP_KERNEL); + rdesc->registers = devm_kcalloc(&d->dev, + rdesc->num_registers, + sizeof(struct rmi_register_desc_item), + GFP_KERNEL); if (!rdesc->registers) return -ENOMEM; @@ -1057,7 +1058,7 @@ int rmi_probe_interrupts(struct rmi_driver_data *data) data->num_of_irq_regs = (data->irq_count + 7) / 8; size = BITS_TO_LONGS(data->irq_count) * sizeof(unsigned long); - data->irq_memory = devm_kzalloc(dev, size * 4, GFP_KERNEL); + data->irq_memory = devm_kcalloc(dev, size, 4, GFP_KERNEL); if (!data->irq_memory) { dev_err(dev, "Failed to allocate memory for irq masks.\n"); return -ENOMEM; diff --git a/drivers/input/rmi4/rmi_f11.c b/drivers/input/rmi4/rmi_f11.c index e8c3e5d1ea22..77a4a1b2dd4f 100644 --- a/drivers/input/rmi4/rmi_f11.c +++ b/drivers/input/rmi4/rmi_f11.c @@ -1190,14 +1190,15 @@ static int rmi_f11_initialize(struct rmi_function *fn) f11->sensor.attn_size += f11->sensor.nbr_fingers * 2; /* allocate the in-kernel tracking buffers */ - sensor->tracking_pos = devm_kzalloc(&fn->dev, - sizeof(struct input_mt_pos) * sensor->nbr_fingers, + sensor->tracking_pos = devm_kcalloc(&fn->dev, + sensor->nbr_fingers, sizeof(struct input_mt_pos), + GFP_KERNEL); + sensor->tracking_slots = devm_kcalloc(&fn->dev, + sensor->nbr_fingers, sizeof(int), GFP_KERNEL); + sensor->objs = devm_kcalloc(&fn->dev, + sensor->nbr_fingers, + sizeof(struct rmi_2d_sensor_abs_object), GFP_KERNEL); - sensor->tracking_slots = devm_kzalloc(&fn->dev, - sizeof(int) * sensor->nbr_fingers, GFP_KERNEL); - sensor->objs = devm_kzalloc(&fn->dev, - sizeof(struct rmi_2d_sensor_abs_object) - * sensor->nbr_fingers, GFP_KERNEL); if (!sensor->tracking_pos || !sensor->tracking_slots || !sensor->objs) return -ENOMEM; diff --git a/drivers/input/rmi4/rmi_f12.c b/drivers/input/rmi4/rmi_f12.c index 99dd2f512058..10847408e0f9 100644 --- a/drivers/input/rmi4/rmi_f12.c +++ b/drivers/input/rmi4/rmi_f12.c @@ -526,14 +526,15 @@ static int rmi_f12_probe(struct rmi_function *fn) } /* allocate the in-kernel tracking buffers */ - sensor->tracking_pos = devm_kzalloc(&fn->dev, - sizeof(struct input_mt_pos) * sensor->nbr_fingers, + sensor->tracking_pos = devm_kcalloc(&fn->dev, + sensor->nbr_fingers, sizeof(struct input_mt_pos), + GFP_KERNEL); + sensor->tracking_slots = devm_kcalloc(&fn->dev, + sensor->nbr_fingers, sizeof(int), GFP_KERNEL); + sensor->objs = devm_kcalloc(&fn->dev, + sensor->nbr_fingers, + sizeof(struct rmi_2d_sensor_abs_object), GFP_KERNEL); - sensor->tracking_slots = devm_kzalloc(&fn->dev, - sizeof(int) * sensor->nbr_fingers, GFP_KERNEL); - sensor->objs = devm_kzalloc(&fn->dev, - sizeof(struct rmi_2d_sensor_abs_object) - * sensor->nbr_fingers, GFP_KERNEL); if (!sensor->tracking_pos || !sensor->tracking_slots || !sensor->objs) return -ENOMEM; diff --git a/drivers/input/rmi4/rmi_f54.c b/drivers/input/rmi4/rmi_f54.c index 7f1959517ec0..de036cad7274 100644 --- a/drivers/input/rmi4/rmi_f54.c +++ b/drivers/input/rmi4/rmi_f54.c @@ -685,7 +685,7 @@ static int rmi_f54_probe(struct rmi_function *fn) rx = f54->num_rx_electrodes; tx = f54->num_tx_electrodes; f54->report_data = devm_kzalloc(&fn->dev, - sizeof(u16) * tx * rx, + array3_size(tx, rx, sizeof(u16)), GFP_KERNEL); if (f54->report_data == NULL) return -ENOMEM; diff --git a/drivers/input/rmi4/rmi_spi.c b/drivers/input/rmi4/rmi_spi.c index d0c3d275bf9f..9623395d9415 100644 --- a/drivers/input/rmi4/rmi_spi.c +++ b/drivers/input/rmi4/rmi_spi.c @@ -69,7 +69,7 @@ static int rmi_spi_manage_pools(struct rmi_spi_xport *rmi_spi, int len) buf_size = RMI_SPI_XFER_SIZE_LIMIT; tmp = rmi_spi->rx_buf; - buf = devm_kzalloc(&spi->dev, buf_size * 2, + buf = devm_kcalloc(&spi->dev, buf_size, 2, GFP_KERNEL | GFP_DMA); if (!buf) return -ENOMEM; @@ -96,9 +96,10 @@ static int rmi_spi_manage_pools(struct rmi_spi_xport *rmi_spi, int len) * per byte delays. */ tmp = rmi_spi->rx_xfers; - xfer_buf = devm_kzalloc(&spi->dev, - (rmi_spi->rx_xfer_count + rmi_spi->tx_xfer_count) - * sizeof(struct spi_transfer), GFP_KERNEL); + xfer_buf = devm_kcalloc(&spi->dev, + rmi_spi->rx_xfer_count + rmi_spi->tx_xfer_count, + sizeof(struct spi_transfer), + GFP_KERNEL); if (!xfer_buf) return -ENOMEM; diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 77d67eaca378..6f10c8b365b3 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -4584,8 +4584,8 @@ static int arm_smmu_init_clocks(struct arm_smmu_power_resources *pwr) return 0; } - pwr->clocks = devm_kzalloc( - dev, sizeof(*pwr->clocks) * pwr->num_clocks, + pwr->clocks = devm_kcalloc( + dev, pwr->num_clocks, sizeof(*pwr->clocks), GFP_KERNEL); if (!pwr->clocks) @@ -4630,8 +4630,8 @@ static int arm_smmu_init_regulators(struct arm_smmu_power_resources *pwr) return 0; } - pwr->gdscs = devm_kzalloc( - dev, sizeof(*pwr->gdscs) * pwr->num_gdscs, GFP_KERNEL); + pwr->gdscs = devm_kcalloc( + dev, pwr->num_gdscs, sizeof(*pwr->gdscs), GFP_KERNEL); if (!pwr->gdscs) return -ENOMEM; @@ -5141,7 +5141,7 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev) return -ENODEV; } - smmu->irqs = devm_kzalloc(dev, sizeof(*smmu->irqs) * num_irqs, + smmu->irqs = devm_kcalloc(dev, num_irqs, sizeof(*smmu->irqs), GFP_KERNEL); if (!smmu->irqs) { dev_err(dev, "failed to allocate %d irqs\n", num_irqs); @@ -5933,7 +5933,7 @@ static int qsmmuv500_read_actlr_tbl(struct arm_smmu_device *smmu) if (len < 0) return 0; - actlrs = devm_kzalloc(dev, sizeof(*actlrs) * len, GFP_KERNEL); + actlrs = devm_kcalloc(dev, len, sizeof(*actlrs), GFP_KERNEL); if (!actlrs) return -ENOMEM; @@ -6632,7 +6632,7 @@ static int qsmmuv500_tbu_probe(struct platform_device *pdev) while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, num_irqs))) num_irqs++; - tbu->irqs = devm_kzalloc(dev, sizeof(*tbu->irqs) * num_irqs, + tbu->irqs = devm_kcalloc(dev, num_irqs, sizeof(*tbu->irqs), GFP_KERNEL); if (!tbu->irqs) return -ENOMEM; diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c index 9d991c2d8767..3300562dfa70 100644 --- a/drivers/iommu/rockchip-iommu.c +++ b/drivers/iommu/rockchip-iommu.c @@ -1148,7 +1148,7 @@ static int rk_iommu_probe(struct platform_device *pdev) iommu->dev = dev; iommu->num_mmu = 0; - iommu->bases = devm_kzalloc(dev, sizeof(*iommu->bases) * num_res, + iommu->bases = devm_kcalloc(dev, num_res, sizeof(*iommu->bases), GFP_KERNEL); if (!iommu->bases) return -ENOMEM; diff --git a/drivers/irqchip/irq-imgpdc.c b/drivers/irqchip/irq-imgpdc.c index 1f59998e03f8..b4a84ba16b39 100644 --- a/drivers/irqchip/irq-imgpdc.c +++ b/drivers/irqchip/irq-imgpdc.c @@ -354,7 +354,7 @@ static int pdc_intc_probe(struct platform_device *pdev) priv->nr_syswakes = val; /* Get peripheral IRQ numbers */ - priv->perip_irqs = devm_kzalloc(&pdev->dev, 4 * priv->nr_perips, + priv->perip_irqs = devm_kcalloc(&pdev->dev, 4, priv->nr_perips, GFP_KERNEL); if (!priv->perip_irqs) { dev_err(&pdev->dev, "cannot allocate perip IRQ list\n"); diff --git a/drivers/irqchip/irq-mvebu-gicp.c b/drivers/irqchip/irq-mvebu-gicp.c index 17a4a7b6cdbb..cb3e6ddb075b 100644 --- a/drivers/irqchip/irq-mvebu-gicp.c +++ b/drivers/irqchip/irq-mvebu-gicp.c @@ -207,8 +207,8 @@ static int mvebu_gicp_probe(struct platform_device *pdev) gicp->spi_ranges_cnt = ret / 2; gicp->spi_ranges = - devm_kzalloc(&pdev->dev, - gicp->spi_ranges_cnt * + devm_kcalloc(&pdev->dev, + gicp->spi_ranges_cnt, sizeof(struct mvebu_gicp_spi_range), GFP_KERNEL); if (!gicp->spi_ranges) @@ -226,8 +226,8 @@ static int mvebu_gicp_probe(struct platform_device *pdev) gicp->spi_cnt += gicp->spi_ranges[i].count; } - gicp->spi_bitmap = devm_kzalloc(&pdev->dev, - BITS_TO_LONGS(gicp->spi_cnt) * sizeof(long), + gicp->spi_bitmap = devm_kcalloc(&pdev->dev, + BITS_TO_LONGS(gicp->spi_cnt), sizeof(long), GFP_KERNEL); if (!gicp->spi_bitmap) return -ENOMEM; diff --git a/drivers/leds/leds-adp5520.c b/drivers/leds/leds-adp5520.c index 853b2d3bdb17..7ecf080f73ad 100644 --- a/drivers/leds/leds-adp5520.c +++ b/drivers/leds/leds-adp5520.c @@ -108,7 +108,7 @@ static int adp5520_led_probe(struct platform_device *pdev) return -EFAULT; } - led = devm_kzalloc(&pdev->dev, sizeof(*led) * pdata->num_leds, + led = devm_kcalloc(&pdev->dev, pdata->num_leds, sizeof(*led), GFP_KERNEL); if (!led) return -ENOMEM; diff --git a/drivers/leds/leds-da9052.c b/drivers/leds/leds-da9052.c index f8c7d82c2652..31d4c94e6fd8 100644 --- a/drivers/leds/leds-da9052.c +++ b/drivers/leds/leds-da9052.c @@ -113,8 +113,8 @@ static int da9052_led_probe(struct platform_device *pdev) goto err; } - led = devm_kzalloc(&pdev->dev, - sizeof(struct da9052_led) * pled->num_leds, + led = devm_kcalloc(&pdev->dev, + pled->num_leds, sizeof(struct da9052_led), GFP_KERNEL); if (!led) { error = -ENOMEM; diff --git a/drivers/leds/leds-lp5521.c b/drivers/leds/leds-lp5521.c index 55c0517fbe03..99689b51a73d 100644 --- a/drivers/leds/leds-lp5521.c +++ b/drivers/leds/leds-lp5521.c @@ -533,8 +533,8 @@ static int lp5521_probe(struct i2c_client *client, if (!chip) return -ENOMEM; - led = devm_kzalloc(&client->dev, - sizeof(*led) * pdata->num_channels, GFP_KERNEL); + led = devm_kcalloc(&client->dev, + pdata->num_channels, sizeof(*led), GFP_KERNEL); if (!led) return -ENOMEM; diff --git a/drivers/leds/leds-lp5523.c b/drivers/leds/leds-lp5523.c index 13838d72e297..5074a1b79563 100644 --- a/drivers/leds/leds-lp5523.c +++ b/drivers/leds/leds-lp5523.c @@ -900,8 +900,8 @@ static int lp5523_probe(struct i2c_client *client, if (!chip) return -ENOMEM; - led = devm_kzalloc(&client->dev, - sizeof(*led) * pdata->num_channels, GFP_KERNEL); + led = devm_kcalloc(&client->dev, + pdata->num_channels, sizeof(*led), GFP_KERNEL); if (!led) return -ENOMEM; diff --git a/drivers/leds/leds-lp5562.c b/drivers/leds/leds-lp5562.c index 9d9b673c873c..18edc8bdc9f7 100644 --- a/drivers/leds/leds-lp5562.c +++ b/drivers/leds/leds-lp5562.c @@ -538,8 +538,8 @@ static int lp5562_probe(struct i2c_client *client, if (!chip) return -ENOMEM; - led = devm_kzalloc(&client->dev, - sizeof(*led) * pdata->num_channels, GFP_KERNEL); + led = devm_kcalloc(&client->dev, + pdata->num_channels, sizeof(*led), GFP_KERNEL); if (!led) return -ENOMEM; diff --git a/drivers/leds/leds-lp55xx-common.c b/drivers/leds/leds-lp55xx-common.c index e2655953667c..723f2f17497a 100644 --- a/drivers/leds/leds-lp55xx-common.c +++ b/drivers/leds/leds-lp55xx-common.c @@ -560,7 +560,7 @@ struct lp55xx_platform_data *lp55xx_of_populate_pdata(struct device *dev, return ERR_PTR(-EINVAL); } - cfg = devm_kzalloc(dev, sizeof(*cfg) * num_channels, GFP_KERNEL); + cfg = devm_kcalloc(dev, num_channels, sizeof(*cfg), GFP_KERNEL); if (!cfg) return ERR_PTR(-ENOMEM); diff --git a/drivers/leds/leds-lp8501.c b/drivers/leds/leds-lp8501.c index 3adb113cf02e..4c800b5989a9 100644 --- a/drivers/leds/leds-lp8501.c +++ b/drivers/leds/leds-lp8501.c @@ -327,8 +327,8 @@ static int lp8501_probe(struct i2c_client *client, if (!chip) return -ENOMEM; - led = devm_kzalloc(&client->dev, - sizeof(*led) * pdata->num_channels, GFP_KERNEL); + led = devm_kcalloc(&client->dev, + pdata->num_channels, sizeof(*led), GFP_KERNEL); if (!led) return -ENOMEM; diff --git a/drivers/leds/leds-lt3593.c b/drivers/leds/leds-lt3593.c index a7ff510cbdd0..5ec730a31b65 100644 --- a/drivers/leds/leds-lt3593.c +++ b/drivers/leds/leds-lt3593.c @@ -128,8 +128,8 @@ static int lt3593_led_probe(struct platform_device *pdev) if (!pdata) return -EBUSY; - leds_data = devm_kzalloc(&pdev->dev, - sizeof(struct lt3593_led_data) * pdata->num_leds, + leds_data = devm_kcalloc(&pdev->dev, + pdata->num_leds, sizeof(struct lt3593_led_data), GFP_KERNEL); if (!leds_data) return -ENOMEM; diff --git a/drivers/leds/leds-mc13783.c b/drivers/leds/leds-mc13783.c index 2421cf104991..47ad7de9553c 100644 --- a/drivers/leds/leds-mc13783.c +++ b/drivers/leds/leds-mc13783.c @@ -136,7 +136,7 @@ static struct mc13xxx_leds_platform_data __init *mc13xxx_led_probe_dt( pdata->num_leds = of_get_child_count(parent); - pdata->led = devm_kzalloc(dev, pdata->num_leds * sizeof(*pdata->led), + pdata->led = devm_kcalloc(dev, pdata->num_leds, sizeof(*pdata->led), GFP_KERNEL); if (!pdata->led) { ret = -ENOMEM; @@ -210,7 +210,7 @@ static int __init mc13xxx_led_probe(struct platform_device *pdev) return -EINVAL; } - leds->led = devm_kzalloc(dev, leds->num_leds * sizeof(*leds->led), + leds->led = devm_kcalloc(dev, leds->num_leds, sizeof(*leds->led), GFP_KERNEL); if (!leds->led) return -ENOMEM; diff --git a/drivers/leds/leds-mlxcpld.c b/drivers/leds/leds-mlxcpld.c index 281482e1d50f..f4721f8065f0 100644 --- a/drivers/leds/leds-mlxcpld.c +++ b/drivers/leds/leds-mlxcpld.c @@ -329,8 +329,10 @@ static int mlxcpld_led_config(struct device *dev, int i; int err; - cpld->pled = devm_kzalloc(dev, sizeof(struct mlxcpld_led_priv) * - cpld->num_led_instances, GFP_KERNEL); + cpld->pled = devm_kcalloc(dev, + cpld->num_led_instances, + sizeof(struct mlxcpld_led_priv), + GFP_KERNEL); if (!cpld->pled) return -ENOMEM; diff --git a/drivers/leds/leds-netxbig.c b/drivers/leds/leds-netxbig.c index f48b1aed9b4e..62fa0de526ee 100644 --- a/drivers/leds/leds-netxbig.c +++ b/drivers/leds/leds-netxbig.c @@ -335,7 +335,7 @@ static int gpio_ext_get_of_pdata(struct device *dev, struct device_node *np, return ret; } num_addr = ret; - addr = devm_kzalloc(dev, num_addr * sizeof(*addr), GFP_KERNEL); + addr = devm_kcalloc(dev, num_addr, sizeof(*addr), GFP_KERNEL); if (!addr) return -ENOMEM; @@ -355,7 +355,7 @@ static int gpio_ext_get_of_pdata(struct device *dev, struct device_node *np, return ret; } num_data = ret; - data = devm_kzalloc(dev, num_data * sizeof(*data), GFP_KERNEL); + data = devm_kcalloc(dev, num_data, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; @@ -415,7 +415,7 @@ static int netxbig_leds_get_of_pdata(struct device *dev, if (ret % 3) return -EINVAL; num_timers = ret / 3; - timers = devm_kzalloc(dev, num_timers * sizeof(*timers), + timers = devm_kcalloc(dev, num_timers, sizeof(*timers), GFP_KERNEL); if (!timers) return -ENOMEM; @@ -444,7 +444,7 @@ static int netxbig_leds_get_of_pdata(struct device *dev, return -ENODEV; } - leds = devm_kzalloc(dev, num_leds * sizeof(*leds), GFP_KERNEL); + leds = devm_kcalloc(dev, num_leds, sizeof(*leds), GFP_KERNEL); if (!leds) return -ENOMEM; @@ -470,8 +470,8 @@ static int netxbig_leds_get_of_pdata(struct device *dev, goto err_node_put; mode_val = - devm_kzalloc(dev, - NETXBIG_LED_MODE_NUM * sizeof(*mode_val), + devm_kcalloc(dev, + NETXBIG_LED_MODE_NUM, sizeof(*mode_val), GFP_KERNEL); if (!mode_val) { ret = -ENOMEM; @@ -560,8 +560,8 @@ static int netxbig_led_probe(struct platform_device *pdev) return ret; } - leds_data = devm_kzalloc(&pdev->dev, - pdata->num_leds * sizeof(*leds_data), + leds_data = devm_kcalloc(&pdev->dev, + pdata->num_leds, sizeof(*leds_data), GFP_KERNEL); if (!leds_data) return -ENOMEM; diff --git a/drivers/leds/leds-ns2.c b/drivers/leds/leds-ns2.c index 506b75b190e7..14fe5cd43232 100644 --- a/drivers/leds/leds-ns2.c +++ b/drivers/leds/leds-ns2.c @@ -264,7 +264,7 @@ ns2_leds_get_of_pdata(struct device *dev, struct ns2_led_platform_data *pdata) if (!num_leds) return -ENODEV; - leds = devm_kzalloc(dev, num_leds * sizeof(struct ns2_led), + leds = devm_kcalloc(dev, num_leds, sizeof(struct ns2_led), GFP_KERNEL); if (!leds) return -ENOMEM; @@ -298,8 +298,9 @@ ns2_leds_get_of_pdata(struct device *dev, struct ns2_led_platform_data *pdata) } num_modes = ret / 3; - modval = devm_kzalloc(dev, - num_modes * sizeof(struct ns2_led_modval), + modval = devm_kcalloc(dev, + num_modes, + sizeof(struct ns2_led_modval), GFP_KERNEL); if (!modval) return -ENOMEM; diff --git a/drivers/leds/leds-pca955x.c b/drivers/leds/leds-pca955x.c index 78183f90820e..f51b356d4426 100644 --- a/drivers/leds/leds-pca955x.c +++ b/drivers/leds/leds-pca955x.c @@ -390,8 +390,8 @@ pca955x_pdata_of_init(struct i2c_client *client, struct pca955x_chipdef *chip) if (!pdata) return ERR_PTR(-ENOMEM); - pdata->leds = devm_kzalloc(&client->dev, - sizeof(struct pca955x_led) * chip->bits, + pdata->leds = devm_kcalloc(&client->dev, + chip->bits, sizeof(struct pca955x_led), GFP_KERNEL); if (!pdata->leds) return ERR_PTR(-ENOMEM); @@ -494,8 +494,8 @@ static int pca955x_probe(struct i2c_client *client, if (!pca955x) return -ENOMEM; - pca955x->leds = devm_kzalloc(&client->dev, - sizeof(*pca955x_led) * chip->bits, GFP_KERNEL); + pca955x->leds = devm_kcalloc(&client->dev, + chip->bits, sizeof(*pca955x_led), GFP_KERNEL); if (!pca955x->leds) return -ENOMEM; diff --git a/drivers/leds/leds-pca963x.c b/drivers/leds/leds-pca963x.c index 88c7313cf869..bbcde13b77f1 100644 --- a/drivers/leds/leds-pca963x.c +++ b/drivers/leds/leds-pca963x.c @@ -302,8 +302,8 @@ pca963x_dt_init(struct i2c_client *client, struct pca963x_chipdef *chip) if (!count || count > chip->n_leds) return ERR_PTR(-ENODEV); - pca963x_leds = devm_kzalloc(&client->dev, - sizeof(struct led_info) * chip->n_leds, GFP_KERNEL); + pca963x_leds = devm_kcalloc(&client->dev, + chip->n_leds, sizeof(struct led_info), GFP_KERNEL); if (!pca963x_leds) return ERR_PTR(-ENOMEM); @@ -409,7 +409,7 @@ static int pca963x_probe(struct i2c_client *client, GFP_KERNEL); if (!pca963x_chip) return -ENOMEM; - pca963x = devm_kzalloc(&client->dev, chip->n_leds * sizeof(*pca963x), + pca963x = devm_kcalloc(&client->dev, chip->n_leds, sizeof(*pca963x), GFP_KERNEL); if (!pca963x) return -ENOMEM; diff --git a/drivers/leds/leds-pca9956b.c b/drivers/leds/leds-pca9956b.c index 0b23f21e1afb..2d0373d2c19e 100644 --- a/drivers/leds/leds-pca9956b.c +++ b/drivers/leds/leds-pca9956b.c @@ -484,8 +484,9 @@ static int pca9956b_probe(struct i2c_client *client, if (!chip) return -ENOMEM; - chip->leds = devm_kzalloc(&client->dev, sizeof(*led)*PCA9956B_LED_NUM, - GFP_KERNEL); + chip->leds = devm_kcalloc(&client->dev, + PCA9956B_LED_NUM, sizeof(*led), + GFP_KERNEL); if (!chip->leds) { devm_kfree(&client->dev, chip); return -ENOMEM; diff --git a/drivers/leds/leds-tca6507.c b/drivers/leds/leds-tca6507.c index 45222a7f4f75..6aae71362d4b 100644 --- a/drivers/leds/leds-tca6507.c +++ b/drivers/leds/leds-tca6507.c @@ -697,8 +697,8 @@ tca6507_led_dt_init(struct i2c_client *client) if (!count || count > NUM_LEDS) return ERR_PTR(-ENODEV); - tca_leds = devm_kzalloc(&client->dev, - sizeof(struct led_info) * NUM_LEDS, GFP_KERNEL); + tca_leds = devm_kcalloc(&client->dev, + NUM_LEDS, sizeof(struct led_info), GFP_KERNEL); if (!tca_leds) return ERR_PTR(-ENOMEM); diff --git a/drivers/mailbox/hi6220-mailbox.c b/drivers/mailbox/hi6220-mailbox.c index 519376d3534c..4fa9803cd204 100644 --- a/drivers/mailbox/hi6220-mailbox.c +++ b/drivers/mailbox/hi6220-mailbox.c @@ -282,13 +282,13 @@ static int hi6220_mbox_probe(struct platform_device *pdev) mbox->dev = dev; mbox->chan_num = MBOX_CHAN_MAX; - mbox->mchan = devm_kzalloc(dev, - mbox->chan_num * sizeof(*mbox->mchan), GFP_KERNEL); + mbox->mchan = devm_kcalloc(dev, + mbox->chan_num, sizeof(*mbox->mchan), GFP_KERNEL); if (!mbox->mchan) return -ENOMEM; - mbox->chan = devm_kzalloc(dev, - mbox->chan_num * sizeof(*mbox->chan), GFP_KERNEL); + mbox->chan = devm_kcalloc(dev, + mbox->chan_num, sizeof(*mbox->chan), GFP_KERNEL); if (!mbox->chan) return -ENOMEM; diff --git a/drivers/mailbox/mailbox-sti.c b/drivers/mailbox/mailbox-sti.c index 41bcd339b68a..779d41262ef0 100644 --- a/drivers/mailbox/mailbox-sti.c +++ b/drivers/mailbox/mailbox-sti.c @@ -442,8 +442,8 @@ static int sti_mbox_probe(struct platform_device *pdev) if (!mbox) return -ENOMEM; - chans = devm_kzalloc(&pdev->dev, - sizeof(*chans) * STI_MBOX_CHAN_MAX, GFP_KERNEL); + chans = devm_kcalloc(&pdev->dev, + STI_MBOX_CHAN_MAX, sizeof(*chans), GFP_KERNEL); if (!chans) return -ENOMEM; diff --git a/drivers/mailbox/msm_qmp.c b/drivers/mailbox/msm_qmp.c index 226d1d7f84ff..9ecae6c3cb00 100644 --- a/drivers/mailbox/msm_qmp.c +++ b/drivers/mailbox/msm_qmp.c @@ -831,7 +831,8 @@ static int qmp_mbox_init(struct device_node *n, struct qmp_device *mdev) mbox->desc = mdev->msgram + desc_of; num_chans = get_mbox_num_chans(n); mbox->rx_disabled = (num_chans > 1) ? true : false; - chans = devm_kzalloc(mdev->dev, sizeof(*chans) * num_chans, GFP_KERNEL); + chans = devm_kcalloc(mdev->dev, num_chans, sizeof(*chans), + GFP_KERNEL); if (!chans) return -ENOMEM; diff --git a/drivers/mailbox/omap-mailbox.c b/drivers/mailbox/omap-mailbox.c index c5e8b9cb170d..b943619a79e9 100644 --- a/drivers/mailbox/omap-mailbox.c +++ b/drivers/mailbox/omap-mailbox.c @@ -729,7 +729,7 @@ static int omap_mbox_probe(struct platform_device *pdev) return -ENODEV; } - finfoblk = devm_kzalloc(&pdev->dev, info_count * sizeof(*finfoblk), + finfoblk = devm_kcalloc(&pdev->dev, info_count, sizeof(*finfoblk), GFP_KERNEL); if (!finfoblk) return -ENOMEM; @@ -773,23 +773,23 @@ static int omap_mbox_probe(struct platform_device *pdev) if (IS_ERR(mdev->mbox_base)) return PTR_ERR(mdev->mbox_base); - mdev->irq_ctx = devm_kzalloc(&pdev->dev, num_users * sizeof(u32), + mdev->irq_ctx = devm_kcalloc(&pdev->dev, num_users, sizeof(u32), GFP_KERNEL); if (!mdev->irq_ctx) return -ENOMEM; /* allocate one extra for marking end of list */ - list = devm_kzalloc(&pdev->dev, (info_count + 1) * sizeof(*list), + list = devm_kcalloc(&pdev->dev, info_count + 1, sizeof(*list), GFP_KERNEL); if (!list) return -ENOMEM; - chnls = devm_kzalloc(&pdev->dev, (info_count + 1) * sizeof(*chnls), + chnls = devm_kcalloc(&pdev->dev, info_count + 1, sizeof(*chnls), GFP_KERNEL); if (!chnls) return -ENOMEM; - mboxblk = devm_kzalloc(&pdev->dev, info_count * sizeof(*mbox), + mboxblk = devm_kcalloc(&pdev->dev, info_count, sizeof(*mbox), GFP_KERNEL); if (!mboxblk) return -ENOMEM; diff --git a/drivers/mailbox/qcom-rpmh-mailbox.c b/drivers/mailbox/qcom-rpmh-mailbox.c index 45d2887aaaa5..a62c296f5f06 100644 --- a/drivers/mailbox/qcom-rpmh-mailbox.c +++ b/drivers/mailbox/qcom-rpmh-mailbox.c @@ -1224,8 +1224,9 @@ static int rsc_drv_probe(struct platform_device *pdev) tcs->tcs_offset = st; st += tcs->num_tcs; - tcs->cmd_addr = devm_kzalloc(&pdev->dev, sizeof(u32) * - tcs->num_tcs * tcs->ncpt, GFP_KERNEL); + tcs->cmd_addr = devm_kzalloc(&pdev->dev, + array3_size(sizeof(u32), tcs->num_tcs, tcs->ncpt), + GFP_KERNEL); if (!tcs->cmd_addr) return -ENOMEM; @@ -1253,7 +1254,7 @@ static int rsc_drv_probe(struct platform_device *pdev) return -ENODEV; } - chans = devm_kzalloc(&pdev->dev, num_chans * sizeof(*chans), + chans = devm_kcalloc(&pdev->dev, num_chans, sizeof(*chans), GFP_KERNEL); if (!chans) return -ENOMEM; diff --git a/drivers/mailbox/ti-msgmgr.c b/drivers/mailbox/ti-msgmgr.c index 54b9e4cb4cfa..ae050f79a27b 100644 --- a/drivers/mailbox/ti-msgmgr.c +++ b/drivers/mailbox/ti-msgmgr.c @@ -576,12 +576,12 @@ static int ti_msgmgr_probe(struct platform_device *pdev) } inst->num_valid_queues = queue_count; - qinst = devm_kzalloc(dev, sizeof(*qinst) * queue_count, GFP_KERNEL); + qinst = devm_kcalloc(dev, queue_count, sizeof(*qinst), GFP_KERNEL); if (!qinst) return -ENOMEM; inst->qinsts = qinst; - chans = devm_kzalloc(dev, sizeof(*chans) * queue_count, GFP_KERNEL); + chans = devm_kcalloc(dev, queue_count, sizeof(*chans), GFP_KERNEL); if (!chans) return -ENOMEM; inst->chans = chans; diff --git a/drivers/media/i2c/s5k5baf.c b/drivers/media/i2c/s5k5baf.c index ff46d2c96cea..5007c9659342 100644 --- a/drivers/media/i2c/s5k5baf.c +++ b/drivers/media/i2c/s5k5baf.c @@ -373,7 +373,7 @@ static int s5k5baf_fw_parse(struct device *dev, struct s5k5baf_fw **fw, data += S5K5BAG_FW_TAG_LEN; count -= S5K5BAG_FW_TAG_LEN; - d = devm_kzalloc(dev, count * sizeof(u16), GFP_KERNEL); + d = devm_kcalloc(dev, count, sizeof(u16), GFP_KERNEL); if (!d) return -ENOMEM; diff --git a/drivers/media/platform/am437x/am437x-vpfe.c b/drivers/media/platform/am437x/am437x-vpfe.c index e92c5b56be42..643a728e2257 100644 --- a/drivers/media/platform/am437x/am437x-vpfe.c +++ b/drivers/media/platform/am437x/am437x-vpfe.c @@ -2585,8 +2585,10 @@ static int vpfe_probe(struct platform_device *pdev) pm_runtime_put_sync(&pdev->dev); - vpfe->sd = devm_kzalloc(&pdev->dev, sizeof(struct v4l2_subdev *) * - ARRAY_SIZE(vpfe->cfg->asd), GFP_KERNEL); + vpfe->sd = devm_kcalloc(&pdev->dev, + ARRAY_SIZE(vpfe->cfg->asd), + sizeof(struct v4l2_subdev *), + GFP_KERNEL); if (!vpfe->sd) { ret = -ENOMEM; goto probe_out_v4l2_unregister; diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c index dc8fc2120b63..ace58725c087 100644 --- a/drivers/media/platform/davinci/vpif_capture.c +++ b/drivers/media/platform/davinci/vpif_capture.c @@ -1523,8 +1523,10 @@ vpif_capture_get_pdata(struct platform_device *pdev) if (!pdata) return NULL; pdata->subdev_info = - devm_kzalloc(&pdev->dev, sizeof(*pdata->subdev_info) * - VPIF_CAPTURE_NUM_CHANNELS, GFP_KERNEL); + devm_kcalloc(&pdev->dev, + VPIF_CAPTURE_NUM_CHANNELS, + sizeof(*pdata->subdev_info), + GFP_KERNEL); if (!pdata->subdev_info) return NULL; @@ -1541,9 +1543,9 @@ vpif_capture_get_pdata(struct platform_device *pdev) sdinfo = &pdata->subdev_info[i]; chan = &pdata->chan_config[i]; - chan->inputs = devm_kzalloc(&pdev->dev, - sizeof(*chan->inputs) * + chan->inputs = devm_kcalloc(&pdev->dev, VPIF_CAPTURE_NUM_CHANNELS, + sizeof(*chan->inputs), GFP_KERNEL); if (!chan->inputs) return NULL; diff --git a/drivers/media/platform/msm/ais/cam_smmu/cam_smmu_api.c b/drivers/media/platform/msm/ais/cam_smmu/cam_smmu_api.c index e00b1f4ec0a7..1bc5a8ec640e 100644 --- a/drivers/media/platform/msm/ais/cam_smmu/cam_smmu_api.c +++ b/drivers/media/platform/msm/ais/cam_smmu/cam_smmu_api.c @@ -3312,8 +3312,8 @@ static int cam_alloc_smmu_context_banks(struct device *dev) } /* allocate memory for the context banks */ - iommu_cb_set.cb_info = devm_kzalloc(dev, - iommu_cb_set.cb_num * sizeof(struct cam_context_bank_info), + iommu_cb_set.cb_info = devm_kcalloc(dev, + iommu_cb_set.cb_num, sizeof(struct cam_context_bank_info), GFP_KERNEL); if (!iommu_cb_set.cb_info) { diff --git a/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.c b/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.c index 6964f641188a..5dabde4184d9 100644 --- a/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.c +++ b/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.c @@ -3315,8 +3315,8 @@ static int cam_alloc_smmu_context_banks(struct device *dev) } /* allocate memory for the context banks */ - iommu_cb_set.cb_info = devm_kzalloc(dev, - iommu_cb_set.cb_num * sizeof(struct cam_context_bank_info), + iommu_cb_set.cb_info = devm_kcalloc(dev, + iommu_cb_set.cb_num, sizeof(struct cam_context_bank_info), GFP_KERNEL); if (!iommu_cb_set.cb_info) { diff --git a/drivers/media/platform/msm/camera_v2/common/cam_hw_ops.c b/drivers/media/platform/msm/camera_v2/common/cam_hw_ops.c index a3b41d02963f..4ceb38eb3eaf 100644 --- a/drivers/media/platform/msm/camera_v2/common/cam_hw_ops.c +++ b/drivers/media/platform/msm/camera_v2/common/cam_hw_ops.c @@ -94,8 +94,8 @@ int cam_ahb_clk_init(struct platform_device *pdev) CDBG("number of bus vectors: %d\n", data.cnt); - data.vectors = devm_kzalloc(&pdev->dev, - sizeof(struct cam_bus_vector) * cnt, + data.vectors = devm_kcalloc(&pdev->dev, + cnt, sizeof(struct cam_bus_vector), GFP_KERNEL); if (!data.vectors) return -ENOMEM; @@ -111,16 +111,16 @@ int cam_ahb_clk_init(struct platform_device *pdev) } } - data.paths = devm_kzalloc(&pdev->dev, - sizeof(struct msm_bus_vectors) * cnt, + data.paths = devm_kcalloc(&pdev->dev, + cnt, sizeof(struct msm_bus_vectors), GFP_KERNEL); if (!data.paths) { rc = -ENOMEM; goto err1; } - data.usecases = devm_kzalloc(&pdev->dev, - sizeof(struct msm_bus_paths) * cnt, + data.usecases = devm_kcalloc(&pdev->dev, + cnt, sizeof(struct msm_bus_paths), GFP_KERNEL); if (!data.usecases) { rc = -ENOMEM; @@ -135,8 +135,8 @@ int cam_ahb_clk_init(struct platform_device *pdev) goto err3; } - data.votes = devm_kzalloc(&pdev->dev, sizeof(u32) * cnt, - GFP_KERNEL); + data.votes = devm_kcalloc(&pdev->dev, cnt, sizeof(u32), + GFP_KERNEL); if (!data.votes) { rc = -ENOMEM; goto err4; diff --git a/drivers/media/platform/msm/camera_v2/common/cam_smmu_api.c b/drivers/media/platform/msm/camera_v2/common/cam_smmu_api.c index 8ae6f4d35d68..6cd1ec986668 100644 --- a/drivers/media/platform/msm/camera_v2/common/cam_smmu_api.c +++ b/drivers/media/platform/msm/camera_v2/common/cam_smmu_api.c @@ -2151,8 +2151,8 @@ static int cam_alloc_smmu_context_banks(struct device *dev) } /* allocate memory for the context banks */ - iommu_cb_set.cb_info = devm_kzalloc(dev, - iommu_cb_set.cb_num * sizeof(struct cam_context_bank_info), + iommu_cb_set.cb_info = devm_kcalloc(dev, + iommu_cb_set.cb_num, sizeof(struct cam_context_bank_info), GFP_KERNEL); if (!iommu_cb_set.cb_info) { diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c index e3ab6643c313..087ef77e0439 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c @@ -2294,8 +2294,8 @@ static int sde_rotator_open_session(struct sde_rot_mgr *mgr, if (!perf) return -ENOMEM; - perf->work_distribution = devm_kzalloc(&mgr->pdev->dev, - sizeof(u32) * mgr->queue_count, GFP_KERNEL); + perf->work_distribution = devm_kcalloc(&mgr->pdev->dev, + mgr->queue_count, sizeof(u32), GFP_KERNEL); if (!perf->work_distribution) { ret = -ENOMEM; goto alloc_err; @@ -2865,8 +2865,9 @@ static int sde_rotator_get_dt_vreg_data(struct device *dev, return 0; } mp->num_vreg = dt_vreg_total; - mp->vreg_config = devm_kzalloc(dev, sizeof(struct sde_vreg) * - dt_vreg_total, GFP_KERNEL); + mp->vreg_config = devm_kcalloc(dev, + dt_vreg_total, sizeof(struct sde_vreg), + GFP_KERNEL); if (!mp->vreg_config) return -ENOMEM; @@ -2989,8 +2990,8 @@ static int sde_rotator_parse_dt_clk(struct platform_device *pdev, } mgr->num_rot_clk = SDE_ROTATOR_CLK_MAX; - mgr->rot_clk = devm_kzalloc(&pdev->dev, - sizeof(struct sde_rot_clk) * mgr->num_rot_clk, + mgr->rot_clk = devm_kcalloc(&pdev->dev, + mgr->num_rot_clk, sizeof(struct sde_rot_clk), GFP_KERNEL); if (!mgr->rot_clk) { rc = -ENOMEM; diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_smmu.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_smmu.c index 4658f2918898..4a169ae589f5 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_smmu.c +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_smmu.c @@ -117,8 +117,8 @@ static int sde_smmu_util_parse_dt_clock(struct platform_device *pdev, } mp->num_clk = num_clk; - mp->clk_config = devm_kzalloc(&pdev->dev, - sizeof(struct sde_clk) * mp->num_clk, GFP_KERNEL); + mp->clk_config = devm_kcalloc(&pdev->dev, + mp->num_clk, sizeof(struct sde_clk), GFP_KERNEL); if (num_clk && !mp->clk_config) { rc = -ENOMEM; mp->num_clk = 0; diff --git a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c index cf2e849b4b98..8ca1edfdc27b 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c @@ -169,8 +169,10 @@ static int msm_vidc_load_reg_table(struct msm_vidc_platform_resources *res) return rc; } - reg_set->reg_tbl = devm_kzalloc(&pdev->dev, reg_set->count * - sizeof(*(reg_set->reg_tbl)), GFP_KERNEL); + reg_set->reg_tbl = devm_kcalloc(&pdev->dev, + reg_set->count, + sizeof(*(reg_set->reg_tbl)), + GFP_KERNEL); if (!reg_set->reg_tbl) { dprintk(VIDC_ERR, "%s Failed to alloc register table\n", __func__); @@ -218,8 +220,9 @@ static int msm_vidc_load_qdss_table(struct msm_vidc_platform_resources *res) return rc; } - qdss_addr_set->addr_tbl = devm_kzalloc(&pdev->dev, - qdss_addr_set->count * sizeof(*qdss_addr_set->addr_tbl), + qdss_addr_set->addr_tbl = devm_kcalloc(&pdev->dev, + qdss_addr_set->count, + sizeof(*qdss_addr_set->addr_tbl), GFP_KERNEL); if (!qdss_addr_set->addr_tbl) { dprintk(VIDC_ERR, "%s Failed to alloc register table\n", @@ -259,8 +262,8 @@ static int msm_vidc_load_subcache_info(struct msm_vidc_platform_resources *res) goto err_load_subcache_table_fail; } - subcaches->subcache_tbl = devm_kzalloc(&pdev->dev, - sizeof(*subcaches->subcache_tbl) * num_subcaches, GFP_KERNEL); + subcaches->subcache_tbl = devm_kcalloc(&pdev->dev, + num_subcaches, sizeof(*subcaches->subcache_tbl), GFP_KERNEL); if (!subcaches->subcache_tbl) { dprintk(VIDC_ERR, "Failed to allocate memory for subcache tbl\n"); @@ -326,7 +329,7 @@ int msm_vidc_load_u32_table(struct platform_device *pdev, } num_elemts /= struct_size / sizeof(u32); - ptbl = devm_kzalloc(&pdev->dev, num_elemts * struct_size, GFP_KERNEL); + ptbl = devm_kcalloc(&pdev->dev, struct_size, num_elemts, GFP_KERNEL); if (!ptbl) { dprintk(VIDC_ERR, "Failed to alloc table %s\n", table_name); return -ENOMEM; @@ -498,8 +501,8 @@ static int msm_vidc_load_buffer_usage_table( return 0; } - buffer_usage_set->buffer_usage_tbl = devm_kzalloc(&pdev->dev, - buffer_usage_set->count * + buffer_usage_set->buffer_usage_tbl = devm_kcalloc(&pdev->dev, + buffer_usage_set->count, sizeof(*buffer_usage_set->buffer_usage_tbl), GFP_KERNEL); if (!buffer_usage_set->buffer_usage_tbl) { @@ -554,9 +557,9 @@ static int msm_vidc_load_regulator_table( reg_count++; } - regulators->regulator_tbl = devm_kzalloc(&pdev->dev, - sizeof(*regulators->regulator_tbl) * - reg_count, GFP_KERNEL); + regulators->regulator_tbl = devm_kcalloc(&pdev->dev, + reg_count, sizeof(*regulators->regulator_tbl), + GFP_KERNEL); if (!regulators->regulator_tbl) { rc = -ENOMEM; @@ -638,8 +641,9 @@ static int msm_vidc_load_clock_table( goto err_load_clk_table_fail; } - clock_props = devm_kzalloc(&pdev->dev, num_clocks * - sizeof(*clock_props), GFP_KERNEL); + clock_props = devm_kcalloc(&pdev->dev, + num_clocks, sizeof(*clock_props), + GFP_KERNEL); if (!clock_props) { dprintk(VIDC_ERR, "No memory to read clock properties\n"); rc = -ENOMEM; @@ -654,8 +658,10 @@ static int msm_vidc_load_clock_table( goto err_load_clk_prop_fail; } - clocks->clock_tbl = devm_kzalloc(&pdev->dev, sizeof(*clocks->clock_tbl) - * num_clocks, GFP_KERNEL); + clocks->clock_tbl = devm_kcalloc(&pdev->dev, + num_clocks, + sizeof(*clocks->clock_tbl), + GFP_KERNEL); if (!clocks->clock_tbl) { dprintk(VIDC_ERR, "Failed to allocate memory for clock tbl\n"); rc = -ENOMEM; diff --git a/drivers/media/platform/qcom/camss-8x16/camss-csid.c b/drivers/media/platform/qcom/camss-8x16/camss-csid.c index 4882ee25bd75..2bf65805f2c1 100644 --- a/drivers/media/platform/qcom/camss-8x16/camss-csid.c +++ b/drivers/media/platform/qcom/camss-8x16/camss-csid.c @@ -851,7 +851,7 @@ int msm_csid_subdev_init(struct csid_device *csid, while (res->clock[csid->nclocks]) csid->nclocks++; - csid->clock = devm_kzalloc(dev, csid->nclocks * sizeof(*csid->clock), + csid->clock = devm_kcalloc(dev, csid->nclocks, sizeof(*csid->clock), GFP_KERNEL); if (!csid->clock) return -ENOMEM; @@ -874,8 +874,10 @@ int msm_csid_subdev_init(struct csid_device *csid, continue; } - clock->freq = devm_kzalloc(dev, clock->nfreqs * - sizeof(*clock->freq), GFP_KERNEL); + clock->freq = devm_kcalloc(dev, + clock->nfreqs, + sizeof(*clock->freq), + GFP_KERNEL); if (!clock->freq) return -ENOMEM; diff --git a/drivers/media/platform/qcom/camss-8x16/camss-csiphy.c b/drivers/media/platform/qcom/camss-8x16/camss-csiphy.c index 072c6cf053f6..7e61caba6a2d 100644 --- a/drivers/media/platform/qcom/camss-8x16/camss-csiphy.c +++ b/drivers/media/platform/qcom/camss-8x16/camss-csiphy.c @@ -732,8 +732,9 @@ int msm_csiphy_subdev_init(struct csiphy_device *csiphy, while (res->clock[csiphy->nclocks]) csiphy->nclocks++; - csiphy->clock = devm_kzalloc(dev, csiphy->nclocks * - sizeof(*csiphy->clock), GFP_KERNEL); + csiphy->clock = devm_kcalloc(dev, + csiphy->nclocks, sizeof(*csiphy->clock), + GFP_KERNEL); if (!csiphy->clock) return -ENOMEM; @@ -755,8 +756,10 @@ int msm_csiphy_subdev_init(struct csiphy_device *csiphy, continue; } - clock->freq = devm_kzalloc(dev, clock->nfreqs * - sizeof(*clock->freq), GFP_KERNEL); + clock->freq = devm_kcalloc(dev, + clock->nfreqs, + sizeof(*clock->freq), + GFP_KERNEL); if (!clock->freq) return -ENOMEM; diff --git a/drivers/media/platform/qcom/camss-8x16/camss-ispif.c b/drivers/media/platform/qcom/camss-8x16/camss-ispif.c index 24da529397b5..9d1af9353c1d 100644 --- a/drivers/media/platform/qcom/camss-8x16/camss-ispif.c +++ b/drivers/media/platform/qcom/camss-8x16/camss-ispif.c @@ -948,7 +948,8 @@ int msm_ispif_subdev_init(struct ispif_device *ispif, while (res->clock[ispif->nclocks]) ispif->nclocks++; - ispif->clock = devm_kzalloc(dev, ispif->nclocks * sizeof(*ispif->clock), + ispif->clock = devm_kcalloc(dev, + ispif->nclocks, sizeof(*ispif->clock), GFP_KERNEL); if (!ispif->clock) return -ENOMEM; @@ -968,8 +969,10 @@ int msm_ispif_subdev_init(struct ispif_device *ispif, while (res->clock_for_reset[ispif->nclocks_for_reset]) ispif->nclocks_for_reset++; - ispif->clock_for_reset = devm_kzalloc(dev, ispif->nclocks_for_reset * - sizeof(*ispif->clock_for_reset), GFP_KERNEL); + ispif->clock_for_reset = devm_kcalloc(dev, + ispif->nclocks_for_reset, + sizeof(*ispif->clock_for_reset), + GFP_KERNEL); if (!ispif->clock_for_reset) return -ENOMEM; diff --git a/drivers/media/platform/qcom/camss-8x16/camss-vfe.c b/drivers/media/platform/qcom/camss-8x16/camss-vfe.c index 55232a912950..a6329a8a7c4a 100644 --- a/drivers/media/platform/qcom/camss-8x16/camss-vfe.c +++ b/drivers/media/platform/qcom/camss-8x16/camss-vfe.c @@ -2794,7 +2794,7 @@ int msm_vfe_subdev_init(struct vfe_device *vfe, const struct resources *res) while (res->clock[vfe->nclocks]) vfe->nclocks++; - vfe->clock = devm_kzalloc(dev, vfe->nclocks * sizeof(*vfe->clock), + vfe->clock = devm_kcalloc(dev, vfe->nclocks, sizeof(*vfe->clock), GFP_KERNEL); if (!vfe->clock) return -ENOMEM; @@ -2817,8 +2817,10 @@ int msm_vfe_subdev_init(struct vfe_device *vfe, const struct resources *res) continue; } - clock->freq = devm_kzalloc(dev, clock->nfreqs * - sizeof(*clock->freq), GFP_KERNEL); + clock->freq = devm_kcalloc(dev, + clock->nfreqs, + sizeof(*clock->freq), + GFP_KERNEL); if (!clock->freq) return -ENOMEM; diff --git a/drivers/media/platform/qcom/camss-8x16/camss.c b/drivers/media/platform/qcom/camss-8x16/camss.c index a3760b5dd1d1..adcef956cbec 100644 --- a/drivers/media/platform/qcom/camss-8x16/camss.c +++ b/drivers/media/platform/qcom/camss-8x16/camss.c @@ -271,7 +271,8 @@ static int camss_of_parse_endpoint_node(struct device *dev, lncfg->clk.pol = mipi_csi2->lane_polarities[0]; lncfg->num_data = mipi_csi2->num_data_lanes; - lncfg->data = devm_kzalloc(dev, lncfg->num_data * sizeof(*lncfg->data), + lncfg->data = devm_kcalloc(dev, + lncfg->num_data, sizeof(*lncfg->data), GFP_KERNEL); if (!lncfg->data) return -ENOMEM; diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index 54de15095709..51ff3d8f39f3 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c @@ -511,7 +511,8 @@ int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity, entity->source_pad = num_pads - 1; /* Allocate and initialize pads. */ - entity->pads = devm_kzalloc(vsp1->dev, num_pads * sizeof(*entity->pads), + entity->pads = devm_kcalloc(vsp1->dev, + num_pads, sizeof(*entity->pads), GFP_KERNEL); if (entity->pads == NULL) return -ENOMEM; diff --git a/drivers/media/platform/xilinx/xilinx-vipp.c b/drivers/media/platform/xilinx/xilinx-vipp.c index ebfdf334d99c..3bd3d640de59 100644 --- a/drivers/media/platform/xilinx/xilinx-vipp.c +++ b/drivers/media/platform/xilinx/xilinx-vipp.c @@ -535,7 +535,7 @@ static int xvip_graph_init(struct xvip_composite_device *xdev) /* Register the subdevices notifier. */ num_subdevs = xdev->num_subdevs; - subdevs = devm_kzalloc(xdev->dev, sizeof(*subdevs) * num_subdevs, + subdevs = devm_kcalloc(xdev->dev, num_subdevs, sizeof(*subdevs), GFP_KERNEL); if (subdevs == NULL) { ret = -ENOMEM; diff --git a/drivers/media/v4l2-core/v4l2-flash-led-class.c b/drivers/media/v4l2-core/v4l2-flash-led-class.c index 4ceef217de83..215b4804ada2 100644 --- a/drivers/media/v4l2-core/v4l2-flash-led-class.c +++ b/drivers/media/v4l2-core/v4l2-flash-led-class.c @@ -412,9 +412,10 @@ static int v4l2_flash_init_controls(struct v4l2_flash *v4l2_flash, struct v4l2_ctrl_config *ctrl_cfg; int i, ret, num_ctrls = 0; - v4l2_flash->ctrls = devm_kzalloc(v4l2_flash->sd.dev, - sizeof(*v4l2_flash->ctrls) * - (STROBE_SOURCE + 1), GFP_KERNEL); + v4l2_flash->ctrls = devm_kcalloc(v4l2_flash->sd.dev, + STROBE_SOURCE + 1, + sizeof(*v4l2_flash->ctrls), + GFP_KERNEL); if (!v4l2_flash->ctrls) return -ENOMEM; diff --git a/drivers/memory/of_memory.c b/drivers/memory/of_memory.c index 568f05ed961a..2f5ed7366eec 100644 --- a/drivers/memory/of_memory.c +++ b/drivers/memory/of_memory.c @@ -126,8 +126,8 @@ const struct lpddr2_timings *of_get_ddr_timings(struct device_node *np_ddr, arr_sz++; if (arr_sz) - timings = devm_kzalloc(dev, sizeof(*timings) * arr_sz, - GFP_KERNEL); + timings = devm_kcalloc(dev, arr_sz, sizeof(*timings), + GFP_KERNEL); if (!timings) goto default_timings; diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c index 28c3ee38b081..eba2a4488823 100644 --- a/drivers/mfd/ab8500-debugfs.c +++ b/drivers/mfd/ab8500-debugfs.c @@ -2952,18 +2952,18 @@ static int ab8500_debug_probe(struct platform_device *plf) ab8500 = dev_get_drvdata(plf->dev.parent); num_irqs = ab8500->mask_size; - irq_count = devm_kzalloc(&plf->dev, - sizeof(*irq_count)*num_irqs, GFP_KERNEL); + irq_count = devm_kcalloc(&plf->dev, + num_irqs, sizeof(*irq_count), GFP_KERNEL); if (!irq_count) return -ENOMEM; - dev_attr = devm_kzalloc(&plf->dev, - sizeof(*dev_attr)*num_irqs, GFP_KERNEL); + dev_attr = devm_kcalloc(&plf->dev, + num_irqs, sizeof(*dev_attr), GFP_KERNEL); if (!dev_attr) return -ENOMEM; - event_name = devm_kzalloc(&plf->dev, - sizeof(*event_name)*num_irqs, GFP_KERNEL); + event_name = devm_kcalloc(&plf->dev, + num_irqs, sizeof(*event_name), GFP_KERNEL); if (!event_name) return -ENOMEM; diff --git a/drivers/mfd/htc-i2cpld.c b/drivers/mfd/htc-i2cpld.c index 3f9eee5f8fb9..9428326608ed 100644 --- a/drivers/mfd/htc-i2cpld.c +++ b/drivers/mfd/htc-i2cpld.c @@ -477,7 +477,9 @@ static int htcpld_setup_chips(struct platform_device *pdev) /* Setup each chip's output GPIOs */ htcpld->nchips = pdata->num_chip; - htcpld->chip = devm_kzalloc(dev, sizeof(struct htcpld_chip) * htcpld->nchips, + htcpld->chip = devm_kcalloc(dev, + htcpld->nchips, + sizeof(struct htcpld_chip), GFP_KERNEL); if (!htcpld->chip) { dev_warn(dev, "Unable to allocate memory for chips\n"); diff --git a/drivers/mfd/motorola-cpcap.c b/drivers/mfd/motorola-cpcap.c index d2cc1eabac05..8198c9c25a9e 100644 --- a/drivers/mfd/motorola-cpcap.c +++ b/drivers/mfd/motorola-cpcap.c @@ -173,9 +173,7 @@ static int cpcap_init_irq(struct cpcap_ddata *cpcap) int ret; cpcap->irqs = devm_kzalloc(&cpcap->spi->dev, - sizeof(*cpcap->irqs) * - CPCAP_NR_IRQ_REG_BANKS * - cpcap->regmap_conf->val_bits, + array3_size(sizeof(*cpcap->irqs), CPCAP_NR_IRQ_REG_BANKS, cpcap->regmap_conf->val_bits), GFP_KERNEL); if (!cpcap->irqs) return -ENOMEM; diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c index 44a5d66314c6..f40fc8d59f13 100644 --- a/drivers/mfd/omap-usb-tll.c +++ b/drivers/mfd/omap-usb-tll.c @@ -254,7 +254,7 @@ static int usbtll_omap_probe(struct platform_device *pdev) break; } - tll->ch_clk = devm_kzalloc(dev, sizeof(struct clk *) * tll->nch, + tll->ch_clk = devm_kcalloc(dev, tll->nch, sizeof(struct clk *), GFP_KERNEL); if (!tll->ch_clk) { ret = -ENOMEM; diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index 8f993272901d..13315039e0a4 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c @@ -1139,8 +1139,9 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id) } num_slaves = twl_get_num_slaves(); - twl_priv->twl_modules = devm_kzalloc(&client->dev, - sizeof(struct twl_client) * num_slaves, + twl_priv->twl_modules = devm_kcalloc(&client->dev, + num_slaves, + sizeof(struct twl_client), GFP_KERNEL); if (!twl_priv->twl_modules) { status = -ENOMEM; diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c index 3259fb82d3c4..56a4c7c65c44 100644 --- a/drivers/mfd/wm8994-core.c +++ b/drivers/mfd/wm8994-core.c @@ -368,9 +368,10 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq) goto err; } - wm8994->supplies = devm_kzalloc(wm8994->dev, - sizeof(struct regulator_bulk_data) * - wm8994->num_supplies, GFP_KERNEL); + wm8994->supplies = devm_kcalloc(wm8994->dev, + wm8994->num_supplies, + sizeof(struct regulator_bulk_data), + GFP_KERNEL); if (!wm8994->supplies) { ret = -ENOMEM; goto err; diff --git a/drivers/misc/memory_state_time.c b/drivers/misc/memory_state_time.c index ba94dcf09169..ab8d5c11eaed 100644 --- a/drivers/misc/memory_state_time.c +++ b/drivers/misc/memory_state_time.c @@ -301,13 +301,13 @@ static int get_bw_buckets(struct device *dev) return -ENODATA; } - bandwidths = devm_kzalloc(dev, - sizeof(*bandwidths) * num_sources, GFP_KERNEL); + bandwidths = devm_kcalloc(dev, + num_sources, sizeof(*bandwidths), GFP_KERNEL); if (!bandwidths) return -ENOMEM; lenb /= sizeof(*bw_buckets); - bw_buckets = devm_kzalloc(dev, lenb * sizeof(*bw_buckets), - GFP_KERNEL); + bw_buckets = devm_kcalloc(dev, lenb, sizeof(*bw_buckets), + GFP_KERNEL); if (!bw_buckets) { devm_kfree(dev, bandwidths); return -ENOMEM; @@ -342,8 +342,8 @@ static int freq_buckets_init(struct device *dev) } lenf /= sizeof(*freq_buckets); - freq_buckets = devm_kzalloc(dev, lenf * sizeof(*freq_buckets), - GFP_KERNEL); + freq_buckets = devm_kcalloc(dev, lenf, sizeof(*freq_buckets), + GFP_KERNEL); if (!freq_buckets) return -ENOMEM; pr_debug("freqs found len %d\n", lenf); @@ -364,8 +364,9 @@ static int freq_buckets_init(struct device *dev) GFP_KERNEL); if (!freq_entry) return -ENOMEM; - freq_entry->buckets = devm_kzalloc(dev, sizeof(u64)*num_buckets, - GFP_KERNEL); + freq_entry->buckets = devm_kcalloc(dev, + num_buckets, sizeof(u64), + GFP_KERNEL); if (!freq_entry->buckets) { devm_kfree(dev, freq_entry); return -ENOMEM; diff --git a/drivers/misc/sram.c b/drivers/misc/sram.c index b856b7ede260..74b183baf044 100644 --- a/drivers/misc/sram.c +++ b/drivers/misc/sram.c @@ -264,8 +264,8 @@ static int sram_reserve_regions(struct sram_dev *sram, struct resource *res) list_sort(NULL, &reserve_list, sram_reserve_cmp); if (exports) { - sram->partition = devm_kzalloc(sram->dev, - exports * sizeof(*sram->partition), + sram->partition = devm_kcalloc(sram->dev, + exports, sizeof(*sram->partition), GFP_KERNEL); if (!sram->partition) { ret = -ENOMEM; diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index a6bd35e37a31..68e21a9c0ca0 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -1560,7 +1560,7 @@ static int sdhci_msm_dt_get_array(struct device *dev, const char *prop_name, goto out; } - arr = devm_kzalloc(dev, sz * sizeof(*arr), GFP_KERNEL); + arr = devm_kcalloc(dev, sz, sizeof(*arr), GFP_KERNEL); if (!arr) { ret = -ENOMEM; goto out; @@ -1745,8 +1745,10 @@ static int sdhci_msm_dt_parse_gpio_info(struct device *dev, goto out; } pin_data->gpio_data->size = cnt; - pin_data->gpio_data->gpio = devm_kzalloc(dev, cnt * - sizeof(struct sdhci_msm_gpio), GFP_KERNEL); + pin_data->gpio_data->gpio = devm_kcalloc(dev, + cnt, + sizeof(struct sdhci_msm_gpio), + GFP_KERNEL); if (!pin_data->gpio_data->gpio) { ret = -ENOMEM; diff --git a/drivers/mtd/devices/docg3.c b/drivers/mtd/devices/docg3.c index 6552696f2d45..f4a071734685 100644 --- a/drivers/mtd/devices/docg3.c +++ b/drivers/mtd/devices/docg3.c @@ -2076,7 +2076,7 @@ static int __init docg3_probe(struct platform_device *pdev) base = devm_ioremap(dev, ress->start, DOC_IOSPACE_SIZE); ret = -ENOMEM; - cascade = devm_kzalloc(dev, sizeof(*cascade) * DOC_MAX_NBFLOORS, + cascade = devm_kcalloc(dev, DOC_MAX_NBFLOORS, sizeof(*cascade), GFP_KERNEL); if (!cascade) return ret; diff --git a/drivers/mtd/nand/qcom_nandc.c b/drivers/mtd/nand/qcom_nandc.c index 65d1be2c3049..20ad11626f86 100644 --- a/drivers/mtd/nand/qcom_nandc.c +++ b/drivers/mtd/nand/qcom_nandc.c @@ -2414,8 +2414,8 @@ static int qcom_nandc_alloc(struct qcom_nand_controller *nandc) if (!nandc->regs) return -ENOMEM; - nandc->reg_read_buf = devm_kzalloc(nandc->dev, - MAX_REG_RD * sizeof(*nandc->reg_read_buf), + nandc->reg_read_buf = devm_kcalloc(nandc->dev, + MAX_REG_RD, sizeof(*nandc->reg_read_buf), GFP_KERNEL); if (!nandc->reg_read_buf) return -ENOMEM; diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c index f60de68bfabc..87f78b6a5c16 100644 --- a/drivers/mtd/nand/s3c2410.c +++ b/drivers/mtd/nand/s3c2410.c @@ -1041,7 +1041,7 @@ static int s3c24xx_nand_probe_dt(struct platform_device *pdev) if (!pdata->nr_sets) return 0; - sets = devm_kzalloc(&pdev->dev, sizeof(*sets) * pdata->nr_sets, + sets = devm_kcalloc(&pdev->dev, pdata->nr_sets, sizeof(*sets), GFP_KERNEL); if (!sets) return -ENOMEM; diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c index 274d36915110..4479bfc228cd 100644 --- a/drivers/net/dsa/b53/b53_common.c +++ b/drivers/net/dsa/b53/b53_common.c @@ -1825,14 +1825,14 @@ static int b53_switch_init(struct b53_device *dev) dev->num_ports = dev->cpu_port + 1; dev->enabled_ports |= BIT(dev->cpu_port); - dev->ports = devm_kzalloc(dev->dev, - sizeof(struct b53_port) * dev->num_ports, + dev->ports = devm_kcalloc(dev->dev, + dev->num_ports, sizeof(struct b53_port), GFP_KERNEL); if (!dev->ports) return -ENOMEM; - dev->vlans = devm_kzalloc(dev->dev, - sizeof(struct b53_vlan) * dev->num_vlans, + dev->vlans = devm_kcalloc(dev->dev, + dev->num_vlans, sizeof(struct b53_vlan), GFP_KERNEL); if (!dev->vlans) return -ENOMEM; diff --git a/drivers/net/ethernet/amazon/ena/ena_ethtool.c b/drivers/net/ethernet/amazon/ena/ena_ethtool.c index d29e256bf610..53683eb51bbd 100644 --- a/drivers/net/ethernet/amazon/ena/ena_ethtool.c +++ b/drivers/net/ethernet/amazon/ena/ena_ethtool.c @@ -877,8 +877,8 @@ static void ena_dump_stats_ex(struct ena_adapter *adapter, u8 *buf) return; } - strings_buf = devm_kzalloc(&adapter->pdev->dev, - strings_num * ETH_GSTRING_LEN, + strings_buf = devm_kcalloc(&adapter->pdev->dev, + ETH_GSTRING_LEN, strings_num, GFP_ATOMIC); if (!strings_buf) { netif_err(adapter, drv, netdev, @@ -886,8 +886,8 @@ static void ena_dump_stats_ex(struct ena_adapter *adapter, u8 *buf) return; } - data_buf = devm_kzalloc(&adapter->pdev->dev, - strings_num * sizeof(u64), + data_buf = devm_kcalloc(&adapter->pdev->dev, + strings_num, sizeof(u64), GFP_ATOMIC); if (!data_buf) { netif_err(adapter, drv, netdev, diff --git a/drivers/net/ethernet/ethoc.c b/drivers/net/ethernet/ethoc.c index 8bb0db990c8f..c30565134c7b 100644 --- a/drivers/net/ethernet/ethoc.c +++ b/drivers/net/ethernet/ethoc.c @@ -1141,7 +1141,8 @@ static int ethoc_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "ethoc: num_tx: %d num_rx: %d\n", priv->num_tx, priv->num_rx); - priv->vma = devm_kzalloc(&pdev->dev, num_bd*sizeof(void *), GFP_KERNEL); + priv->vma = devm_kcalloc(&pdev->dev, num_bd, sizeof(void *), + GFP_KERNEL); if (!priv->vma) { ret = -ENOMEM; goto free; diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c index 67246d42c3d9..49f318c1c8c3 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c @@ -672,7 +672,7 @@ static struct dpaa_fq *dpaa_fq_alloc(struct device *dev, struct dpaa_fq *dpaa_fq; int i; - dpaa_fq = devm_kzalloc(dev, sizeof(*dpaa_fq) * count, + dpaa_fq = devm_kcalloc(dev, count, sizeof(*dpaa_fq), GFP_KERNEL); if (!dpaa_fq) return NULL; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.c index e9cff8ed5e07..06d22a9c8651 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.c @@ -2554,8 +2554,8 @@ static int hns3_get_ring_config(struct hns3_nic_priv *priv) struct pci_dev *pdev = h->pdev; int i, ret; - priv->ring_data = devm_kzalloc(&pdev->dev, h->kinfo.num_tqps * - sizeof(*priv->ring_data) * 2, + priv->ring_data = devm_kzalloc(&pdev->dev, + array3_size(h->kinfo.num_tqps, sizeof(*priv->ring_data), 2), GFP_KERNEL); if (!priv->ring_data) return -ENOMEM; diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index 3189afcd5888..a592b1e90442 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -2630,8 +2630,9 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data, } data->active_slave = prop; - data->slave_data = devm_kzalloc(&pdev->dev, data->slaves - * sizeof(struct cpsw_slave_data), + data->slave_data = devm_kcalloc(&pdev->dev, + data->slaves, + sizeof(struct cpsw_slave_data), GFP_KERNEL); if (!data->slave_data) return -ENOMEM; @@ -2959,8 +2960,8 @@ static int cpsw_probe(struct platform_device *pdev) memcpy(ndev->dev_addr, priv->mac_addr, ETH_ALEN); - cpsw->slaves = devm_kzalloc(&pdev->dev, - sizeof(struct cpsw_slave) * data->slaves, + cpsw->slaves = devm_kcalloc(&pdev->dev, + data->slaves, sizeof(struct cpsw_slave), GFP_KERNEL); if (!cpsw->slaves) { ret = -ENOMEM; diff --git a/drivers/net/ethernet/ti/netcp_ethss.c b/drivers/net/ethernet/ti/netcp_ethss.c index ff7a71ca0b13..ba14f5dd7e04 100644 --- a/drivers/net/ethernet/ti/netcp_ethss.c +++ b/drivers/net/ethernet/ti/netcp_ethss.c @@ -3173,8 +3173,8 @@ static int set_xgbe_ethss10_priv(struct gbe_priv *gbe_dev, gbe_dev->et_stats = xgbe10_et_stats; gbe_dev->num_et_stats = ARRAY_SIZE(xgbe10_et_stats); - gbe_dev->hw_stats = devm_kzalloc(gbe_dev->dev, - gbe_dev->num_et_stats * sizeof(u64), + gbe_dev->hw_stats = devm_kcalloc(gbe_dev->dev, + gbe_dev->num_et_stats, sizeof(u64), GFP_KERNEL); if (!gbe_dev->hw_stats) { dev_err(gbe_dev->dev, "hw_stats memory allocation failed\n"); @@ -3182,8 +3182,8 @@ static int set_xgbe_ethss10_priv(struct gbe_priv *gbe_dev, } gbe_dev->hw_stats_prev = - devm_kzalloc(gbe_dev->dev, - gbe_dev->num_et_stats * sizeof(u32), + devm_kcalloc(gbe_dev->dev, + gbe_dev->num_et_stats, sizeof(u32), GFP_KERNEL); if (!gbe_dev->hw_stats_prev) { dev_err(gbe_dev->dev, @@ -3293,8 +3293,8 @@ static int set_gbe_ethss14_priv(struct gbe_priv *gbe_dev, gbe_dev->et_stats = gbe13_et_stats; gbe_dev->num_et_stats = ARRAY_SIZE(gbe13_et_stats); - gbe_dev->hw_stats = devm_kzalloc(gbe_dev->dev, - gbe_dev->num_et_stats * sizeof(u64), + gbe_dev->hw_stats = devm_kcalloc(gbe_dev->dev, + gbe_dev->num_et_stats, sizeof(u64), GFP_KERNEL); if (!gbe_dev->hw_stats) { dev_err(gbe_dev->dev, "hw_stats memory allocation failed\n"); @@ -3302,8 +3302,8 @@ static int set_gbe_ethss14_priv(struct gbe_priv *gbe_dev, } gbe_dev->hw_stats_prev = - devm_kzalloc(gbe_dev->dev, - gbe_dev->num_et_stats * sizeof(u32), + devm_kcalloc(gbe_dev->dev, + gbe_dev->num_et_stats, sizeof(u32), GFP_KERNEL); if (!gbe_dev->hw_stats_prev) { dev_err(gbe_dev->dev, @@ -3365,8 +3365,8 @@ static int set_gbenu_ethss_priv(struct gbe_priv *gbe_dev, gbe_dev->num_et_stats = GBENU_ET_STATS_HOST_SIZE + GBENU_ET_STATS_PORT_SIZE; - gbe_dev->hw_stats = devm_kzalloc(gbe_dev->dev, - gbe_dev->num_et_stats * sizeof(u64), + gbe_dev->hw_stats = devm_kcalloc(gbe_dev->dev, + gbe_dev->num_et_stats, sizeof(u64), GFP_KERNEL); if (!gbe_dev->hw_stats) { dev_err(gbe_dev->dev, "hw_stats memory allocation failed\n"); @@ -3374,8 +3374,8 @@ static int set_gbenu_ethss_priv(struct gbe_priv *gbe_dev, } gbe_dev->hw_stats_prev = - devm_kzalloc(gbe_dev->dev, - gbe_dev->num_et_stats * sizeof(u32), + devm_kcalloc(gbe_dev->dev, + gbe_dev->num_et_stats, sizeof(u32), GFP_KERNEL); if (!gbe_dev->hw_stats_prev) { dev_err(gbe_dev->dev, diff --git a/drivers/net/phy/phy_led_triggers.c b/drivers/net/phy/phy_led_triggers.c index 94ca42e630bb..0049dcae5f30 100644 --- a/drivers/net/phy/phy_led_triggers.c +++ b/drivers/net/phy/phy_led_triggers.c @@ -99,9 +99,9 @@ int phy_led_triggers_register(struct phy_device *phy) if (!phy->phy_num_led_triggers) return 0; - phy->phy_led_triggers = devm_kzalloc(&phy->mdio.dev, - sizeof(struct phy_led_trigger) * - phy->phy_num_led_triggers, + phy->phy_led_triggers = devm_kcalloc(&phy->mdio.dev, + phy->phy_num_led_triggers, + sizeof(struct phy_led_trigger), GFP_KERNEL); if (!phy->phy_led_triggers) { err = -ENOMEM; diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c index 70f6376afd14..a3beeeb46496 100644 --- a/drivers/net/wireless/cnss2/pci.c +++ b/drivers/net/wireless/cnss2/pci.c @@ -726,9 +726,10 @@ static void cnss_pci_dump_shadow_reg(struct cnss_pci_data *pci_priv) gfp = GFP_ATOMIC; if (!pci_priv->debug_reg) { - pci_priv->debug_reg = devm_kzalloc(&pci_priv->pci_dev->dev, - sizeof(*pci_priv->debug_reg) - * array_size, gfp); + pci_priv->debug_reg = devm_kcalloc(&pci_priv->pci_dev->dev, + array_size, + sizeof(*pci_priv->debug_reg), + gfp); if (!pci_priv->debug_reg) return; } @@ -2604,9 +2605,10 @@ static void cnss_pci_dump_qdss_reg(struct cnss_pci_data *pci_priv) gfp = GFP_ATOMIC; if (!plat_priv->qdss_reg) { - plat_priv->qdss_reg = devm_kzalloc(&pci_priv->pci_dev->dev, - sizeof(*plat_priv->qdss_reg) - * array_size, gfp); + plat_priv->qdss_reg = devm_kcalloc(&pci_priv->pci_dev->dev, + array_size, + sizeof(*plat_priv->qdss_reg), + gfp); if (!plat_priv->qdss_reg) return; } diff --git a/drivers/pci/dwc/pci-dra7xx.c b/drivers/pci/dwc/pci-dra7xx.c index 2e0d0b29cdcb..7bfb14a8c49c 100644 --- a/drivers/pci/dwc/pci-dra7xx.c +++ b/drivers/pci/dwc/pci-dra7xx.c @@ -649,11 +649,11 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev) return phy_count; } - phy = devm_kzalloc(dev, sizeof(*phy) * phy_count, GFP_KERNEL); + phy = devm_kcalloc(dev, phy_count, sizeof(*phy), GFP_KERNEL); if (!phy) return -ENOMEM; - link = devm_kzalloc(dev, sizeof(*link) * phy_count, GFP_KERNEL); + link = devm_kcalloc(dev, phy_count, sizeof(*link), GFP_KERNEL); if (!link) return -ENOMEM; diff --git a/drivers/pci/dwc/pcie-designware-ep.c b/drivers/pci/dwc/pcie-designware-ep.c index 71795db41261..aea4b15cf16f 100644 --- a/drivers/pci/dwc/pcie-designware-ep.c +++ b/drivers/pci/dwc/pcie-designware-ep.c @@ -315,19 +315,21 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep) return -EINVAL; } - ep->ib_window_map = devm_kzalloc(dev, sizeof(long) * + ep->ib_window_map = devm_kcalloc(dev, BITS_TO_LONGS(ep->num_ib_windows), + sizeof(long), GFP_KERNEL); if (!ep->ib_window_map) return -ENOMEM; - ep->ob_window_map = devm_kzalloc(dev, sizeof(long) * + ep->ob_window_map = devm_kcalloc(dev, BITS_TO_LONGS(ep->num_ob_windows), + sizeof(long), GFP_KERNEL); if (!ep->ob_window_map) return -ENOMEM; - addr = devm_kzalloc(dev, sizeof(phys_addr_t) * ep->num_ob_windows, + addr = devm_kcalloc(dev, ep->num_ob_windows, sizeof(phys_addr_t), GFP_KERNEL); if (!addr) return -ENOMEM; diff --git a/drivers/pci/host/pci-msm.c b/drivers/pci/host/pci-msm.c index 71c7833ee4d3..2a6cbe368546 100644 --- a/drivers/pci/host/pci-msm.c +++ b/drivers/pci/host/pci-msm.c @@ -3776,8 +3776,9 @@ static int msm_pcie_get_resources(struct msm_pcie_dev_t *dev, "iommu-map", (u32 *)map, size / sizeof(u32)); dev->sid_info_len = map_len; - dev->sid_info = devm_kzalloc(&pdev->dev, - dev->sid_info_len * sizeof(*dev->sid_info), GFP_KERNEL); + dev->sid_info = devm_kcalloc(&pdev->dev, + dev->sid_info_len, sizeof(*dev->sid_info), + GFP_KERNEL); if (!dev->sid_info) { devm_kfree(&pdev->dev, map); ret = -ENOMEM; diff --git a/drivers/pinctrl/berlin/berlin.c b/drivers/pinctrl/berlin/berlin.c index cc3bd2efafe3..df284e9017e4 100644 --- a/drivers/pinctrl/berlin/berlin.c +++ b/drivers/pinctrl/berlin/berlin.c @@ -219,8 +219,9 @@ static int berlin_pinctrl_build_state(struct platform_device *pdev) } /* we will reallocate later */ - pctrl->functions = devm_kzalloc(&pdev->dev, - max_functions * sizeof(*pctrl->functions), + pctrl->functions = devm_kcalloc(&pdev->dev, + max_functions, + sizeof(*pctrl->functions), GFP_KERNEL); if (!pctrl->functions) return -ENOMEM; @@ -264,8 +265,9 @@ static int berlin_pinctrl_build_state(struct platform_device *pdev) if (!function->groups) { function->groups = - devm_kzalloc(&pdev->dev, - function->ngroups * sizeof(char *), + devm_kcalloc(&pdev->dev, + function->ngroups, + sizeof(char *), GFP_KERNEL); if (!function->groups) diff --git a/drivers/pinctrl/freescale/pinctrl-imx.c b/drivers/pinctrl/freescale/pinctrl-imx.c index e088648b3bd4..2291cc38edcc 100644 --- a/drivers/pinctrl/freescale/pinctrl-imx.c +++ b/drivers/pinctrl/freescale/pinctrl-imx.c @@ -477,10 +477,12 @@ static int imx_pinctrl_parse_groups(struct device_node *np, config = imx_pinconf_parse_generic_config(np, ipctl); grp->num_pins = size / pin_size; - grp->data = devm_kzalloc(info->dev, grp->num_pins * - sizeof(struct imx_pin), GFP_KERNEL); - grp->pins = devm_kzalloc(info->dev, grp->num_pins * - sizeof(unsigned int), GFP_KERNEL); + grp->data = devm_kcalloc(info->dev, + grp->num_pins, sizeof(struct imx_pin), + GFP_KERNEL); + grp->pins = devm_kcalloc(info->dev, + grp->num_pins, sizeof(unsigned int), + GFP_KERNEL); if (!grp->pins || !grp->data) return -ENOMEM; diff --git a/drivers/pinctrl/freescale/pinctrl-imx1-core.c b/drivers/pinctrl/freescale/pinctrl-imx1-core.c index e994f8916f01..e423d58d57f7 100644 --- a/drivers/pinctrl/freescale/pinctrl-imx1-core.c +++ b/drivers/pinctrl/freescale/pinctrl-imx1-core.c @@ -488,10 +488,10 @@ static int imx1_pinctrl_parse_groups(struct device_node *np, } grp->npins = size / 12; - grp->pins = devm_kzalloc(info->dev, - grp->npins * sizeof(struct imx1_pin), GFP_KERNEL); - grp->pin_ids = devm_kzalloc(info->dev, - grp->npins * sizeof(unsigned int), GFP_KERNEL); + grp->pins = devm_kcalloc(info->dev, + grp->npins, sizeof(struct imx1_pin), GFP_KERNEL); + grp->pin_ids = devm_kcalloc(info->dev, + grp->npins, sizeof(unsigned int), GFP_KERNEL); if (!grp->pins || !grp->pin_ids) return -ENOMEM; @@ -528,8 +528,8 @@ static int imx1_pinctrl_parse_functions(struct device_node *np, if (func->num_groups == 0) return -EINVAL; - func->groups = devm_kzalloc(info->dev, - func->num_groups * sizeof(char *), GFP_KERNEL); + func->groups = devm_kcalloc(info->dev, + func->num_groups, sizeof(char *), GFP_KERNEL); if (!func->groups) return -ENOMEM; @@ -571,12 +571,12 @@ static int imx1_pinctrl_parse_dt(struct platform_device *pdev, } info->nfunctions = nfuncs; - info->functions = devm_kzalloc(&pdev->dev, - nfuncs * sizeof(struct imx1_pmx_func), GFP_KERNEL); + info->functions = devm_kcalloc(&pdev->dev, + nfuncs, sizeof(struct imx1_pmx_func), GFP_KERNEL); info->ngroups = ngroups; - info->groups = devm_kzalloc(&pdev->dev, - ngroups * sizeof(struct imx1_pin_group), GFP_KERNEL); + info->groups = devm_kcalloc(&pdev->dev, + ngroups, sizeof(struct imx1_pin_group), GFP_KERNEL); if (!info->functions || !info->groups) diff --git a/drivers/pinctrl/freescale/pinctrl-mxs.c b/drivers/pinctrl/freescale/pinctrl-mxs.c index 43a6e900c20f..1286fdab8632 100644 --- a/drivers/pinctrl/freescale/pinctrl-mxs.c +++ b/drivers/pinctrl/freescale/pinctrl-mxs.c @@ -377,12 +377,12 @@ static int mxs_pinctrl_parse_group(struct platform_device *pdev, return -EINVAL; g->npins = length / sizeof(u32); - g->pins = devm_kzalloc(&pdev->dev, g->npins * sizeof(*g->pins), + g->pins = devm_kcalloc(&pdev->dev, g->npins, sizeof(*g->pins), GFP_KERNEL); if (!g->pins) return -ENOMEM; - g->muxsel = devm_kzalloc(&pdev->dev, g->npins * sizeof(*g->muxsel), + g->muxsel = devm_kcalloc(&pdev->dev, g->npins, sizeof(*g->muxsel), GFP_KERNEL); if (!g->muxsel) return -ENOMEM; @@ -433,13 +433,16 @@ static int mxs_pinctrl_probe_dt(struct platform_device *pdev, } } - soc->functions = devm_kzalloc(&pdev->dev, soc->nfunctions * - sizeof(*soc->functions), GFP_KERNEL); + soc->functions = devm_kcalloc(&pdev->dev, + soc->nfunctions, + sizeof(*soc->functions), + GFP_KERNEL); if (!soc->functions) return -ENOMEM; - soc->groups = devm_kzalloc(&pdev->dev, soc->ngroups * - sizeof(*soc->groups), GFP_KERNEL); + soc->groups = devm_kcalloc(&pdev->dev, + soc->ngroups, sizeof(*soc->groups), + GFP_KERNEL); if (!soc->groups) return -ENOMEM; @@ -499,7 +502,8 @@ static int mxs_pinctrl_probe_dt(struct platform_device *pdev, if (strcmp(fn, child->name)) { f = &soc->functions[idxf++]; - f->groups = devm_kzalloc(&pdev->dev, f->ngroups * + f->groups = devm_kcalloc(&pdev->dev, + f->ngroups, sizeof(*f->groups), GFP_KERNEL); if (!f->groups) diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c index 262f591ad8a6..fc00aa4cd982 100644 --- a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +++ b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c @@ -806,9 +806,10 @@ static int armada_37xx_fill_group(struct armada_37xx_pinctrl *info) struct armada_37xx_pin_group *grp = &info->groups[n]; int i, j, f; - grp->pins = devm_kzalloc(info->dev, - (grp->npins + grp->extra_npins) * - sizeof(*grp->pins), GFP_KERNEL); + grp->pins = devm_kcalloc(info->dev, + grp->npins + grp->extra_npins, + sizeof(*grp->pins), + GFP_KERNEL); if (!grp->pins) return -ENOMEM; @@ -858,7 +859,8 @@ static int armada_37xx_fill_func(struct armada_37xx_pinctrl *info) const char **groups; int g; - funcs[n].groups = devm_kzalloc(info->dev, funcs[n].ngroups * + funcs[n].groups = devm_kcalloc(info->dev, + funcs[n].ngroups, sizeof(*(funcs[n].groups)), GFP_KERNEL); if (!funcs[n].groups) @@ -898,8 +900,9 @@ static int armada_37xx_pinctrl_register(struct platform_device *pdev, ctrldesc->pmxops = &armada_37xx_pmx_ops; ctrldesc->confops = &armada_37xx_pinconf_ops; - pindesc = devm_kzalloc(&pdev->dev, sizeof(*pindesc) * - pin_data->nr_pins, GFP_KERNEL); + pindesc = devm_kcalloc(&pdev->dev, + pin_data->nr_pins, sizeof(*pindesc), + GFP_KERNEL); if (!pindesc) return -ENOMEM; @@ -918,8 +921,10 @@ static int armada_37xx_pinctrl_register(struct platform_device *pdev, * we allocate functions for number of pins and hope there are * fewer unique functions than pins available */ - info->funcs = devm_kzalloc(&pdev->dev, pin_data->nr_pins * - sizeof(struct armada_37xx_pmx_func), GFP_KERNEL); + info->funcs = devm_kcalloc(&pdev->dev, + pin_data->nr_pins, + sizeof(struct armada_37xx_pmx_func), + GFP_KERNEL); if (!info->funcs) return -ENOMEM; diff --git a/drivers/pinctrl/mvebu/pinctrl-mvebu.c b/drivers/pinctrl/mvebu/pinctrl-mvebu.c index 163d4614b0f8..30bb9f7117bb 100644 --- a/drivers/pinctrl/mvebu/pinctrl-mvebu.c +++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.c @@ -501,8 +501,9 @@ static int mvebu_pinctrl_build_functions(struct platform_device *pdev, /* we allocate functions for number of pins and hope * there are fewer unique functions than pins available */ - funcs = devm_kzalloc(&pdev->dev, funcsize * - sizeof(struct mvebu_pinctrl_function), GFP_KERNEL); + funcs = devm_kcalloc(&pdev->dev, + funcsize, sizeof(struct mvebu_pinctrl_function), + GFP_KERNEL); if (!funcs) return -ENOMEM; @@ -549,8 +550,9 @@ static int mvebu_pinctrl_build_functions(struct platform_device *pdev, /* allocate group name array if not done already */ if (!f->groups) { - f->groups = devm_kzalloc(&pdev->dev, - f->num_groups * sizeof(char *), + f->groups = devm_kcalloc(&pdev->dev, + f->num_groups, + sizeof(char *), GFP_KERNEL); if (!f->groups) return -ENOMEM; @@ -622,8 +624,10 @@ int mvebu_pinctrl_probe(struct platform_device *pdev) } } - pdesc = devm_kzalloc(&pdev->dev, pctl->desc.npins * - sizeof(struct pinctrl_pin_desc), GFP_KERNEL); + pdesc = devm_kcalloc(&pdev->dev, + pctl->desc.npins, + sizeof(struct pinctrl_pin_desc), + GFP_KERNEL); if (!pdesc) return -ENOMEM; diff --git a/drivers/pinctrl/pinctrl-at91-pio4.c b/drivers/pinctrl/pinctrl-at91-pio4.c index e9d797707255..abb1c853001e 100644 --- a/drivers/pinctrl/pinctrl-at91-pio4.c +++ b/drivers/pinctrl/pinctrl-at91-pio4.c @@ -941,27 +941,30 @@ static int atmel_pinctrl_probe(struct platform_device *pdev) return PTR_ERR(atmel_pioctrl->clk); } - atmel_pioctrl->pins = devm_kzalloc(dev, sizeof(*atmel_pioctrl->pins) - * atmel_pioctrl->npins, GFP_KERNEL); + atmel_pioctrl->pins = devm_kcalloc(dev, + atmel_pioctrl->npins, + sizeof(*atmel_pioctrl->pins), + GFP_KERNEL); if (!atmel_pioctrl->pins) return -ENOMEM; - pin_desc = devm_kzalloc(dev, sizeof(*pin_desc) - * atmel_pioctrl->npins, GFP_KERNEL); + pin_desc = devm_kcalloc(dev, atmel_pioctrl->npins, sizeof(*pin_desc), + GFP_KERNEL); if (!pin_desc) return -ENOMEM; atmel_pinctrl_desc.pins = pin_desc; atmel_pinctrl_desc.npins = atmel_pioctrl->npins; /* One pin is one group since a pin can achieve all functions. */ - group_names = devm_kzalloc(dev, sizeof(*group_names) - * atmel_pioctrl->npins, GFP_KERNEL); + group_names = devm_kcalloc(dev, + atmel_pioctrl->npins, sizeof(*group_names), + GFP_KERNEL); if (!group_names) return -ENOMEM; atmel_pioctrl->group_names = group_names; - atmel_pioctrl->groups = devm_kzalloc(&pdev->dev, - sizeof(*atmel_pioctrl->groups) * atmel_pioctrl->npins, + atmel_pioctrl->groups = devm_kcalloc(&pdev->dev, + atmel_pioctrl->npins, sizeof(*atmel_pioctrl->groups), GFP_KERNEL); if (!atmel_pioctrl->groups) return -ENOMEM; @@ -997,20 +1000,24 @@ static int atmel_pinctrl_probe(struct platform_device *pdev) atmel_pioctrl->gpio_chip->parent = dev; atmel_pioctrl->gpio_chip->names = atmel_pioctrl->group_names; - atmel_pioctrl->pm_wakeup_sources = devm_kzalloc(dev, - sizeof(*atmel_pioctrl->pm_wakeup_sources) - * atmel_pioctrl->nbanks, GFP_KERNEL); + atmel_pioctrl->pm_wakeup_sources = devm_kcalloc(dev, + atmel_pioctrl->nbanks, + sizeof(*atmel_pioctrl->pm_wakeup_sources), + GFP_KERNEL); if (!atmel_pioctrl->pm_wakeup_sources) return -ENOMEM; - atmel_pioctrl->pm_suspend_backup = devm_kzalloc(dev, - sizeof(*atmel_pioctrl->pm_suspend_backup) - * atmel_pioctrl->nbanks, GFP_KERNEL); + atmel_pioctrl->pm_suspend_backup = devm_kcalloc(dev, + atmel_pioctrl->nbanks, + sizeof(*atmel_pioctrl->pm_suspend_backup), + GFP_KERNEL); if (!atmel_pioctrl->pm_suspend_backup) return -ENOMEM; - atmel_pioctrl->irqs = devm_kzalloc(dev, sizeof(*atmel_pioctrl->irqs) - * atmel_pioctrl->nbanks, GFP_KERNEL); + atmel_pioctrl->irqs = devm_kcalloc(dev, + atmel_pioctrl->nbanks, + sizeof(*atmel_pioctrl->irqs), + GFP_KERNEL); if (!atmel_pioctrl->irqs) return -ENOMEM; diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c index 404711f0985a..2311eb8ce8c7 100644 --- a/drivers/pinctrl/pinctrl-at91.c +++ b/drivers/pinctrl/pinctrl-at91.c @@ -269,7 +269,8 @@ static int at91_dt_node_to_map(struct pinctrl_dev *pctldev, } map_num += grp->npins; - new_map = devm_kzalloc(pctldev->dev, sizeof(*new_map) * map_num, GFP_KERNEL); + new_map = devm_kcalloc(pctldev->dev, map_num, sizeof(*new_map), + GFP_KERNEL); if (!new_map) return -ENOMEM; @@ -1049,7 +1050,8 @@ static int at91_pinctrl_mux_mask(struct at91_pinctrl *info, } info->nmux = size / gpio_banks; - info->mux_mask = devm_kzalloc(info->dev, sizeof(u32) * size, GFP_KERNEL); + info->mux_mask = devm_kcalloc(info->dev, size, sizeof(u32), + GFP_KERNEL); if (!info->mux_mask) { dev_err(info->dev, "could not alloc mux_mask\n"); return -ENOMEM; @@ -1089,10 +1091,12 @@ static int at91_pinctrl_parse_groups(struct device_node *np, } grp->npins = size / 4; - pin = grp->pins_conf = devm_kzalloc(info->dev, grp->npins * sizeof(struct at91_pmx_pin), - GFP_KERNEL); - grp->pins = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned int), - GFP_KERNEL); + pin = grp->pins_conf = devm_kcalloc(info->dev, + grp->npins, + sizeof(struct at91_pmx_pin), + GFP_KERNEL); + grp->pins = devm_kcalloc(info->dev, grp->npins, sizeof(unsigned int), + GFP_KERNEL); if (!grp->pins_conf || !grp->pins) return -ENOMEM; @@ -1131,8 +1135,8 @@ static int at91_pinctrl_parse_functions(struct device_node *np, dev_err(info->dev, "no groups defined\n"); return -EINVAL; } - func->groups = devm_kzalloc(info->dev, - func->ngroups * sizeof(char *), GFP_KERNEL); + func->groups = devm_kcalloc(info->dev, + func->ngroups, sizeof(char *), GFP_KERNEL); if (!func->groups) return -ENOMEM; @@ -1194,12 +1198,16 @@ static int at91_pinctrl_probe_dt(struct platform_device *pdev, dev_dbg(&pdev->dev, "nfunctions = %d\n", info->nfunctions); dev_dbg(&pdev->dev, "ngroups = %d\n", info->ngroups); - info->functions = devm_kzalloc(&pdev->dev, info->nfunctions * sizeof(struct at91_pmx_func), + info->functions = devm_kcalloc(&pdev->dev, + info->nfunctions, + sizeof(struct at91_pmx_func), GFP_KERNEL); if (!info->functions) return -ENOMEM; - info->groups = devm_kzalloc(&pdev->dev, info->ngroups * sizeof(struct at91_pin_group), + info->groups = devm_kcalloc(&pdev->dev, + info->ngroups, + sizeof(struct at91_pin_group), GFP_KERNEL); if (!info->groups) return -ENOMEM; @@ -1258,7 +1266,9 @@ static int at91_pinctrl_probe(struct platform_device *pdev) at91_pinctrl_desc.name = dev_name(&pdev->dev); at91_pinctrl_desc.npins = gpio_banks * MAX_NB_GPIO_PER_BANK; at91_pinctrl_desc.pins = pdesc = - devm_kzalloc(&pdev->dev, sizeof(*pdesc) * at91_pinctrl_desc.npins, GFP_KERNEL); + devm_kcalloc(&pdev->dev, + at91_pinctrl_desc.npins, sizeof(*pdesc), + GFP_KERNEL); if (!at91_pinctrl_desc.pins) return -ENOMEM; @@ -1765,7 +1775,7 @@ static int at91_gpio_probe(struct platform_device *pdev) chip->ngpio = ngpio; } - names = devm_kzalloc(&pdev->dev, sizeof(char *) * chip->ngpio, + names = devm_kcalloc(&pdev->dev, chip->ngpio, sizeof(char *), GFP_KERNEL); if (!names) { diff --git a/drivers/pinctrl/pinctrl-digicolor.c b/drivers/pinctrl/pinctrl-digicolor.c index ce269ced4d49..5353b23f775c 100644 --- a/drivers/pinctrl/pinctrl-digicolor.c +++ b/drivers/pinctrl/pinctrl-digicolor.c @@ -291,10 +291,11 @@ static int dc_pinctrl_probe(struct platform_device *pdev) if (IS_ERR(pmap->regs)) return PTR_ERR(pmap->regs); - pins = devm_kzalloc(&pdev->dev, sizeof(*pins)*PINS_COUNT, GFP_KERNEL); + pins = devm_kcalloc(&pdev->dev, PINS_COUNT, sizeof(*pins), + GFP_KERNEL); if (!pins) return -ENOMEM; - pin_names = devm_kzalloc(&pdev->dev, name_len * PINS_COUNT, + pin_names = devm_kcalloc(&pdev->dev, PINS_COUNT, name_len, GFP_KERNEL); if (!pin_names) return -ENOMEM; diff --git a/drivers/pinctrl/pinctrl-ingenic.c b/drivers/pinctrl/pinctrl-ingenic.c index 1541f8cba556..47b1d65f9867 100644 --- a/drivers/pinctrl/pinctrl-ingenic.c +++ b/drivers/pinctrl/pinctrl-ingenic.c @@ -772,8 +772,8 @@ int ingenic_pinctrl_probe(struct platform_device *pdev) pctl_desc->pmxops = &ingenic_pmxops; pctl_desc->confops = &ingenic_confops; pctl_desc->npins = chip_info->num_chips * PINS_PER_GPIO_CHIP; - pctl_desc->pins = jzpc->pdesc = devm_kzalloc(&pdev->dev, - sizeof(*jzpc->pdesc) * pctl_desc->npins, GFP_KERNEL); + pctl_desc->pins = jzpc->pdesc = devm_kcalloc(&pdev->dev, + pctl_desc->npins, sizeof(*jzpc->pdesc), GFP_KERNEL); if (!jzpc->pdesc) return -ENOMEM; diff --git a/drivers/pinctrl/pinctrl-lpc18xx.c b/drivers/pinctrl/pinctrl-lpc18xx.c index 8b4e3582af6e..1d3b88e6ab86 100644 --- a/drivers/pinctrl/pinctrl-lpc18xx.c +++ b/drivers/pinctrl/pinctrl-lpc18xx.c @@ -1302,8 +1302,9 @@ static int lpc18xx_create_group_func_map(struct device *dev, } scu->func[func].ngroups = ngroups; - scu->func[func].groups = devm_kzalloc(dev, ngroups * - sizeof(char *), GFP_KERNEL); + scu->func[func].groups = devm_kcalloc(dev, + ngroups, sizeof(char *), + GFP_KERNEL); if (!scu->func[func].groups) return -ENOMEM; diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c index 5d6cf024ee9c..53cb6c579266 100644 --- a/drivers/pinctrl/pinctrl-rockchip.c +++ b/drivers/pinctrl/pinctrl-rockchip.c @@ -506,7 +506,7 @@ static int rockchip_dt_node_to_map(struct pinctrl_dev *pctldev, } map_num += grp->npins; - new_map = devm_kzalloc(pctldev->dev, sizeof(*new_map) * map_num, + new_map = devm_kcalloc(pctldev->dev, map_num, sizeof(*new_map), GFP_KERNEL); if (!new_map) return -ENOMEM; @@ -2293,10 +2293,11 @@ static int rockchip_pinctrl_parse_groups(struct device_node *np, grp->npins = size / 4; - grp->pins = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned int), + grp->pins = devm_kcalloc(info->dev, grp->npins, sizeof(unsigned int), GFP_KERNEL); - grp->data = devm_kzalloc(info->dev, grp->npins * - sizeof(struct rockchip_pin_config), + grp->data = devm_kcalloc(info->dev, + grp->npins, + sizeof(struct rockchip_pin_config), GFP_KERNEL); if (!grp->pins || !grp->data) return -ENOMEM; @@ -2348,8 +2349,8 @@ static int rockchip_pinctrl_parse_functions(struct device_node *np, if (func->ngroups <= 0) return 0; - func->groups = devm_kzalloc(info->dev, - func->ngroups * sizeof(char *), GFP_KERNEL); + func->groups = devm_kcalloc(info->dev, + func->ngroups, sizeof(char *), GFP_KERNEL); if (!func->groups) return -ENOMEM; @@ -2380,7 +2381,8 @@ static int rockchip_pinctrl_parse_dt(struct platform_device *pdev, dev_dbg(&pdev->dev, "nfunctions = %d\n", info->nfunctions); dev_dbg(&pdev->dev, "ngroups = %d\n", info->ngroups); - info->functions = devm_kzalloc(dev, info->nfunctions * + info->functions = devm_kcalloc(dev, + info->nfunctions, sizeof(struct rockchip_pmx_func), GFP_KERNEL); if (!info->functions) { @@ -2388,7 +2390,8 @@ static int rockchip_pinctrl_parse_dt(struct platform_device *pdev, return -EINVAL; } - info->groups = devm_kzalloc(dev, info->ngroups * + info->groups = devm_kcalloc(dev, + info->ngroups, sizeof(struct rockchip_pin_group), GFP_KERNEL); if (!info->groups) { @@ -2428,8 +2431,9 @@ static int rockchip_pinctrl_register(struct platform_device *pdev, ctrldesc->pmxops = &rockchip_pmx_ops; ctrldesc->confops = &rockchip_pinconf_ops; - pindesc = devm_kzalloc(&pdev->dev, sizeof(*pindesc) * - info->ctrl->nr_pins, GFP_KERNEL); + pindesc = devm_kcalloc(&pdev->dev, + info->ctrl->nr_pins, sizeof(*pindesc), + GFP_KERNEL); if (!pindesc) { dev_err(&pdev->dev, "mem alloc for pin descriptors failed\n"); return -ENOMEM; diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c index b8b3d932cd73..7c00775af758 100644 --- a/drivers/pinctrl/pinctrl-single.c +++ b/drivers/pinctrl/pinctrl-single.c @@ -690,8 +690,8 @@ static int pcs_allocate_pin_table(struct pcs_device *pcs) } dev_dbg(pcs->dev, "allocating %i pins\n", nr_pins); - pcs->pins.pa = devm_kzalloc(pcs->dev, - sizeof(*pcs->pins.pa) * nr_pins, + pcs->pins.pa = devm_kcalloc(pcs->dev, + nr_pins, sizeof(*pcs->pins.pa), GFP_KERNEL); if (!pcs->pins.pa) return -ENOMEM; @@ -902,15 +902,15 @@ static int pcs_parse_pinconf(struct pcs_device *pcs, struct device_node *np, if (!nconfs) return 0; - func->conf = devm_kzalloc(pcs->dev, - sizeof(struct pcs_conf_vals) * nconfs, + func->conf = devm_kcalloc(pcs->dev, + nconfs, sizeof(struct pcs_conf_vals), GFP_KERNEL); if (!func->conf) return -ENOMEM; func->nconfs = nconfs; conf = &(func->conf[0]); m++; - settings = devm_kzalloc(pcs->dev, sizeof(unsigned long) * nconfs, + settings = devm_kcalloc(pcs->dev, nconfs, sizeof(unsigned long), GFP_KERNEL); if (!settings) return -ENOMEM; @@ -966,11 +966,11 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs, return -EINVAL; } - vals = devm_kzalloc(pcs->dev, sizeof(*vals) * rows, GFP_KERNEL); + vals = devm_kcalloc(pcs->dev, rows, sizeof(*vals), GFP_KERNEL); if (!vals) return -ENOMEM; - pins = devm_kzalloc(pcs->dev, sizeof(*pins) * rows, GFP_KERNEL); + pins = devm_kcalloc(pcs->dev, rows, sizeof(*pins), GFP_KERNEL); if (!pins) goto free_vals; @@ -1067,13 +1067,15 @@ static int pcs_parse_bits_in_pinctrl_entry(struct pcs_device *pcs, npins_in_row = pcs->width / pcs->bits_per_pin; - vals = devm_kzalloc(pcs->dev, sizeof(*vals) * rows * npins_in_row, - GFP_KERNEL); + vals = devm_kzalloc(pcs->dev, + array3_size(rows, npins_in_row, sizeof(*vals)), + GFP_KERNEL); if (!vals) return -ENOMEM; - pins = devm_kzalloc(pcs->dev, sizeof(*pins) * rows * npins_in_row, - GFP_KERNEL); + pins = devm_kzalloc(pcs->dev, + array3_size(rows, npins_in_row, sizeof(*pins)), + GFP_KERNEL); if (!pins) goto free_vals; @@ -1195,7 +1197,7 @@ static int pcs_dt_node_to_map(struct pinctrl_dev *pctldev, pcs = pinctrl_dev_get_drvdata(pctldev); /* create 2 maps. One is for pinmux, and the other is for pinconf. */ - *map = devm_kzalloc(pcs->dev, sizeof(**map) * 2, GFP_KERNEL); + *map = devm_kcalloc(pcs->dev, 2, sizeof(**map), GFP_KERNEL); if (!*map) return -ENOMEM; diff --git a/drivers/pinctrl/pinctrl-st.c b/drivers/pinctrl/pinctrl-st.c index a5205b94b2e6..6988935e8ded 100644 --- a/drivers/pinctrl/pinctrl-st.c +++ b/drivers/pinctrl/pinctrl-st.c @@ -823,8 +823,8 @@ static int st_pctl_dt_node_to_map(struct pinctrl_dev *pctldev, } map_num = grp->npins + 1; - new_map = devm_kzalloc(pctldev->dev, - sizeof(*new_map) * map_num, GFP_KERNEL); + new_map = devm_kcalloc(pctldev->dev, + map_num, sizeof(*new_map), GFP_KERNEL); if (!new_map) return -ENOMEM; @@ -1191,9 +1191,9 @@ static int st_pctl_dt_parse_groups(struct device_node *np, grp->npins = npins; grp->name = np->name; - grp->pins = devm_kzalloc(info->dev, npins * sizeof(u32), GFP_KERNEL); - grp->pin_conf = devm_kzalloc(info->dev, - npins * sizeof(*conf), GFP_KERNEL); + grp->pins = devm_kcalloc(info->dev, npins, sizeof(u32), GFP_KERNEL); + grp->pin_conf = devm_kcalloc(info->dev, + npins, sizeof(*conf), GFP_KERNEL); if (!grp->pins || !grp->pin_conf) return -ENOMEM; @@ -1249,8 +1249,8 @@ static int st_pctl_parse_functions(struct device_node *np, dev_err(info->dev, "No groups defined\n"); return -EINVAL; } - func->groups = devm_kzalloc(info->dev, - func->ngroups * sizeof(char *), GFP_KERNEL); + func->groups = devm_kcalloc(info->dev, + func->ngroups, sizeof(char *), GFP_KERNEL); if (!func->groups) return -ENOMEM; @@ -1573,14 +1573,15 @@ static int st_pctl_probe_dt(struct platform_device *pdev, dev_info(&pdev->dev, "nfunctions = %d\n", info->nfunctions); dev_info(&pdev->dev, "ngroups = %d\n", info->ngroups); - info->functions = devm_kzalloc(&pdev->dev, - info->nfunctions * sizeof(*info->functions), GFP_KERNEL); + info->functions = devm_kcalloc(&pdev->dev, + info->nfunctions, sizeof(*info->functions), GFP_KERNEL); - info->groups = devm_kzalloc(&pdev->dev, - info->ngroups * sizeof(*info->groups) , GFP_KERNEL); + info->groups = devm_kcalloc(&pdev->dev, + info->ngroups, sizeof(*info->groups), + GFP_KERNEL); - info->banks = devm_kzalloc(&pdev->dev, - info->nbanks * sizeof(*info->banks), GFP_KERNEL); + info->banks = devm_kcalloc(&pdev->dev, + info->nbanks, sizeof(*info->banks), GFP_KERNEL); if (!info->functions || !info->groups || !info->banks) return -ENOMEM; @@ -1608,8 +1609,8 @@ static int st_pctl_probe_dt(struct platform_device *pdev, } pctl_desc->npins = info->nbanks * ST_GPIO_PINS_PER_BANK; - pdesc = devm_kzalloc(&pdev->dev, - sizeof(*pdesc) * pctl_desc->npins, GFP_KERNEL); + pdesc = devm_kcalloc(&pdev->dev, + pctl_desc->npins, sizeof(*pdesc), GFP_KERNEL); if (!pdesc) return -ENOMEM; diff --git a/drivers/pinctrl/pinctrl-xway.c b/drivers/pinctrl/pinctrl-xway.c index 1b0c5958c56a..ea65b0041f7e 100644 --- a/drivers/pinctrl/pinctrl-xway.c +++ b/drivers/pinctrl/pinctrl-xway.c @@ -1727,8 +1727,8 @@ static int pinmux_xway_probe(struct platform_device *pdev) xway_chip.ngpio = xway_soc->pin_count; /* load our pad descriptors */ - xway_info.pads = devm_kzalloc(&pdev->dev, - sizeof(struct pinctrl_pin_desc) * xway_chip.ngpio, + xway_info.pads = devm_kcalloc(&pdev->dev, + xway_chip.ngpio, sizeof(struct pinctrl_pin_desc), GFP_KERNEL); if (!xway_info.pads) { dev_err(&pdev->dev, "Failed to allocate pads\n"); diff --git a/drivers/pinctrl/qcom/pinctrl-sm6150.c b/drivers/pinctrl/qcom/pinctrl-sm6150.c index ba2237ed1e1d..b0d685dbd6f2 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm6150.c +++ b/drivers/pinctrl/qcom/pinctrl-sm6150.c @@ -1684,8 +1684,9 @@ static int sm6150_pinctrl_dir_conn_probe(struct platform_device *pdev) dir_conn_length = length / sizeof(u32); - dir_conn_entries = devm_kzalloc(&pdev->dev, - dir_conn_length*sizeof(uint32_t), GFP_KERNEL); + dir_conn_entries = devm_kcalloc(&pdev->dev, + dir_conn_length, sizeof(uint32_t), + GFP_KERNEL); if (!dir_conn_entries) return -ENOMEM; @@ -1700,8 +1701,8 @@ static int sm6150_pinctrl_dir_conn_probe(struct platform_device *pdev) num_dir_conns = (dir_conn_length / 3); - dir_conn_list = devm_kzalloc(&pdev->dev, - num_dir_conns * sizeof(*dir_conn_list), GFP_KERNEL); + dir_conn_list = devm_kcalloc(&pdev->dev, + num_dir_conns, sizeof(*dir_conn_list), GFP_KERNEL); if (!dir_conn_list) return -ENOMEM; diff --git a/drivers/pinctrl/qcom/pinctrl-sm8150.c b/drivers/pinctrl/qcom/pinctrl-sm8150.c index b25777617a30..b1baff68e334 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm8150.c +++ b/drivers/pinctrl/qcom/pinctrl-sm8150.c @@ -1985,8 +1985,9 @@ static int sm8150_pinctrl_dir_conn_probe(struct platform_device *pdev) dir_conn_length = length / sizeof(u32); - dir_conn_entries = devm_kzalloc(&pdev->dev, - dir_conn_length*sizeof(uint32_t), GFP_KERNEL); + dir_conn_entries = devm_kcalloc(&pdev->dev, + dir_conn_length, sizeof(uint32_t), + GFP_KERNEL); if (!dir_conn_entries) return -ENOMEM; @@ -1995,8 +1996,8 @@ static int sm8150_pinctrl_dir_conn_probe(struct platform_device *pdev) num_dir_conns = (dir_conn_length / 3); - dir_conn_list = devm_kzalloc(&pdev->dev, - num_dir_conns * sizeof(*dir_conn_list), GFP_KERNEL); + dir_conn_list = devm_kcalloc(&pdev->dev, + num_dir_conns, sizeof(*dir_conn_list), GFP_KERNEL); if (!dir_conn_list) return -ENOMEM; diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.c b/drivers/pinctrl/samsung/pinctrl-exynos.c index 6925a3d969e2..6e93478027e4 100644 --- a/drivers/pinctrl/samsung/pinctrl-exynos.c +++ b/drivers/pinctrl/samsung/pinctrl-exynos.c @@ -499,8 +499,9 @@ int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d) continue; } - weint_data = devm_kzalloc(dev, bank->nr_pins - * sizeof(*weint_data), GFP_KERNEL); + weint_data = devm_kcalloc(dev, + bank->nr_pins, sizeof(*weint_data), + GFP_KERNEL); if (!weint_data) return -ENOMEM; diff --git a/drivers/pinctrl/samsung/pinctrl-exynos5440.c b/drivers/pinctrl/samsung/pinctrl-exynos5440.c index f8073ccd449f..cf5e066008a4 100644 --- a/drivers/pinctrl/samsung/pinctrl-exynos5440.c +++ b/drivers/pinctrl/samsung/pinctrl-exynos5440.c @@ -642,7 +642,7 @@ static int exynos5440_pinctrl_parse_dt_pins(struct platform_device *pdev, return -EINVAL; } - *pin_list = devm_kzalloc(dev, *npins * sizeof(**pin_list), GFP_KERNEL); + *pin_list = devm_kcalloc(dev, *npins, sizeof(**pin_list), GFP_KERNEL); if (!*pin_list) return -ENOMEM; @@ -671,13 +671,14 @@ static int exynos5440_pinctrl_parse_dt(struct platform_device *pdev, if (!grp_cnt) return -EINVAL; - groups = devm_kzalloc(dev, grp_cnt * sizeof(*groups), GFP_KERNEL); + groups = devm_kcalloc(dev, grp_cnt, sizeof(*groups), GFP_KERNEL); if (!groups) return -EINVAL; grp = groups; - functions = devm_kzalloc(dev, grp_cnt * sizeof(*functions), GFP_KERNEL); + functions = devm_kcalloc(dev, grp_cnt, sizeof(*functions), + GFP_KERNEL); if (!functions) return -EINVAL; @@ -759,8 +760,9 @@ static int exynos5440_pinctrl_register(struct platform_device *pdev, ctrldesc->pmxops = &exynos5440_pinmux_ops; ctrldesc->confops = &exynos5440_pinconf_ops; - pindesc = devm_kzalloc(&pdev->dev, sizeof(*pindesc) * - EXYNOS5440_MAX_PINS, GFP_KERNEL); + pindesc = devm_kcalloc(&pdev->dev, + EXYNOS5440_MAX_PINS, sizeof(*pindesc), + GFP_KERNEL); if (!pindesc) return -ENOMEM; ctrldesc->pins = pindesc; @@ -774,8 +776,9 @@ static int exynos5440_pinctrl_register(struct platform_device *pdev, * allocate space for storing the dynamically generated names for all * the pins which belong to this pin-controller. */ - pin_names = devm_kzalloc(&pdev->dev, sizeof(char) * PIN_NAME_LENGTH * - ctrldesc->npins, GFP_KERNEL); + pin_names = devm_kzalloc(&pdev->dev, + array3_size(sizeof(char), PIN_NAME_LENGTH, ctrldesc->npins), + GFP_KERNEL); if (!pin_names) return -ENOMEM; @@ -914,7 +917,7 @@ static int exynos5440_gpio_irq_init(struct platform_device *pdev, struct exynos5440_gpio_intr_data *intd; int i, irq, ret; - intd = devm_kzalloc(dev, sizeof(*intd) * EXYNOS5440_MAX_GPIO_INT, + intd = devm_kcalloc(dev, EXYNOS5440_MAX_GPIO_INT, sizeof(*intd), GFP_KERNEL); if (!intd) return -ENOMEM; diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c index 7c0f5d4e89f3..306faf2c9a70 100644 --- a/drivers/pinctrl/samsung/pinctrl-samsung.c +++ b/drivers/pinctrl/samsung/pinctrl-samsung.c @@ -651,7 +651,7 @@ static struct samsung_pin_group *samsung_pinctrl_create_groups( const struct pinctrl_pin_desc *pdesc; int i; - groups = devm_kzalloc(dev, ctrldesc->npins * sizeof(*groups), + groups = devm_kcalloc(dev, ctrldesc->npins, sizeof(*groups), GFP_KERNEL); if (!groups) return ERR_PTR(-EINVAL); @@ -688,7 +688,7 @@ static int samsung_pinctrl_create_function(struct device *dev, func->name = func_np->full_name; - func->groups = devm_kzalloc(dev, npins * sizeof(char *), GFP_KERNEL); + func->groups = devm_kcalloc(dev, npins, sizeof(char *), GFP_KERNEL); if (!func->groups) return -ENOMEM; @@ -745,7 +745,7 @@ static struct samsung_pmx_func *samsung_pinctrl_create_functions( } } - functions = devm_kzalloc(dev, func_cnt * sizeof(*functions), + functions = devm_kcalloc(dev, func_cnt, sizeof(*functions), GFP_KERNEL); if (!functions) return ERR_PTR(-ENOMEM); @@ -842,8 +842,9 @@ static int samsung_pinctrl_register(struct platform_device *pdev, ctrldesc->pmxops = &samsung_pinmux_ops; ctrldesc->confops = &samsung_pinconf_ops; - pindesc = devm_kzalloc(&pdev->dev, sizeof(*pindesc) * - drvdata->nr_pins, GFP_KERNEL); + pindesc = devm_kcalloc(&pdev->dev, + drvdata->nr_pins, sizeof(*pindesc), + GFP_KERNEL); if (!pindesc) return -ENOMEM; ctrldesc->pins = pindesc; @@ -857,8 +858,9 @@ static int samsung_pinctrl_register(struct platform_device *pdev, * allocate space for storing the dynamically generated names for all * the pins which belong to this pin-controller. */ - pin_names = devm_kzalloc(&pdev->dev, sizeof(char) * PIN_NAME_LENGTH * - drvdata->nr_pins, GFP_KERNEL); + pin_names = devm_kzalloc(&pdev->dev, + array3_size(sizeof(char), PIN_NAME_LENGTH, drvdata->nr_pins), + GFP_KERNEL); if (!pin_names) return -ENOMEM; diff --git a/drivers/pinctrl/sh-pfc/core.c b/drivers/pinctrl/sh-pfc/core.c index 0c5e952461fd..56d5214ac5f9 100644 --- a/drivers/pinctrl/sh-pfc/core.c +++ b/drivers/pinctrl/sh-pfc/core.c @@ -56,7 +56,7 @@ static int sh_pfc_map_resources(struct sh_pfc *pfc, return -EINVAL; /* Allocate memory windows and IRQs arrays. */ - windows = devm_kzalloc(pfc->dev, num_windows * sizeof(*windows), + windows = devm_kcalloc(pfc->dev, num_windows, sizeof(*windows), GFP_KERNEL); if (windows == NULL) return -ENOMEM; @@ -65,7 +65,7 @@ static int sh_pfc_map_resources(struct sh_pfc *pfc, pfc->windows = windows; if (num_irqs) { - irqs = devm_kzalloc(pfc->dev, num_irqs * sizeof(*irqs), + irqs = devm_kcalloc(pfc->dev, num_irqs, sizeof(*irqs), GFP_KERNEL); if (irqs == NULL) return -ENOMEM; @@ -438,7 +438,7 @@ static int sh_pfc_init_ranges(struct sh_pfc *pfc) } pfc->nr_ranges = nr_ranges; - pfc->ranges = devm_kzalloc(pfc->dev, sizeof(*pfc->ranges) * nr_ranges, + pfc->ranges = devm_kcalloc(pfc->dev, nr_ranges, sizeof(*pfc->ranges), GFP_KERNEL); if (pfc->ranges == NULL) return -ENOMEM; diff --git a/drivers/pinctrl/sh-pfc/gpio.c b/drivers/pinctrl/sh-pfc/gpio.c index 6b5422766f13..b173148e752f 100644 --- a/drivers/pinctrl/sh-pfc/gpio.c +++ b/drivers/pinctrl/sh-pfc/gpio.c @@ -107,7 +107,7 @@ static int gpio_setup_data_regs(struct sh_pfc_chip *chip) for (i = 0; pfc->info->data_regs[i].reg_width; ++i) ; - chip->regs = devm_kzalloc(pfc->dev, i * sizeof(*chip->regs), + chip->regs = devm_kcalloc(pfc->dev, i, sizeof(*chip->regs), GFP_KERNEL); if (chip->regs == NULL) return -ENOMEM; @@ -224,8 +224,9 @@ static int gpio_pin_setup(struct sh_pfc_chip *chip) struct gpio_chip *gc = &chip->gpio_chip; int ret; - chip->pins = devm_kzalloc(pfc->dev, pfc->info->nr_pins * - sizeof(*chip->pins), GFP_KERNEL); + chip->pins = devm_kcalloc(pfc->dev, + pfc->info->nr_pins, sizeof(*chip->pins), + GFP_KERNEL); if (chip->pins == NULL) return -ENOMEM; diff --git a/drivers/pinctrl/sh-pfc/pinctrl.c b/drivers/pinctrl/sh-pfc/pinctrl.c index 5c9d79981e6d..90fb4c4083fa 100644 --- a/drivers/pinctrl/sh-pfc/pinctrl.c +++ b/drivers/pinctrl/sh-pfc/pinctrl.c @@ -770,14 +770,14 @@ static int sh_pfc_map_pins(struct sh_pfc *pfc, struct sh_pfc_pinctrl *pmx) unsigned int i; /* Allocate and initialize the pins and configs arrays. */ - pmx->pins = devm_kzalloc(pfc->dev, - sizeof(*pmx->pins) * pfc->info->nr_pins, + pmx->pins = devm_kcalloc(pfc->dev, + pfc->info->nr_pins, sizeof(*pmx->pins), GFP_KERNEL); if (unlikely(!pmx->pins)) return -ENOMEM; - pmx->configs = devm_kzalloc(pfc->dev, - sizeof(*pmx->configs) * pfc->info->nr_pins, + pmx->configs = devm_kcalloc(pfc->dev, + pfc->info->nr_pins, sizeof(*pmx->configs), GFP_KERNEL); if (unlikely(!pmx->configs)) return -ENOMEM; diff --git a/drivers/pinctrl/spear/pinctrl-plgpio.c b/drivers/pinctrl/spear/pinctrl-plgpio.c index cf6d68c7345b..bd5bea82683e 100644 --- a/drivers/pinctrl/spear/pinctrl-plgpio.c +++ b/drivers/pinctrl/spear/pinctrl-plgpio.c @@ -540,9 +540,9 @@ static int plgpio_probe(struct platform_device *pdev) dev_warn(&pdev->dev, "clk_get() failed, work without it\n"); #ifdef CONFIG_PM_SLEEP - plgpio->csave_regs = devm_kzalloc(&pdev->dev, - sizeof(*plgpio->csave_regs) * + plgpio->csave_regs = devm_kcalloc(&pdev->dev, DIV_ROUND_UP(plgpio->chip.ngpio, MAX_GPIO_PER_REG), + sizeof(*plgpio->csave_regs), GFP_KERNEL); if (!plgpio->csave_regs) { dev_err(&pdev->dev, "csave registers memory allocation fail\n"); diff --git a/drivers/pinctrl/sprd/pinctrl-sprd.c b/drivers/pinctrl/sprd/pinctrl-sprd.c index 83958bdd0f05..2c850f8059c8 100644 --- a/drivers/pinctrl/sprd/pinctrl-sprd.c +++ b/drivers/pinctrl/sprd/pinctrl-sprd.c @@ -877,8 +877,9 @@ static int sprd_pinctrl_parse_groups(struct device_node *np, grp->name = np->name; grp->npins = ret; - grp->pins = devm_kzalloc(sprd_pctl->dev, grp->npins * - sizeof(unsigned int), GFP_KERNEL); + grp->pins = devm_kcalloc(sprd_pctl->dev, + grp->npins, sizeof(unsigned int), + GFP_KERNEL); if (!grp->pins) return -ENOMEM; @@ -929,14 +930,15 @@ static int sprd_pinctrl_parse_dt(struct sprd_pinctrl *sprd_pctl) if (!info->ngroups) return 0; - info->groups = devm_kzalloc(sprd_pctl->dev, info->ngroups * + info->groups = devm_kcalloc(sprd_pctl->dev, + info->ngroups, sizeof(struct sprd_pin_group), GFP_KERNEL); if (!info->groups) return -ENOMEM; - info->grp_names = devm_kzalloc(sprd_pctl->dev, - info->ngroups * sizeof(char *), + info->grp_names = devm_kcalloc(sprd_pctl->dev, + info->ngroups, sizeof(char *), GFP_KERNEL); if (!info->grp_names) return -ENOMEM; @@ -978,8 +980,8 @@ static int sprd_pinctrl_add_pins(struct sprd_pinctrl *sprd_pctl, int i; info->npins = pins_cnt; - info->pins = devm_kzalloc(sprd_pctl->dev, - info->npins * sizeof(struct sprd_pin), + info->pins = devm_kcalloc(sprd_pctl->dev, + info->npins, sizeof(struct sprd_pin), GFP_KERNEL); if (!info->pins) return -ENOMEM; @@ -1055,7 +1057,8 @@ int sprd_pinctrl_core_probe(struct platform_device *pdev, return ret; } - pin_desc = devm_kzalloc(&pdev->dev, pinctrl_info->npins * + pin_desc = devm_kcalloc(&pdev->dev, + pinctrl_info->npins, sizeof(struct pinctrl_pin_desc), GFP_KERNEL); if (!pin_desc) diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index 8b3fd553ef55..c281ac177f72 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c @@ -1053,8 +1053,8 @@ static int sunxi_pinctrl_build_state(struct platform_device *pdev) * this means that the number of pins is the maximum group * number we will ever see. */ - pctl->groups = devm_kzalloc(&pdev->dev, - pctl->desc->npins * sizeof(*pctl->groups), + pctl->groups = devm_kcalloc(&pdev->dev, + pctl->desc->npins, sizeof(*pctl->groups), GFP_KERNEL); if (!pctl->groups) return -ENOMEM; @@ -1077,8 +1077,9 @@ static int sunxi_pinctrl_build_state(struct platform_device *pdev) * We suppose that we won't have any more functions than pins, * we'll reallocate that later anyway */ - pctl->functions = devm_kzalloc(&pdev->dev, - pctl->ngroups * sizeof(*pctl->functions), + pctl->functions = devm_kcalloc(&pdev->dev, + pctl->ngroups, + sizeof(*pctl->functions), GFP_KERNEL); if (!pctl->functions) return -ENOMEM; @@ -1137,8 +1138,9 @@ static int sunxi_pinctrl_build_state(struct platform_device *pdev) if (!func_item->groups) { func_item->groups = - devm_kzalloc(&pdev->dev, - func_item->ngroups * sizeof(*func_item->groups), + devm_kcalloc(&pdev->dev, + func_item->ngroups, + sizeof(*func_item->groups), GFP_KERNEL); if (!func_item->groups) return -ENOMEM; @@ -1281,8 +1283,8 @@ int sunxi_pinctrl_init_with_variant(struct platform_device *pdev, return ret; } - pins = devm_kzalloc(&pdev->dev, - pctl->desc->npins * sizeof(*pins), + pins = devm_kcalloc(&pdev->dev, + pctl->desc->npins, sizeof(*pins), GFP_KERNEL); if (!pins) return -ENOMEM; diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.c b/drivers/pinctrl/tegra/pinctrl-tegra.c index e5c9b9c68428..c26376690b02 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra.c +++ b/drivers/pinctrl/tegra/pinctrl-tegra.c @@ -679,8 +679,8 @@ int tegra_pinctrl_probe(struct platform_device *pdev, * Each mux group will appear in 4 functions' list of groups. * This over-allocates slightly, since not all groups are mux groups. */ - pmx->group_pins = devm_kzalloc(&pdev->dev, - soc_data->ngroups * 4 * sizeof(*pmx->group_pins), + pmx->group_pins = devm_kcalloc(&pdev->dev, + soc_data->ngroups * 4, sizeof(*pmx->group_pins), GFP_KERNEL); if (!pmx->group_pins) return -ENOMEM; @@ -722,7 +722,7 @@ int tegra_pinctrl_probe(struct platform_device *pdev, } pmx->nbanks = i; - pmx->regs = devm_kzalloc(&pdev->dev, pmx->nbanks * sizeof(*pmx->regs), + pmx->regs = devm_kcalloc(&pdev->dev, pmx->nbanks, sizeof(*pmx->regs), GFP_KERNEL); if (!pmx->regs) { dev_err(&pdev->dev, "Can't alloc regs pointer\n"); diff --git a/drivers/pinctrl/ti/pinctrl-ti-iodelay.c b/drivers/pinctrl/ti/pinctrl-ti-iodelay.c index 8ac1f1ce4442..61f8b8d14b2d 100644 --- a/drivers/pinctrl/ti/pinctrl-ti-iodelay.c +++ b/drivers/pinctrl/ti/pinctrl-ti-iodelay.c @@ -510,11 +510,11 @@ static int ti_iodelay_dt_node_to_map(struct pinctrl_dev *pctldev, goto free_map; } - pins = devm_kzalloc(iod->dev, sizeof(*pins) * rows, GFP_KERNEL); + pins = devm_kcalloc(iod->dev, rows, sizeof(*pins), GFP_KERNEL); if (!pins) goto free_group; - cfg = devm_kzalloc(iod->dev, sizeof(*cfg) * rows, GFP_KERNEL); + cfg = devm_kcalloc(iod->dev, rows, sizeof(*cfg), GFP_KERNEL); if (!cfg) { error = -ENOMEM; goto free_pins; @@ -753,7 +753,7 @@ static int ti_iodelay_alloc_pins(struct device *dev, nr_pins = ti_iodelay_offset_to_pin(iod, r->regmap_config->max_register); dev_dbg(dev, "Allocating %i pins\n", nr_pins); - iod->pa = devm_kzalloc(dev, sizeof(*iod->pa) * nr_pins, GFP_KERNEL); + iod->pa = devm_kcalloc(dev, nr_pins, sizeof(*iod->pa), GFP_KERNEL); if (!iod->pa) return -ENOMEM; diff --git a/drivers/pinctrl/zte/pinctrl-zx.c b/drivers/pinctrl/zte/pinctrl-zx.c index 91955e770236..3cb69309912b 100644 --- a/drivers/pinctrl/zte/pinctrl-zx.c +++ b/drivers/pinctrl/zte/pinctrl-zx.c @@ -277,7 +277,7 @@ static int zx_pinctrl_build_state(struct platform_device *pdev) /* Every single pin composes a group */ ngroups = info->npins; - groups = devm_kzalloc(&pdev->dev, ngroups * sizeof(*groups), + groups = devm_kcalloc(&pdev->dev, ngroups, sizeof(*groups), GFP_KERNEL); if (!groups) return -ENOMEM; @@ -362,8 +362,8 @@ static int zx_pinctrl_build_state(struct platform_device *pdev) func = functions + j; if (!func->group_names) { - func->group_names = devm_kzalloc(&pdev->dev, - func->num_group_names * + func->group_names = devm_kcalloc(&pdev->dev, + func->num_group_names, sizeof(*func->group_names), GFP_KERNEL); if (!func->group_names) { diff --git a/drivers/platform/msm/gsi/gsi.c b/drivers/platform/msm/gsi/gsi.c index b13347dbac96..17fdb10c8a6c 100644 --- a/drivers/platform/msm/gsi/gsi.c +++ b/drivers/platform/msm/gsi/gsi.c @@ -2374,8 +2374,8 @@ int gsi_alloc_channel(struct gsi_chan_props *props, unsigned long dev_hdl, if (props->prot == GSI_CHAN_PROT_GCI) user_data_size += GSI_VEID_MAX; - user_data = devm_kzalloc(gsi_ctx->dev, - user_data_size * sizeof(*user_data), + user_data = devm_kcalloc(gsi_ctx->dev, + user_data_size, sizeof(*user_data), GFP_KERNEL); if (user_data == NULL) { GSIERR("context not allocated\n"); diff --git a/drivers/platform/msm/qcom-geni-se.c b/drivers/platform/msm/qcom-geni-se.c index 8d5d37809546..a3ca53d4a11a 100644 --- a/drivers/platform/msm/qcom-geni-se.c +++ b/drivers/platform/msm/qcom-geni-se.c @@ -1861,8 +1861,10 @@ static struct msm_bus_scale_pdata *ab_ib_register(struct platform_device *pdev, for (i = 0; i < pdata->num_usecases; i++) { usecase[i].num_paths = host->num_paths; - usecase[i].vectors = devm_kzalloc(dev, host->num_paths * - sizeof(struct msm_bus_vectors), GFP_KERNEL); + usecase[i].vectors = devm_kcalloc(dev, + host->num_paths, + sizeof(struct msm_bus_vectors), + GFP_KERNEL); if (!usecase[i].vectors) { mem_err = true; pr_err("Error: Mem alloc failure in vectors\n"); diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c index d0079e39e84d..8bdb7e108cdc 100644 --- a/drivers/platform/msm/usb_bam.c +++ b/drivers/platform/msm/usb_bam.c @@ -2952,8 +2952,10 @@ static struct msm_usb_bam_data *usb_bam_dt_to_data( goto err; } - usb_bam_connections = devm_kzalloc(&pdev->dev, max_connections * - sizeof(struct usb_bam_pipe_connect), GFP_KERNEL); + usb_bam_connections = devm_kcalloc(&pdev->dev, + max_connections, + sizeof(struct usb_bam_pipe_connect), + GFP_KERNEL); if (!usb_bam_connections) { log_event_err("%s: devm_kzalloc failed(%d)\n", @@ -3165,8 +3167,8 @@ static int enable_usb_bam(struct platform_device *pdev) if (ret) return ret; - ctx->usb_bam_sps.sps_pipes = devm_kzalloc(&pdev->dev, - ctx->max_connections * sizeof(struct sps_pipe *), + ctx->usb_bam_sps.sps_pipes = devm_kcalloc(&pdev->dev, + ctx->max_connections, sizeof(struct sps_pipe *), GFP_KERNEL); if (!ctx->usb_bam_sps.sps_pipes) { @@ -3174,8 +3176,8 @@ static int enable_usb_bam(struct platform_device *pdev) return -ENOMEM; } - ctx->usb_bam_sps.sps_connections = devm_kzalloc(&pdev->dev, - ctx->max_connections * sizeof(struct sps_connect), + ctx->usb_bam_sps.sps_connections = devm_kcalloc(&pdev->dev, + ctx->max_connections, sizeof(struct sps_connect), GFP_KERNEL); if (!ctx->usb_bam_sps.sps_connections) { log_event_err("%s: failed to allocate sps_connections\n", diff --git a/drivers/platform/x86/mlxcpld-hotplug.c b/drivers/platform/x86/mlxcpld-hotplug.c index aff3686b3b37..c6fdd4e1d2c5 100644 --- a/drivers/platform/x86/mlxcpld-hotplug.c +++ b/drivers/platform/x86/mlxcpld-hotplug.c @@ -140,7 +140,8 @@ static int mlxcpld_hotplug_attr_init(struct mlxcpld_hotplug_priv_data *priv) priv->plat->fan_count; int i; - priv->group.attrs = devm_kzalloc(&priv->pdev->dev, num_attrs * + priv->group.attrs = devm_kcalloc(&priv->pdev->dev, + num_attrs, sizeof(struct attribute *), GFP_KERNEL); if (!priv->group.attrs) diff --git a/drivers/power/supply/charger-manager.c b/drivers/power/supply/charger-manager.c index f60dfc213257..d0ad8229133b 100644 --- a/drivers/power/supply/charger-manager.c +++ b/drivers/power/supply/charger-manager.c @@ -1379,7 +1379,7 @@ static int charger_manager_register_sysfs(struct charger_manager *cm) snprintf(buf, 10, "charger.%d", i); str = devm_kzalloc(cm->dev, - sizeof(char) * (strlen(buf) + 1), GFP_KERNEL); + strlen(buf) + 1, GFP_KERNEL); if (!str) return -ENOMEM; @@ -1521,8 +1521,10 @@ static struct charger_desc *of_cm_parse_desc(struct device *dev) of_property_read_u32(np, "cm-num-chargers", &num_chgs); if (num_chgs) { /* Allocate empty bin at the tail of array */ - desc->psy_charger_stat = devm_kzalloc(dev, sizeof(char *) - * (num_chgs + 1), GFP_KERNEL); + desc->psy_charger_stat = devm_kcalloc(dev, + num_chgs + 1, + sizeof(char *), + GFP_KERNEL); if (desc->psy_charger_stat) { int i; for (i = 0; i < num_chgs; i++) @@ -1554,8 +1556,9 @@ static struct charger_desc *of_cm_parse_desc(struct device *dev) struct charger_regulator *chg_regs; struct device_node *child; - chg_regs = devm_kzalloc(dev, sizeof(*chg_regs) - * desc->num_charger_regulators, + chg_regs = devm_kcalloc(dev, + desc->num_charger_regulators, + sizeof(*chg_regs), GFP_KERNEL); if (!chg_regs) return ERR_PTR(-ENOMEM); @@ -1572,9 +1575,10 @@ static struct charger_desc *of_cm_parse_desc(struct device *dev) /* charger cables */ chg_regs->num_cables = of_get_child_count(child); if (chg_regs->num_cables) { - cables = devm_kzalloc(dev, sizeof(*cables) - * chg_regs->num_cables, - GFP_KERNEL); + cables = devm_kcalloc(dev, + chg_regs->num_cables, + sizeof(*cables), + GFP_KERNEL); if (!cables) { of_node_put(child); return ERR_PTR(-ENOMEM); @@ -1723,10 +1727,10 @@ static int charger_manager_probe(struct platform_device *pdev) cm->charger_psy_desc.name = cm->psy_name_buf; /* Allocate for psy properties because they may vary */ - cm->charger_psy_desc.properties = devm_kzalloc(&pdev->dev, - sizeof(enum power_supply_property) - * (ARRAY_SIZE(default_charger_props) + - NUM_CHARGER_PSY_OPTIONAL), GFP_KERNEL); + cm->charger_psy_desc.properties = devm_kcalloc(&pdev->dev, + ARRAY_SIZE(default_charger_props) + NUM_CHARGER_PSY_OPTIONAL, + sizeof(enum power_supply_property), + GFP_KERNEL); if (!cm->charger_psy_desc.properties) return -ENOMEM; diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c index 4bcfcf67dcf6..ec0e1a26fc77 100644 --- a/drivers/power/supply/power_supply_core.c +++ b/drivers/power/supply/power_supply_core.c @@ -272,8 +272,8 @@ static int power_supply_check_supplies(struct power_supply *psy) if (!psy->supplied_from) return -ENOMEM; - *psy->supplied_from = devm_kzalloc(&psy->dev, - sizeof(char *) * (cnt - 1), + *psy->supplied_from = devm_kcalloc(&psy->dev, + cnt - 1, sizeof(char *), GFP_KERNEL); if (!*psy->supplied_from) return -ENOMEM; diff --git a/drivers/pwm/pwm-lp3943.c b/drivers/pwm/pwm-lp3943.c index 52584e9962ed..15b40a8bc4fb 100644 --- a/drivers/pwm/pwm-lp3943.c +++ b/drivers/pwm/pwm-lp3943.c @@ -225,7 +225,7 @@ static int lp3943_pwm_parse_dt(struct device *dev, if (num_outputs == 0) continue; - output = devm_kzalloc(dev, sizeof(*output) * num_outputs, + output = devm_kcalloc(dev, num_outputs, sizeof(*output), GFP_KERNEL); if (!output) return -ENOMEM; diff --git a/drivers/regulator/act8865-regulator.c b/drivers/regulator/act8865-regulator.c index 39e8d60df060..e0239cf3f56d 100644 --- a/drivers/regulator/act8865-regulator.c +++ b/drivers/regulator/act8865-regulator.c @@ -425,9 +425,10 @@ static int act8865_pdata_from_dt(struct device *dev, if (matched <= 0) return matched; - pdata->regulators = devm_kzalloc(dev, - sizeof(struct act8865_regulator_data) * - num_matches, GFP_KERNEL); + pdata->regulators = devm_kcalloc(dev, + num_matches, + sizeof(struct act8865_regulator_data), + GFP_KERNEL); if (!pdata->regulators) return -ENOMEM; diff --git a/drivers/regulator/as3711-regulator.c b/drivers/regulator/as3711-regulator.c index 874d415d6b4f..565a71343a8e 100644 --- a/drivers/regulator/as3711-regulator.c +++ b/drivers/regulator/as3711-regulator.c @@ -239,8 +239,10 @@ static int as3711_regulator_probe(struct platform_device *pdev) } } - regs = devm_kzalloc(&pdev->dev, AS3711_REGULATOR_NUM * - sizeof(struct as3711_regulator), GFP_KERNEL); + regs = devm_kcalloc(&pdev->dev, + AS3711_REGULATOR_NUM, + sizeof(struct as3711_regulator), + GFP_KERNEL); if (!regs) return -ENOMEM; diff --git a/drivers/regulator/bcm590xx-regulator.c b/drivers/regulator/bcm590xx-regulator.c index 9dd715407b39..92d6d7b10cf7 100644 --- a/drivers/regulator/bcm590xx-regulator.c +++ b/drivers/regulator/bcm590xx-regulator.c @@ -383,8 +383,10 @@ static int bcm590xx_probe(struct platform_device *pdev) platform_set_drvdata(pdev, pmu); - pmu->desc = devm_kzalloc(&pdev->dev, BCM590XX_NUM_REGS * - sizeof(struct regulator_desc), GFP_KERNEL); + pmu->desc = devm_kcalloc(&pdev->dev, + BCM590XX_NUM_REGS, + sizeof(struct regulator_desc), + GFP_KERNEL); if (!pmu->desc) return -ENOMEM; diff --git a/drivers/regulator/cpr-regulator.c b/drivers/regulator/cpr-regulator.c index 7c103991214d..210439c0a85e 100644 --- a/drivers/regulator/cpr-regulator.c +++ b/drivers/regulator/cpr-regulator.c @@ -1751,8 +1751,8 @@ static int cpr_config(struct cpr_regulator *cpr_vreg, struct device *dev) cpr_vreg->flags |= FLAGS_IGNORE_1ST_IRQ_STATUS; size = cpr_vreg->num_corners + 1; - cpr_vreg->save_ctl = devm_kzalloc(dev, sizeof(int) * size, GFP_KERNEL); - cpr_vreg->save_irq = devm_kzalloc(dev, sizeof(int) * size, GFP_KERNEL); + cpr_vreg->save_ctl = devm_kcalloc(dev, size, sizeof(int), GFP_KERNEL); + cpr_vreg->save_irq = devm_kcalloc(dev, size, sizeof(int), GFP_KERNEL); if (!cpr_vreg->save_ctl || !cpr_vreg->save_irq) return -ENOMEM; @@ -2118,9 +2118,9 @@ static int cpr_parse_vdd_mx_parameters(struct platform_device *pdev, return -EINVAL; } - cpr_vreg->vdd_mx_corner_map = devm_kzalloc(&pdev->dev, - (corner_map_len + 1) * sizeof(*cpr_vreg->vdd_mx_corner_map), - GFP_KERNEL); + cpr_vreg->vdd_mx_corner_map = devm_kcalloc(&pdev->dev, + corner_map_len + 1, sizeof(*cpr_vreg->vdd_mx_corner_map), + GFP_KERNEL); if (!cpr_vreg->vdd_mx_corner_map) return -ENOMEM; @@ -2369,8 +2369,8 @@ static int cpr_get_open_loop_voltage(struct cpr_regulator *cpr_vreg, u64 volt_high, volt_low, freq_high, freq_low, freq, temp, temp_limit; u32 *max_factor = NULL; - cpr_vreg->open_loop_volt = devm_kzalloc(dev, - sizeof(int) * (cpr_vreg->num_corners + 1), GFP_KERNEL); + cpr_vreg->open_loop_volt = devm_kcalloc(dev, + cpr_vreg->num_corners + 1, sizeof(int), GFP_KERNEL); if (!cpr_vreg->open_loop_volt) return -ENOMEM; @@ -2619,8 +2619,8 @@ static int cpr_get_fuse_quot_offset(struct cpr_regulator *cpr_vreg, return rc; } - cpr_vreg->fuse_quot_offset = devm_kzalloc(dev, - sizeof(u32) * (cpr_vreg->num_fuse_corners + 1), + cpr_vreg->fuse_quot_offset = devm_kcalloc(dev, + cpr_vreg->num_fuse_corners + 1, sizeof(u32), GFP_KERNEL); if (!cpr_vreg->fuse_quot_offset) { kfree(fuse_sel); @@ -2824,14 +2824,14 @@ static int cpr_get_corner_quot_adjustment(struct cpr_regulator *cpr_vreg, corners_mapped = false; } - cpr_vreg->corner_map = devm_kzalloc(dev, sizeof(int) * (size + 1), - GFP_KERNEL); + cpr_vreg->corner_map = devm_kcalloc(dev, size + 1, sizeof(int), + GFP_KERNEL); if (!cpr_vreg->corner_map) return -ENOMEM; cpr_vreg->num_corners = size; - cpr_vreg->quot_adjust = devm_kzalloc(dev, - sizeof(u32) * (cpr_vreg->num_corners + 1), + cpr_vreg->quot_adjust = devm_kcalloc(dev, + cpr_vreg->num_corners + 1, sizeof(u32), GFP_KERNEL); if (!cpr_vreg->quot_adjust) return -ENOMEM; @@ -4118,7 +4118,8 @@ static int cpr_init_cpr_voltages(struct cpr_regulator *cpr_vreg, int i; int size = cpr_vreg->num_corners + 1; - cpr_vreg->last_volt = devm_kzalloc(dev, sizeof(int) * size, GFP_KERNEL); + cpr_vreg->last_volt = devm_kcalloc(dev, size, sizeof(int), + GFP_KERNEL); if (!cpr_vreg->last_volt) return -EINVAL; @@ -4227,12 +4228,12 @@ static int cpr_init_ceiling_floor_override_voltages( int rc, i; int size = cpr_vreg->num_corners + 1; - cpr_vreg->ceiling_volt = devm_kzalloc(dev, sizeof(int) * size, + cpr_vreg->ceiling_volt = devm_kcalloc(dev, size, sizeof(int), GFP_KERNEL); - cpr_vreg->floor_volt = devm_kzalloc(dev, sizeof(int) * size, - GFP_KERNEL); - cpr_vreg->cpr_max_ceiling = devm_kzalloc(dev, sizeof(int) * size, + cpr_vreg->floor_volt = devm_kcalloc(dev, size, sizeof(int), GFP_KERNEL); + cpr_vreg->cpr_max_ceiling = devm_kcalloc(dev, size, sizeof(int), + GFP_KERNEL); if (!cpr_vreg->ceiling_volt || !cpr_vreg->floor_volt || !cpr_vreg->cpr_max_ceiling) return -ENOMEM; @@ -4586,9 +4587,10 @@ static int cpr_rpm_apc_init(struct platform_device *pdev, return -EINVAL; } - cpr_vreg->rpm_apc_corner_map = devm_kzalloc(&pdev->dev, - (cpr_vreg->num_corners + 1) * - sizeof(*cpr_vreg->rpm_apc_corner_map), GFP_KERNEL); + cpr_vreg->rpm_apc_corner_map = devm_kcalloc(&pdev->dev, + cpr_vreg->num_corners + 1, + sizeof(*cpr_vreg->rpm_apc_corner_map), + GFP_KERNEL); if (!cpr_vreg->rpm_apc_corner_map) return -ENOMEM; @@ -4845,8 +4847,8 @@ static int cpr_remap_efuse_data(struct platform_device *pdev, bits += temp[i * 4 + 2]; cpr_vreg->num_remapped_rows = DIV_ROUND_UP(bits, 64); - cpr_vreg->remapped_row = devm_kzalloc(&pdev->dev, - sizeof(*cpr_vreg->remapped_row) * cpr_vreg->num_remapped_rows, + cpr_vreg->remapped_row = devm_kcalloc(&pdev->dev, + cpr_vreg->num_remapped_rows, sizeof(*cpr_vreg->remapped_row), GFP_KERNEL); if (!cpr_vreg->remapped_row) { rc = -ENOMEM; @@ -5025,18 +5027,18 @@ static int cpr_fuse_corner_array_alloc(struct device *dev, */ len = cpr_vreg->num_fuse_corners + 1; - cpr_vreg->pvs_corner_v = devm_kzalloc(dev, - len * sizeof(*cpr_vreg->pvs_corner_v), GFP_KERNEL); - cpr_vreg->cpr_fuse_target_quot = devm_kzalloc(dev, - len * sizeof(*cpr_vreg->cpr_fuse_target_quot), GFP_KERNEL); - cpr_vreg->cpr_fuse_ro_sel = devm_kzalloc(dev, - len * sizeof(*cpr_vreg->cpr_fuse_ro_sel), GFP_KERNEL); - cpr_vreg->fuse_ceiling_volt = devm_kzalloc(dev, - len * (sizeof(*cpr_vreg->fuse_ceiling_volt)), GFP_KERNEL); - cpr_vreg->fuse_floor_volt = devm_kzalloc(dev, - len * (sizeof(*cpr_vreg->fuse_floor_volt)), GFP_KERNEL); - cpr_vreg->step_quotient = devm_kzalloc(dev, - len * sizeof(*cpr_vreg->step_quotient), GFP_KERNEL); + cpr_vreg->pvs_corner_v = devm_kcalloc(dev, + len, sizeof(*cpr_vreg->pvs_corner_v), GFP_KERNEL); + cpr_vreg->cpr_fuse_target_quot = devm_kcalloc(dev, + len, sizeof(*cpr_vreg->cpr_fuse_target_quot), GFP_KERNEL); + cpr_vreg->cpr_fuse_ro_sel = devm_kcalloc(dev, + len, sizeof(*cpr_vreg->cpr_fuse_ro_sel), GFP_KERNEL); + cpr_vreg->fuse_ceiling_volt = devm_kcalloc(dev, + len, sizeof(*cpr_vreg->fuse_ceiling_volt), GFP_KERNEL); + cpr_vreg->fuse_floor_volt = devm_kcalloc(dev, + len, sizeof(*cpr_vreg->fuse_floor_volt), GFP_KERNEL); + cpr_vreg->step_quotient = devm_kcalloc(dev, + len, sizeof(*cpr_vreg->step_quotient), GFP_KERNEL); if (cpr_vreg->pvs_corner_v == NULL || cpr_vreg->cpr_fuse_ro_sel == NULL || cpr_vreg->fuse_ceiling_volt == NULL @@ -5127,8 +5129,8 @@ static int cpr_mem_acc_init(struct platform_device *pdev, } size = prop->length / sizeof(u32); - cpr_vreg->mem_acc_corner_map = devm_kzalloc(&pdev->dev, - sizeof(int) * (size + 1), + cpr_vreg->mem_acc_corner_map = devm_kcalloc(&pdev->dev, + size + 1, sizeof(int), GFP_KERNEL); rc = of_property_read_u32_array(pdev->dev.of_node, corner_map_str, diff --git a/drivers/regulator/da9063-regulator.c b/drivers/regulator/da9063-regulator.c index 6a8f9cd69f52..2df26f36c687 100644 --- a/drivers/regulator/da9063-regulator.c +++ b/drivers/regulator/da9063-regulator.c @@ -681,8 +681,8 @@ static struct da9063_regulators_pdata *da9063_parse_regulators_dt( if (!pdata) return ERR_PTR(-ENOMEM); - pdata->regulator_data = devm_kzalloc(&pdev->dev, - num * sizeof(*pdata->regulator_data), + pdata->regulator_data = devm_kcalloc(&pdev->dev, + num, sizeof(*pdata->regulator_data), GFP_KERNEL); if (!pdata->regulator_data) return ERR_PTR(-ENOMEM); diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c index a2eb50719c7b..953966f5e84d 100644 --- a/drivers/regulator/gpio-regulator.c +++ b/drivers/regulator/gpio-regulator.c @@ -172,8 +172,8 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np, if (ret > 0) { config->nr_gpios = ret; - config->gpios = devm_kzalloc(dev, - sizeof(struct gpio) * config->nr_gpios, + config->gpios = devm_kcalloc(dev, + config->nr_gpios, sizeof(struct gpio), GFP_KERNEL); if (!config->gpios) return ERR_PTR(-ENOMEM); @@ -213,9 +213,9 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np, return ERR_PTR(-EINVAL); } - config->states = devm_kzalloc(dev, - sizeof(struct gpio_regulator_state) - * (proplen / 2), + config->states = devm_kcalloc(dev, + proplen / 2, + sizeof(struct gpio_regulator_state), GFP_KERNEL); if (!config->states) return ERR_PTR(-ENOMEM); diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c index 66bbaa999433..cc52779b53f7 100644 --- a/drivers/regulator/max1586.c +++ b/drivers/regulator/max1586.c @@ -194,8 +194,10 @@ static int of_get_max1586_platform_data(struct device *dev, if (matched <= 0) return matched; - pdata->subdevs = devm_kzalloc(dev, sizeof(struct max1586_subdev_data) * - matched, GFP_KERNEL); + pdata->subdevs = devm_kcalloc(dev, + matched, + sizeof(struct max1586_subdev_data), + GFP_KERNEL); if (!pdata->subdevs) return -ENOMEM; diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c index a6183425f27d..4cf6897a401f 100644 --- a/drivers/regulator/max8660.c +++ b/drivers/regulator/max8660.c @@ -351,8 +351,10 @@ static int max8660_pdata_from_dt(struct device *dev, if (matched <= 0) return matched; - pdata->subdevs = devm_kzalloc(dev, sizeof(struct max8660_subdev_data) * - matched, GFP_KERNEL); + pdata->subdevs = devm_kcalloc(dev, + matched, + sizeof(struct max8660_subdev_data), + GFP_KERNEL); if (!pdata->subdevs) return -ENOMEM; diff --git a/drivers/regulator/max8997-regulator.c b/drivers/regulator/max8997-regulator.c index 559b9ac45404..a8ea30ee18a6 100644 --- a/drivers/regulator/max8997-regulator.c +++ b/drivers/regulator/max8997-regulator.c @@ -929,8 +929,9 @@ static int max8997_pmic_dt_parse_pdata(struct platform_device *pdev, /* count the number of regulators to be supported in pmic */ pdata->num_regulators = of_get_child_count(regulators_np); - rdata = devm_kzalloc(&pdev->dev, sizeof(*rdata) * - pdata->num_regulators, GFP_KERNEL); + rdata = devm_kcalloc(&pdev->dev, + pdata->num_regulators, sizeof(*rdata), + GFP_KERNEL); if (!rdata) { of_node_put(regulators_np); return -ENOMEM; diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c index 3027e7ce100b..050082230ad0 100644 --- a/drivers/regulator/max8998.c +++ b/drivers/regulator/max8998.c @@ -671,8 +671,9 @@ static int max8998_pmic_dt_parse_pdata(struct max8998_dev *iodev, /* count the number of regulators to be supported in pmic */ pdata->num_regulators = of_get_child_count(regulators_np); - rdata = devm_kzalloc(iodev->dev, sizeof(*rdata) * - pdata->num_regulators, GFP_KERNEL); + rdata = devm_kcalloc(iodev->dev, + pdata->num_regulators, sizeof(*rdata), + GFP_KERNEL); if (!rdata) { of_node_put(regulators_np); return -ENOMEM; diff --git a/drivers/regulator/mc13xxx-regulator-core.c b/drivers/regulator/mc13xxx-regulator-core.c index 0281c31ae2ed..eb63b11330f0 100644 --- a/drivers/regulator/mc13xxx-regulator-core.c +++ b/drivers/regulator/mc13xxx-regulator-core.c @@ -175,7 +175,7 @@ struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt( if (!parent) return NULL; - data = devm_kzalloc(&pdev->dev, sizeof(*data) * priv->num_regulators, + data = devm_kcalloc(&pdev->dev, priv->num_regulators, sizeof(*data), GFP_KERNEL); if (!data) { of_node_put(parent); diff --git a/drivers/regulator/mem-acc-regulator.c b/drivers/regulator/mem-acc-regulator.c index ebe50c185481..30cff9373c26 100644 --- a/drivers/regulator/mem-acc-regulator.c +++ b/drivers/regulator/mem-acc-regulator.c @@ -334,8 +334,8 @@ static int __mem_acc_sel_init(struct mem_acc_regulator *mem_acc_vreg, int i; u32 bit, mask; - mem_acc_vreg->acc_sel_mask[mem_type] = devm_kzalloc(mem_acc_vreg->dev, - mem_acc_vreg->num_acc_sel[mem_type] * sizeof(u32), GFP_KERNEL); + mem_acc_vreg->acc_sel_mask[mem_type] = devm_kcalloc(mem_acc_vreg->dev, + mem_acc_vreg->num_acc_sel[mem_type], sizeof(u32), GFP_KERNEL); if (!mem_acc_vreg->acc_sel_mask[mem_type]) return -ENOMEM; @@ -396,7 +396,7 @@ static int populate_acc_data(struct mem_acc_regulator *mem_acc_vreg, return -EINVAL; } - *value = devm_kzalloc(mem_acc_vreg->dev, (*len) * sizeof(u32), + *value = devm_kcalloc(mem_acc_vreg->dev, *len, sizeof(u32), GFP_KERNEL); if (!(*value)) { pr_err("Unable to allocate memory for %s\n", prop_name); @@ -1403,9 +1403,11 @@ static int mem_acc_init(struct platform_device *pdev, return rc; } if (acc_type_present) { - mem_acc_vreg->mem_acc_type_data = devm_kzalloc( - mem_acc_vreg->dev, mem_acc_vreg->num_corners * - MEM_ACC_TYPE_MAX * sizeof(u32), GFP_KERNEL); + mem_acc_vreg->mem_acc_type_data = devm_kcalloc( + mem_acc_vreg->dev, + mem_acc_vreg->num_corners * MEM_ACC_TYPE_MAX, + sizeof(u32), + GFP_KERNEL); if (!mem_acc_vreg->mem_acc_type_data) { pr_err("Unable to allocate memory for mem_acc_type\n"); diff --git a/drivers/regulator/pbias-regulator.c b/drivers/regulator/pbias-regulator.c index 0cb76ba29e84..6fca1968869a 100644 --- a/drivers/regulator/pbias-regulator.c +++ b/drivers/regulator/pbias-regulator.c @@ -158,8 +158,9 @@ static int pbias_regulator_probe(struct platform_device *pdev) if (count < 0) return count; - drvdata = devm_kzalloc(&pdev->dev, sizeof(struct pbias_regulator_data) - * count, GFP_KERNEL); + drvdata = devm_kcalloc(&pdev->dev, + count, sizeof(struct pbias_regulator_data), + GFP_KERNEL); if (!drvdata) return -ENOMEM; diff --git a/drivers/regulator/rc5t583-regulator.c b/drivers/regulator/rc5t583-regulator.c index d0f1340168b1..2ec51af43673 100644 --- a/drivers/regulator/rc5t583-regulator.c +++ b/drivers/regulator/rc5t583-regulator.c @@ -132,8 +132,10 @@ static int rc5t583_regulator_probe(struct platform_device *pdev) return -ENODEV; } - regs = devm_kzalloc(&pdev->dev, RC5T583_REGULATOR_MAX * - sizeof(struct rc5t583_regulator), GFP_KERNEL); + regs = devm_kcalloc(&pdev->dev, + RC5T583_REGULATOR_MAX, + sizeof(struct rc5t583_regulator), + GFP_KERNEL); if (!regs) return -ENOMEM; diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index 4836947e1521..ad94489aaf23 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c @@ -553,13 +553,15 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev, /* count the number of regulators to be supported in pmic */ pdata->num_regulators = of_get_child_count(regulators_np); - rdata = devm_kzalloc(&pdev->dev, sizeof(*rdata) * - pdata->num_regulators, GFP_KERNEL); + rdata = devm_kcalloc(&pdev->dev, + pdata->num_regulators, sizeof(*rdata), + GFP_KERNEL); if (!rdata) return -ENOMEM; - rmode = devm_kzalloc(&pdev->dev, sizeof(*rmode) * - pdata->num_regulators, GFP_KERNEL); + rmode = devm_kcalloc(&pdev->dev, + pdata->num_regulators, sizeof(*rmode), + GFP_KERNEL); if (!rmode) return -ENOMEM; diff --git a/drivers/regulator/ti-abb-regulator.c b/drivers/regulator/ti-abb-regulator.c index 6d17357b3a24..89b9314d64c9 100644 --- a/drivers/regulator/ti-abb-regulator.c +++ b/drivers/regulator/ti-abb-regulator.c @@ -522,13 +522,13 @@ static int ti_abb_init_table(struct device *dev, struct ti_abb *abb, } num_entries /= num_values; - info = devm_kzalloc(dev, sizeof(*info) * num_entries, GFP_KERNEL); + info = devm_kcalloc(dev, num_entries, sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; abb->info = info; - volt_table = devm_kzalloc(dev, sizeof(unsigned int) * num_entries, + volt_table = devm_kcalloc(dev, num_entries, sizeof(unsigned int), GFP_KERNEL); if (!volt_table) return -ENOMEM; diff --git a/drivers/regulator/tps65090-regulator.c b/drivers/regulator/tps65090-regulator.c index 395f35dc8cdb..42a6cea64104 100644 --- a/drivers/regulator/tps65090-regulator.c +++ b/drivers/regulator/tps65090-regulator.c @@ -351,8 +351,9 @@ static struct tps65090_platform_data *tps65090_parse_dt_reg_data( if (!tps65090_pdata) return ERR_PTR(-ENOMEM); - reg_pdata = devm_kzalloc(&pdev->dev, TPS65090_REGULATOR_MAX * - sizeof(*reg_pdata), GFP_KERNEL); + reg_pdata = devm_kcalloc(&pdev->dev, + TPS65090_REGULATOR_MAX, sizeof(*reg_pdata), + GFP_KERNEL); if (!reg_pdata) return ERR_PTR(-ENOMEM); @@ -432,8 +433,9 @@ static int tps65090_regulator_probe(struct platform_device *pdev) return tps65090_pdata ? PTR_ERR(tps65090_pdata) : -EINVAL; } - pmic = devm_kzalloc(&pdev->dev, TPS65090_REGULATOR_MAX * sizeof(*pmic), - GFP_KERNEL); + pmic = devm_kcalloc(&pdev->dev, + TPS65090_REGULATOR_MAX, sizeof(*pmic), + GFP_KERNEL); if (!pmic) return -ENOMEM; diff --git a/drivers/regulator/tps65217-regulator.c b/drivers/regulator/tps65217-regulator.c index 5324dc9e6d6e..77247e4d52b3 100644 --- a/drivers/regulator/tps65217-regulator.c +++ b/drivers/regulator/tps65217-regulator.c @@ -234,8 +234,9 @@ static int tps65217_regulator_probe(struct platform_device *pdev) } /* Allocate memory for strobes */ - tps->strobes = devm_kzalloc(&pdev->dev, sizeof(u8) * - TPS65217_NUM_REGULATOR, GFP_KERNEL); + tps->strobes = devm_kcalloc(&pdev->dev, + TPS65217_NUM_REGULATOR, sizeof(u8), + GFP_KERNEL); platform_set_drvdata(pdev, tps); diff --git a/drivers/regulator/tps65218-regulator.c b/drivers/regulator/tps65218-regulator.c index 9aafbb03482d..e5917ad4e5e3 100644 --- a/drivers/regulator/tps65218-regulator.c +++ b/drivers/regulator/tps65218-regulator.c @@ -327,8 +327,9 @@ static int tps65218_regulator_probe(struct platform_device *pdev) config.regmap = tps->regmap; /* Allocate memory for strobes */ - tps->strobes = devm_kzalloc(&pdev->dev, sizeof(u8) * - TPS65218_NUM_REGULATOR, GFP_KERNEL); + tps->strobes = devm_kcalloc(&pdev->dev, + TPS65218_NUM_REGULATOR, sizeof(u8), + GFP_KERNEL); for (i = 0; i < ARRAY_SIZE(regulators); i++) { rdev = devm_regulator_register(&pdev->dev, ®ulators[i], diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c index 194fa0cbbc04..5ebb6ee73f07 100644 --- a/drivers/regulator/tps65910-regulator.c +++ b/drivers/regulator/tps65910-regulator.c @@ -1133,18 +1133,24 @@ static int tps65910_probe(struct platform_device *pdev) return -ENODEV; } - pmic->desc = devm_kzalloc(&pdev->dev, pmic->num_regulators * - sizeof(struct regulator_desc), GFP_KERNEL); + pmic->desc = devm_kcalloc(&pdev->dev, + pmic->num_regulators, + sizeof(struct regulator_desc), + GFP_KERNEL); if (!pmic->desc) return -ENOMEM; - pmic->info = devm_kzalloc(&pdev->dev, pmic->num_regulators * - sizeof(struct tps_info *), GFP_KERNEL); + pmic->info = devm_kcalloc(&pdev->dev, + pmic->num_regulators, + sizeof(struct tps_info *), + GFP_KERNEL); if (!pmic->info) return -ENOMEM; - pmic->rdev = devm_kzalloc(&pdev->dev, pmic->num_regulators * - sizeof(struct regulator_dev *), GFP_KERNEL); + pmic->rdev = devm_kcalloc(&pdev->dev, + pmic->num_regulators, + sizeof(struct regulator_dev *), + GFP_KERNEL); if (!pmic->rdev) return -ENOMEM; diff --git a/drivers/regulator/tps80031-regulator.c b/drivers/regulator/tps80031-regulator.c index d4cc60ad18ae..1001147404c3 100644 --- a/drivers/regulator/tps80031-regulator.c +++ b/drivers/regulator/tps80031-regulator.c @@ -691,8 +691,8 @@ static int tps80031_regulator_probe(struct platform_device *pdev) return -EINVAL; } - pmic = devm_kzalloc(&pdev->dev, - TPS80031_REGULATOR_MAX * sizeof(*pmic), GFP_KERNEL); + pmic = devm_kcalloc(&pdev->dev, + TPS80031_REGULATOR_MAX, sizeof(*pmic), GFP_KERNEL); if (!pmic) return -ENOMEM; diff --git a/drivers/reset/reset-ti-syscon.c b/drivers/reset/reset-ti-syscon.c index 99520b0a1329..a2635c21db7f 100644 --- a/drivers/reset/reset-ti-syscon.c +++ b/drivers/reset/reset-ti-syscon.c @@ -189,7 +189,8 @@ static int ti_syscon_reset_probe(struct platform_device *pdev) } nr_controls = (size / sizeof(*list)) / 7; - controls = devm_kzalloc(dev, nr_controls * sizeof(*controls), GFP_KERNEL); + controls = devm_kcalloc(dev, nr_controls, sizeof(*controls), + GFP_KERNEL); if (!controls) return -ENOMEM; diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index c71e0f3b146a..c1bdcac3fea6 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -232,14 +232,14 @@ static int isci_register_sas_ha(struct isci_host *isci_host) struct asd_sas_phy **sas_phys; struct asd_sas_port **sas_ports; - sas_phys = devm_kzalloc(&isci_host->pdev->dev, - SCI_MAX_PHYS * sizeof(void *), + sas_phys = devm_kcalloc(&isci_host->pdev->dev, + SCI_MAX_PHYS, sizeof(void *), GFP_KERNEL); if (!sas_phys) return -ENOMEM; - sas_ports = devm_kzalloc(&isci_host->pdev->dev, - SCI_MAX_PORTS * sizeof(void *), + sas_ports = devm_kcalloc(&isci_host->pdev->dev, + SCI_MAX_PORTS, sizeof(void *), GFP_KERNEL); if (!sas_ports) return -ENOMEM; diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c index 63c5c7b8cd78..e7b6fd0df2c1 100644 --- a/drivers/scsi/ufs/ufshcd-pltfrm.c +++ b/drivers/scsi/ufs/ufshcd-pltfrm.c @@ -102,8 +102,8 @@ static int ufshcd_parse_clock_info(struct ufs_hba *hba) goto out; } - clkfreq = devm_kzalloc(dev, sz * sizeof(*clkfreq), - GFP_KERNEL); + clkfreq = devm_kcalloc(dev, sz, sizeof(*clkfreq), + GFP_KERNEL); if (!clkfreq) { ret = -ENOMEM; goto out; diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index bce6a4175eab..d587fcd7e3a2 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -4883,8 +4883,8 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba) } /* Allocate memory for local reference block */ - hba->lrb = devm_kzalloc(hba->dev, - hba->nutrs * sizeof(struct ufshcd_lrb), + hba->lrb = devm_kcalloc(hba->dev, + hba->nutrs, sizeof(struct ufshcd_lrb), GFP_KERNEL); if (!hba->lrb) { dev_err(hba->dev, "LRB Memory allocation failed\n"); diff --git a/drivers/soc/bcm/raspberrypi-power.c b/drivers/soc/bcm/raspberrypi-power.c index f7ed1187518b..a78dfe0a2b50 100644 --- a/drivers/soc/bcm/raspberrypi-power.c +++ b/drivers/soc/bcm/raspberrypi-power.c @@ -165,8 +165,10 @@ static int rpi_power_probe(struct platform_device *pdev) return -ENOMEM; rpi_domains->xlate.domains = - devm_kzalloc(dev, sizeof(*rpi_domains->xlate.domains) * - RPI_POWER_DOMAIN_COUNT, GFP_KERNEL); + devm_kcalloc(dev, + RPI_POWER_DOMAIN_COUNT, + sizeof(*rpi_domains->xlate.domains), + GFP_KERNEL); if (!rpi_domains->xlate.domains) return -ENOMEM; diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c index fb2a8b1e7979..b0cb5214f659 100644 --- a/drivers/soc/mediatek/mtk-scpsys.c +++ b/drivers/soc/mediatek/mtk-scpsys.c @@ -404,15 +404,15 @@ static struct scp *init_scp(struct platform_device *pdev, if (IS_ERR(scp->base)) return ERR_CAST(scp->base); - scp->domains = devm_kzalloc(&pdev->dev, - sizeof(*scp->domains) * num, GFP_KERNEL); + scp->domains = devm_kcalloc(&pdev->dev, + num, sizeof(*scp->domains), GFP_KERNEL); if (!scp->domains) return ERR_PTR(-ENOMEM); pd_data = &scp->pd_data; - pd_data->domains = devm_kzalloc(&pdev->dev, - sizeof(*pd_data->domains) * num, GFP_KERNEL); + pd_data->domains = devm_kcalloc(&pdev->dev, + num, sizeof(*pd_data->domains), GFP_KERNEL); if (!pd_data->domains) return ERR_PTR(-ENOMEM); diff --git a/drivers/soc/qcom/gladiator_hang_detect.c b/drivers/soc/qcom/gladiator_hang_detect.c index 4d1f601f204c..4b9bc793ecf1 100644 --- a/drivers/soc/qcom/gladiator_hang_detect.c +++ b/drivers/soc/qcom/gladiator_hang_detect.c @@ -517,15 +517,15 @@ static int msm_gladiator_hang_detect_probe(struct platform_device *pdev) hang_attr_group.attrs = hang_attrs_v3; } - hang_det->threshold = devm_kzalloc(&pdev->dev, - sizeof(phys_addr_t)*NR_GLA_REG, GFP_KERNEL); + hang_det->threshold = devm_kcalloc(&pdev->dev, + NR_GLA_REG, sizeof(phys_addr_t), GFP_KERNEL); if (!hang_det->threshold) { pr_err("Can't allocate hang_detect threshold memory\n"); return -ENOMEM; } - treg = devm_kzalloc(&pdev->dev, sizeof(u32)*NR_GLA_REG, GFP_KERNEL); + treg = devm_kcalloc(&pdev->dev, NR_GLA_REG, sizeof(u32), GFP_KERNEL); if (!treg) return -ENOMEM; diff --git a/drivers/soc/qcom/glink_pkt.c b/drivers/soc/qcom/glink_pkt.c index 376ff9f62efd..2378a5a3c9f9 100644 --- a/drivers/soc/qcom/glink_pkt.c +++ b/drivers/soc/qcom/glink_pkt.c @@ -680,7 +680,7 @@ static int glink_pkt_init_rpmsg(struct glink_pkt_device *gpdev) char *drv_name; /* zalloc array of two to NULL terminate the match list */ - match = devm_kzalloc(dev, 2 * sizeof(*match), GFP_KERNEL); + match = devm_kcalloc(dev, 2, sizeof(*match), GFP_KERNEL); if (!match) return -ENOMEM; snprintf(match->name, RPMSG_NAME_SIZE, "%s", gpdev->ch_name); diff --git a/drivers/soc/qcom/jtagv8-etm.c b/drivers/soc/qcom/jtagv8-etm.c index a3080251aaf8..d16a776076d4 100644 --- a/drivers/soc/qcom/jtagv8-etm.c +++ b/drivers/soc/qcom/jtagv8-etm.c @@ -1619,8 +1619,8 @@ static int jtag_mm_etm_probe(struct platform_device *pdev, uint32_t cpu) etmdata->save_restore_disabled = 1; /* Allocate etm state save space per core */ - etmdata->state = devm_kzalloc(dev, - MAX_ETM_STATE_SIZE * sizeof(uint64_t), + etmdata->state = devm_kcalloc(dev, + MAX_ETM_STATE_SIZE, sizeof(uint64_t), GFP_KERNEL); if (!etmdata->state) return -ENOMEM; diff --git a/drivers/soc/qcom/msm_bus/msm_bus_arb_adhoc.c b/drivers/soc/qcom/msm_bus/msm_bus_arb_adhoc.c index 731fa98d9ee8..3e4ce8efc515 100644 --- a/drivers/soc/qcom/msm_bus/msm_bus_arb_adhoc.c +++ b/drivers/soc/qcom/msm_bus/msm_bus_arb_adhoc.c @@ -127,9 +127,9 @@ static int gen_lnode(struct device *dev, } if (!cur_dev->num_lnodes) { - cur_dev->lnode_list = devm_kzalloc(dev, - sizeof(struct link_node) * NUM_LNODES, - GFP_KERNEL); + cur_dev->lnode_list = devm_kcalloc(dev, + NUM_LNODES, sizeof(struct link_node), + GFP_KERNEL); if (!cur_dev->lnode_list) goto exit_gen_lnode; diff --git a/drivers/soc/qcom/msm_bus/msm_bus_arb_rpmh.c b/drivers/soc/qcom/msm_bus/msm_bus_arb_rpmh.c index a64a294e0e8c..ed62bf25d145 100644 --- a/drivers/soc/qcom/msm_bus/msm_bus_arb_rpmh.c +++ b/drivers/soc/qcom/msm_bus/msm_bus_arb_rpmh.c @@ -140,9 +140,9 @@ static void bcm_add_bus_req(struct device *dev) bcm_dev = to_msm_bus_node(cur_dev->node_info->bcm_devs[i]); max_num_lnodes = bcm_dev->bcmdev->num_bus_devs; if (!bcm_dev->num_lnodes) { - bcm_dev->lnode_list = devm_kzalloc(dev, - sizeof(struct link_node) * max_num_lnodes, - GFP_KERNEL); + bcm_dev->lnode_list = devm_kcalloc(dev, + max_num_lnodes, sizeof(struct link_node), + GFP_KERNEL); if (!bcm_dev->lnode_list) goto exit_bcm_add_bus_req; @@ -211,9 +211,9 @@ static int gen_lnode(struct device *dev, } if (!cur_dev->num_lnodes) { - cur_dev->lnode_list = devm_kzalloc(dev, - sizeof(struct link_node) * NUM_LNODES, - GFP_KERNEL); + cur_dev->lnode_list = devm_kcalloc(dev, + NUM_LNODES, sizeof(struct link_node), + GFP_KERNEL); if (!cur_dev->lnode_list) goto exit_gen_lnode; diff --git a/drivers/soc/qcom/msm_bus/msm_bus_fabric_adhoc.c b/drivers/soc/qcom/msm_bus/msm_bus_fabric_adhoc.c index c214e384f53c..6ba06875c869 100644 --- a/drivers/soc/qcom/msm_bus/msm_bus_fabric_adhoc.c +++ b/drivers/soc/qcom/msm_bus/msm_bus_fabric_adhoc.c @@ -919,9 +919,9 @@ static int msm_bus_copy_node_info(struct msm_bus_node_device_type *pdata, pdata_node_info->agg_params.num_aggports; node_info->agg_params.num_util_levels = pdata_node_info->agg_params.num_util_levels; - node_info->agg_params.util_levels = devm_kzalloc(bus_dev, - sizeof(struct node_util_levels_type) * + node_info->agg_params.util_levels = devm_kcalloc(bus_dev, node_info->agg_params.num_util_levels, + sizeof(struct node_util_levels_type), GFP_KERNEL); if (!node_info->agg_params.util_levels) { MSM_BUS_ERR("%s: Agg util level alloc failed\n", __func__); @@ -933,9 +933,9 @@ static int msm_bus_copy_node_info(struct msm_bus_node_device_type *pdata, sizeof(struct node_util_levels_type) * pdata_node_info->agg_params.num_util_levels); - node_info->dev_connections = devm_kzalloc(bus_dev, - sizeof(struct device *) * - pdata_node_info->num_connections, + node_info->dev_connections = devm_kcalloc(bus_dev, + pdata_node_info->num_connections, + sizeof(struct device *), GFP_KERNEL); if (!node_info->dev_connections) { MSM_BUS_ERR("%s:Bus dev connections alloc failed\n", __func__); @@ -943,8 +943,8 @@ static int msm_bus_copy_node_info(struct msm_bus_node_device_type *pdata, goto exit_copy_node_info; } - node_info->connections = devm_kzalloc(bus_dev, - sizeof(int) * pdata_node_info->num_connections, + node_info->connections = devm_kcalloc(bus_dev, + pdata_node_info->num_connections, sizeof(int), GFP_KERNEL); if (!node_info->connections) { MSM_BUS_ERR("%s:Bus connections alloc failed\n", __func__); @@ -957,9 +957,8 @@ static int msm_bus_copy_node_info(struct msm_bus_node_device_type *pdata, pdata_node_info->connections, sizeof(int) * pdata_node_info->num_connections); - node_info->black_connections = devm_kzalloc(bus_dev, - sizeof(struct device *) * - pdata_node_info->num_blist, + node_info->black_connections = devm_kcalloc(bus_dev, + pdata_node_info->num_blist, sizeof(struct device *), GFP_KERNEL); if (!node_info->black_connections) { MSM_BUS_ERR("%s: Bus black connections alloc failed\n", @@ -970,8 +969,8 @@ static int msm_bus_copy_node_info(struct msm_bus_node_device_type *pdata, goto exit_copy_node_info; } - node_info->bl_cons = devm_kzalloc(bus_dev, - pdata_node_info->num_blist * sizeof(int), + node_info->bl_cons = devm_kcalloc(bus_dev, + pdata_node_info->num_blist, sizeof(int), GFP_KERNEL); if (!node_info->bl_cons) { MSM_BUS_ERR("%s:Bus black list connections alloc failed\n", @@ -987,8 +986,8 @@ static int msm_bus_copy_node_info(struct msm_bus_node_device_type *pdata, pdata_node_info->bl_cons, sizeof(int) * pdata_node_info->num_blist); - node_info->qport = devm_kzalloc(bus_dev, - sizeof(int) * pdata_node_info->num_qports, + node_info->qport = devm_kcalloc(bus_dev, + pdata_node_info->num_qports, sizeof(int), GFP_KERNEL); if (!node_info->qport) { MSM_BUS_ERR("%s:Bus qport allocation failed\n", __func__); diff --git a/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c b/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c index 708713f92762..2bbe261c89e3 100644 --- a/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c +++ b/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c @@ -1384,8 +1384,8 @@ static int msm_bus_copy_node_info(struct msm_bus_node_device_type *pdata, node_info->name = pdata_node_info->name; node_info->id = pdata_node_info->id; - node_info->bcm_req_idx = devm_kzalloc(bus_dev, - sizeof(int) * pdata_node_info->num_bcm_devs, + node_info->bcm_req_idx = devm_kcalloc(bus_dev, + pdata_node_info->num_bcm_devs, sizeof(int), GFP_KERNEL); if (!node_info->bcm_req_idx) { ret = -ENOMEM; @@ -1441,9 +1441,9 @@ static int msm_bus_copy_node_info(struct msm_bus_node_device_type *pdata, pdata_node_info->agg_params.num_aggports; node_info->agg_params.num_util_levels = pdata_node_info->agg_params.num_util_levels; - node_info->agg_params.util_levels = devm_kzalloc(bus_dev, - sizeof(struct node_util_levels_type) * + node_info->agg_params.util_levels = devm_kcalloc(bus_dev, node_info->agg_params.num_util_levels, + sizeof(struct node_util_levels_type), GFP_KERNEL); if (!node_info->agg_params.util_levels) { MSM_BUS_ERR("%s: Agg util level alloc failed\n", __func__); @@ -1455,9 +1455,9 @@ static int msm_bus_copy_node_info(struct msm_bus_node_device_type *pdata, sizeof(struct node_util_levels_type) * pdata_node_info->agg_params.num_util_levels); - node_info->dev_connections = devm_kzalloc(bus_dev, - sizeof(struct device *) * - pdata_node_info->num_connections, + node_info->dev_connections = devm_kcalloc(bus_dev, + pdata_node_info->num_connections, + sizeof(struct device *), GFP_KERNEL); if (!node_info->dev_connections) { MSM_BUS_ERR("%s:Bus dev connections alloc failed\n", __func__); @@ -1465,8 +1465,8 @@ static int msm_bus_copy_node_info(struct msm_bus_node_device_type *pdata, goto exit_copy_node_info; } - node_info->connections = devm_kzalloc(bus_dev, - sizeof(int) * pdata_node_info->num_connections, + node_info->connections = devm_kcalloc(bus_dev, + pdata_node_info->num_connections, sizeof(int), GFP_KERNEL); if (!node_info->connections) { MSM_BUS_ERR("%s:Bus connections alloc failed\n", __func__); @@ -1479,9 +1479,8 @@ static int msm_bus_copy_node_info(struct msm_bus_node_device_type *pdata, pdata_node_info->connections, sizeof(int) * pdata_node_info->num_connections); - node_info->black_connections = devm_kzalloc(bus_dev, - sizeof(struct device *) * - pdata_node_info->num_blist, + node_info->black_connections = devm_kcalloc(bus_dev, + pdata_node_info->num_blist, sizeof(struct device *), GFP_KERNEL); if (!node_info->black_connections) { MSM_BUS_ERR("%s: Bus black connections alloc failed\n", @@ -1492,8 +1491,8 @@ static int msm_bus_copy_node_info(struct msm_bus_node_device_type *pdata, goto exit_copy_node_info; } - node_info->bl_cons = devm_kzalloc(bus_dev, - pdata_node_info->num_blist * sizeof(int), + node_info->bl_cons = devm_kcalloc(bus_dev, + pdata_node_info->num_blist, sizeof(int), GFP_KERNEL); if (!node_info->bl_cons) { MSM_BUS_ERR("%s:Bus black list connections alloc failed\n", @@ -1509,9 +1508,9 @@ static int msm_bus_copy_node_info(struct msm_bus_node_device_type *pdata, pdata_node_info->bl_cons, sizeof(int) * pdata_node_info->num_blist); - node_info->bcm_devs = devm_kzalloc(bus_dev, - sizeof(struct device *) * - pdata_node_info->num_bcm_devs, + node_info->bcm_devs = devm_kcalloc(bus_dev, + pdata_node_info->num_bcm_devs, + sizeof(struct device *), GFP_KERNEL); if (!node_info->bcm_devs) { MSM_BUS_ERR("%s:Bcm dev connections alloc failed\n", __func__); @@ -1519,8 +1518,8 @@ static int msm_bus_copy_node_info(struct msm_bus_node_device_type *pdata, goto exit_copy_node_info; } - node_info->bcm_dev_ids = devm_kzalloc(bus_dev, - sizeof(int) * pdata_node_info->num_bcm_devs, + node_info->bcm_dev_ids = devm_kcalloc(bus_dev, + pdata_node_info->num_bcm_devs, sizeof(int), GFP_KERNEL); if (!node_info->bcm_dev_ids) { MSM_BUS_ERR("%s:Bus connections alloc failed\n", __func__); @@ -1533,9 +1532,9 @@ static int msm_bus_copy_node_info(struct msm_bus_node_device_type *pdata, pdata_node_info->bcm_dev_ids, sizeof(int) * pdata_node_info->num_bcm_devs); - node_info->rsc_devs = devm_kzalloc(bus_dev, - sizeof(struct device *) * - pdata_node_info->num_rsc_devs, + node_info->rsc_devs = devm_kcalloc(bus_dev, + pdata_node_info->num_rsc_devs, + sizeof(struct device *), GFP_KERNEL); if (!node_info->rsc_devs) { MSM_BUS_ERR("%s:rsc dev connections alloc failed\n", __func__); @@ -1543,8 +1542,8 @@ static int msm_bus_copy_node_info(struct msm_bus_node_device_type *pdata, goto exit_copy_node_info; } - node_info->rsc_dev_ids = devm_kzalloc(bus_dev, - sizeof(int) * pdata_node_info->num_rsc_devs, + node_info->rsc_dev_ids = devm_kcalloc(bus_dev, + pdata_node_info->num_rsc_devs, sizeof(int), GFP_KERNEL); if (!node_info->rsc_dev_ids) { MSM_BUS_ERR("%s:Bus connections alloc failed\n", __func__); @@ -1557,8 +1556,8 @@ static int msm_bus_copy_node_info(struct msm_bus_node_device_type *pdata, pdata_node_info->rsc_dev_ids, sizeof(int) * pdata_node_info->num_rsc_devs); - node_info->qport = devm_kzalloc(bus_dev, - sizeof(int) * pdata_node_info->num_qports, + node_info->qport = devm_kcalloc(bus_dev, + pdata_node_info->num_qports, sizeof(int), GFP_KERNEL); if (!node_info->qport) { MSM_BUS_ERR("%s:Bus qport allocation failed\n", __func__); diff --git a/drivers/soc/qcom/msm_bus/msm_bus_of.c b/drivers/soc/qcom/msm_bus/msm_bus_of.c index f24bc92f16bf..f7ade63aca43 100644 --- a/drivers/soc/qcom/msm_bus/msm_bus_of.c +++ b/drivers/soc/qcom/msm_bus/msm_bus_of.c @@ -149,8 +149,10 @@ static struct msm_bus_scale_pdata *get_pdata(struct device *dev, for (i = 0; i < num_usecases; i++) { usecase[i].num_paths = num_paths; - usecase[i].vectors = devm_kzalloc(dev, num_paths * - sizeof(struct msm_bus_vectors), GFP_KERNEL); + usecase[i].vectors = devm_kcalloc(dev, + num_paths, + sizeof(struct msm_bus_vectors), + GFP_KERNEL); if (!usecase[i].vectors) { mem_err = true; pr_err("Error: Mem alloc failure in vectors\n"); @@ -415,8 +417,9 @@ static struct msm_bus_node_info *get_nodes(struct device_node *of_node, pdata->len = i; info = (struct msm_bus_node_info *) - devm_kzalloc(&pdev->dev, sizeof(struct msm_bus_node_info) * - pdata->len, GFP_KERNEL); + devm_kcalloc(&pdev->dev, + pdata->len, sizeof(struct msm_bus_node_info), + GFP_KERNEL); if (ZERO_OR_NULL_PTR(info)) { pr_err("Failed to alloc memory for nodes: %d\n", pdata->len); goto err; diff --git a/drivers/soc/qcom/msm_bus/msm_bus_of_adhoc.c b/drivers/soc/qcom/msm_bus/msm_bus_of_adhoc.c index 34a0c5ce0b60..98ec7d726393 100644 --- a/drivers/soc/qcom/msm_bus/msm_bus_of_adhoc.c +++ b/drivers/soc/qcom/msm_bus/msm_bus_of_adhoc.c @@ -714,9 +714,10 @@ struct msm_bus_device_node_registration pdata->num_devices = of_get_child_count(of_node); - pdata->info = devm_kzalloc(&pdev->dev, - sizeof(struct msm_bus_node_device_type) * - pdata->num_devices, GFP_KERNEL); + pdata->info = devm_kcalloc(&pdev->dev, + pdata->num_devices, + sizeof(struct msm_bus_node_device_type), + GFP_KERNEL); if (!pdata->info) goto node_reg_err; @@ -824,8 +825,8 @@ int msm_bus_of_get_static_rules(struct platform_device *pdev, of_node = pdev->dev.of_node; num_rules = of_get_child_count(of_node); - local_rule = devm_kzalloc(&pdev->dev, - sizeof(struct bus_rule_type) * num_rules, + local_rule = devm_kcalloc(&pdev->dev, + num_rules, sizeof(struct bus_rule_type), GFP_KERNEL); if (IS_ERR_OR_NULL(local_rule)) { diff --git a/drivers/soc/qcom/msm_bus/msm_bus_of_rpmh.c b/drivers/soc/qcom/msm_bus/msm_bus_of_rpmh.c index a97a44c3cd28..7568353f51ca 100644 --- a/drivers/soc/qcom/msm_bus/msm_bus_of_rpmh.c +++ b/drivers/soc/qcom/msm_bus/msm_bus_of_rpmh.c @@ -754,9 +754,10 @@ struct msm_bus_device_node_registration pdata->num_devices = of_get_child_count(of_node); - pdata->info = devm_kzalloc(&pdev->dev, - sizeof(struct msm_bus_node_device_type) * - pdata->num_devices, GFP_KERNEL); + pdata->info = devm_kcalloc(&pdev->dev, + pdata->num_devices, + sizeof(struct msm_bus_node_device_type), + GFP_KERNEL); if (!pdata->info) { dev_err(&pdev->dev, @@ -869,8 +870,8 @@ int msm_bus_of_get_static_rules(struct platform_device *pdev, of_node = pdev->dev.of_node; num_rules = of_get_child_count(of_node); - local_rule = devm_kzalloc(&pdev->dev, - sizeof(struct bus_rule_type) * num_rules, + local_rule = devm_kcalloc(&pdev->dev, + num_rules, sizeof(struct bus_rule_type), GFP_KERNEL); if (IS_ERR_OR_NULL(local_rule)) { diff --git a/drivers/soc/qcom/qsee_ipc_irq.c b/drivers/soc/qcom/qsee_ipc_irq.c index 38a90e640835..f586fa0fe2bc 100644 --- a/drivers/soc/qcom/qsee_ipc_irq.c +++ b/drivers/soc/qcom/qsee_ipc_irq.c @@ -267,7 +267,7 @@ static int qsee_irq_probe(struct platform_device *pdev) return -ENODEV; irq_count = platform_irq_count(pdev); - qirq->banks = devm_kzalloc(dev, sizeof(*qirq->banks) * irq_count, + qirq->banks = devm_kcalloc(dev, irq_count, sizeof(*qirq->banks), GFP_KERNEL); if (!qirq->banks) return -ENOMEM; diff --git a/drivers/soc/qcom/rpm_master_stat.c b/drivers/soc/qcom/rpm_master_stat.c index 1cbf2a1dbc02..ccd11684dfe7 100644 --- a/drivers/soc/qcom/rpm_master_stat.c +++ b/drivers/soc/qcom/rpm_master_stat.c @@ -398,7 +398,9 @@ static struct msm_rpm_master_stats_platform_data goto err; } - pdata->masters = devm_kzalloc(dev, sizeof(char *) * pdata->num_masters, + pdata->masters = devm_kcalloc(dev, + pdata->num_masters, + sizeof(char *), GFP_KERNEL); if (!pdata->masters) goto err; diff --git a/drivers/soc/qcom/subsys-pil-tz.c b/drivers/soc/qcom/subsys-pil-tz.c index e267ceadf41a..322ad9550757 100644 --- a/drivers/soc/qcom/subsys-pil-tz.c +++ b/drivers/soc/qcom/subsys-pil-tz.c @@ -238,7 +238,7 @@ static int of_read_clocks(struct device *dev, struct clk ***clks_ref, return -EINVAL; } - clks = devm_kzalloc(dev, sizeof(struct clk *) * clk_count, + clks = devm_kcalloc(dev, clk_count, sizeof(struct clk *), GFP_KERNEL); if (!clks) return -ENOMEM; @@ -297,7 +297,7 @@ static int of_read_regs(struct device *dev, struct reg_info **regs_ref, return -EINVAL; } - regs = devm_kzalloc(dev, sizeof(struct reg_info) * reg_count, + regs = devm_kcalloc(dev, reg_count, sizeof(struct reg_info), GFP_KERNEL); if (!regs) return -ENOMEM; diff --git a/drivers/soc/qcom/subsystem_restart.c b/drivers/soc/qcom/subsystem_restart.c index d97b129b7e66..54f501820d73 100644 --- a/drivers/soc/qcom/subsystem_restart.c +++ b/drivers/soc/qcom/subsystem_restart.c @@ -1525,14 +1525,14 @@ static struct subsys_soc_restart_order *ssr_parse_restart_orders(struct if (!order) return ERR_PTR(-ENOMEM); - order->subsys_ptrs = devm_kzalloc(dev, - count * sizeof(struct subsys_device *), + order->subsys_ptrs = devm_kcalloc(dev, + count, sizeof(struct subsys_device *), GFP_KERNEL); if (!order->subsys_ptrs) return ERR_PTR(-ENOMEM); - order->device_ptrs = devm_kzalloc(dev, - count * sizeof(struct device_node *), + order->device_ptrs = devm_kcalloc(dev, + count, sizeof(struct device_node *), GFP_KERNEL); if (!order->device_ptrs) return ERR_PTR(-ENOMEM); diff --git a/drivers/soc/ti/knav_qmss_acc.c b/drivers/soc/ti/knav_qmss_acc.c index 672aebe1e378..2f7fb2dcc1d6 100644 --- a/drivers/soc/ti/knav_qmss_acc.c +++ b/drivers/soc/ti/knav_qmss_acc.c @@ -405,8 +405,8 @@ static int knav_acc_init_queue(struct knav_range_info *range, { unsigned id = kq->id - range->queue_base; - kq->descs = devm_kzalloc(range->kdev->dev, - ACC_DESCS_MAX * sizeof(u32), GFP_KERNEL); + kq->descs = devm_kcalloc(range->kdev->dev, + ACC_DESCS_MAX, sizeof(u32), GFP_KERNEL); if (!kq->descs) return -ENOMEM; @@ -552,7 +552,7 @@ int knav_init_acc_range(struct knav_device *kdev, info->list_size = list_size; mem_size = PAGE_ALIGN(list_size * 2); info->mem_size = mem_size; - range->acc = devm_kzalloc(kdev->dev, channels * sizeof(*range->acc), + range->acc = devm_kcalloc(kdev->dev, channels, sizeof(*range->acc), GFP_KERNEL); if (!range->acc) return -ENOMEM; diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c index c5bbe08771a4..c2b2959f4eea 100644 --- a/drivers/spi/spi-davinci.c +++ b/drivers/spi/spi-davinci.c @@ -923,9 +923,10 @@ static int davinci_spi_probe(struct platform_device *pdev) /* pdata in dspi is now updated and point pdata to that */ pdata = &dspi->pdata; - dspi->bytes_per_word = devm_kzalloc(&pdev->dev, - sizeof(*dspi->bytes_per_word) * - pdata->num_chipselect, GFP_KERNEL); + dspi->bytes_per_word = devm_kcalloc(&pdev->dev, + pdata->num_chipselect, + sizeof(*dspi->bytes_per_word), + GFP_KERNEL); if (dspi->bytes_per_word == NULL) { ret = -ENOMEM; goto free_master; diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index ce28c910ee48..79fc3940245a 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -685,8 +685,8 @@ static int ep93xx_spi_probe(struct platform_device *pdev) master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16); master->num_chipselect = info->num_chipselect; - master->cs_gpios = devm_kzalloc(&master->dev, - sizeof(int) * master->num_chipselect, + master->cs_gpios = devm_kcalloc(&master->dev, + master->num_chipselect, sizeof(int), GFP_KERNEL); if (!master->cs_gpios) { error = -ENOMEM; diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index df18d07d544d..38d830141d0a 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -1415,8 +1415,8 @@ static int spi_imx_probe(struct platform_device *pdev) if (mxc_platform_info) { master->num_chipselect = mxc_platform_info->num_chipselect; - master->cs_gpios = devm_kzalloc(&master->dev, - sizeof(int) * master->num_chipselect, GFP_KERNEL); + master->cs_gpios = devm_kcalloc(&master->dev, + master->num_chipselect, sizeof(int), GFP_KERNEL); if (!master->cs_gpios) return -ENOMEM; diff --git a/drivers/spi/spi-oc-tiny.c b/drivers/spi/spi-oc-tiny.c index b5911282a611..085f580be7ec 100644 --- a/drivers/spi/spi-oc-tiny.c +++ b/drivers/spi/spi-oc-tiny.c @@ -213,8 +213,8 @@ static int tiny_spi_of_probe(struct platform_device *pdev) return 0; hw->gpio_cs_count = of_gpio_count(np); if (hw->gpio_cs_count > 0) { - hw->gpio_cs = devm_kzalloc(&pdev->dev, - hw->gpio_cs_count * sizeof(unsigned int), + hw->gpio_cs = devm_kcalloc(&pdev->dev, + hw->gpio_cs_count, sizeof(unsigned int), GFP_KERNEL); if (!hw->gpio_cs) return -ENOMEM; diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index 4797c57f4263..1af8c96b940e 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -2135,7 +2135,7 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id) pl022->master_info = platform_info; pl022->adev = adev; pl022->vendor = id->data; - pl022->chipselects = devm_kzalloc(dev, num_cs * sizeof(int), + pl022->chipselects = devm_kcalloc(dev, num_cs, sizeof(int), GFP_KERNEL); if (!pl022->chipselects) { status = -ENOMEM; diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 49eee894f51d..237099464fec 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -2044,7 +2044,7 @@ static int of_spi_register_master(struct spi_controller *ctlr) else if (nb < 0) return nb; - cs = devm_kzalloc(&ctlr->dev, sizeof(int) * ctlr->num_chipselect, + cs = devm_kcalloc(&ctlr->dev, ctlr->num_chipselect, sizeof(int), GFP_KERNEL); ctlr->cs_gpios = cs; diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c b/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c index 8ea3920400a0..db39daef4cbe 100644 --- a/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c +++ b/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c @@ -357,8 +357,8 @@ int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus, if (error < 0) return error; - irq_resources = devm_kzalloc(&mc_bus_dev->dev, - sizeof(*irq_resources) * irq_count, + irq_resources = devm_kcalloc(&mc_bus_dev->dev, + irq_count, sizeof(*irq_resources), GFP_KERNEL); if (!irq_resources) { error = -ENOMEM; @@ -458,7 +458,7 @@ int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev) return -ENOSPC; } - irqs = devm_kzalloc(&mc_dev->dev, irq_count * sizeof(irqs[0]), + irqs = devm_kcalloc(&mc_dev->dev, irq_count, sizeof(irqs[0]), GFP_KERNEL); if (!irqs) return -ENOMEM; diff --git a/drivers/staging/greybus/audio_topology.c b/drivers/staging/greybus/audio_topology.c index 07fac3948f3a..cc35037ace59 100644 --- a/drivers/staging/greybus/audio_topology.c +++ b/drivers/staging/greybus/audio_topology.c @@ -145,7 +145,7 @@ static const char **gb_generate_enum_strings(struct gbaudio_module_info *gb, __u8 *data; items = le32_to_cpu(gbenum->items); - strings = devm_kzalloc(gb->dev, sizeof(char *) * items, GFP_KERNEL); + strings = devm_kcalloc(gb->dev, items, sizeof(char *), GFP_KERNEL); data = gbenum->names; for (i = 0; i < items; i++) { diff --git a/drivers/staging/media/atomisp/pci/atomisp2/atomisp_subdev.c b/drivers/staging/media/atomisp/pci/atomisp2/atomisp_subdev.c index 744ab6eb42a0..e5bf60601d92 100644 --- a/drivers/staging/media/atomisp/pci/atomisp2/atomisp_subdev.c +++ b/drivers/staging/media/atomisp/pci/atomisp2/atomisp_subdev.c @@ -1414,8 +1414,10 @@ int atomisp_subdev_init(struct atomisp_device *isp) * multiple streams */ isp->num_of_streams = 2; - isp->asd = devm_kzalloc(isp->dev, sizeof(struct atomisp_sub_device) * - isp->num_of_streams, GFP_KERNEL); + isp->asd = devm_kcalloc(isp->dev, + isp->num_of_streams, + sizeof(struct atomisp_sub_device), + GFP_KERNEL); if (!isp->asd) return -ENOMEM; for (i = 0; i < isp->num_of_streams; i++) { diff --git a/drivers/thermal/tegra/soctherm.c b/drivers/thermal/tegra/soctherm.c index 7d2db23d71a3..ca313c9c3aec 100644 --- a/drivers/thermal/tegra/soctherm.c +++ b/drivers/thermal/tegra/soctherm.c @@ -1352,8 +1352,8 @@ static int tegra_soctherm_probe(struct platform_device *pdev) return PTR_ERR(tegra->clock_soctherm); } - tegra->calib = devm_kzalloc(&pdev->dev, - sizeof(u32) * soc->num_tsensors, + tegra->calib = devm_kcalloc(&pdev->dev, + soc->num_tsensors, sizeof(u32), GFP_KERNEL); if (!tegra->calib) return -ENOMEM; @@ -1372,8 +1372,8 @@ static int tegra_soctherm_probe(struct platform_device *pdev) return err; } - tegra->thermctl_tzs = devm_kzalloc(&pdev->dev, - sizeof(*z) * soc->num_ttgs, + tegra->thermctl_tzs = devm_kcalloc(&pdev->dev, + soc->num_ttgs, sizeof(*z), GFP_KERNEL); if (!tegra->thermctl_tzs) return -ENOMEM; diff --git a/drivers/thermal/thermal-generic-adc.c b/drivers/thermal/thermal-generic-adc.c index ad601e5b4175..173856665430 100644 --- a/drivers/thermal/thermal-generic-adc.c +++ b/drivers/thermal/thermal-generic-adc.c @@ -91,8 +91,9 @@ static int gadc_thermal_read_linear_lookup_table(struct device *dev, return -EINVAL; } - gti->lookup_table = devm_kzalloc(dev, sizeof(*gti->lookup_table) * - ntable, GFP_KERNEL); + gti->lookup_table = devm_kcalloc(dev, + ntable, sizeof(*gti->lookup_table), + GFP_KERNEL); if (!gti->lookup_table) return -ENOMEM; diff --git a/drivers/tty/serial/rp2.c b/drivers/tty/serial/rp2.c index 056f91b3a4ca..6dc3fee6dc61 100644 --- a/drivers/tty/serial/rp2.c +++ b/drivers/tty/serial/rp2.c @@ -777,7 +777,7 @@ static int rp2_probe(struct pci_dev *pdev, rp2_init_card(card); - ports = devm_kzalloc(&pdev->dev, sizeof(*ports) * card->n_ports, + ports = devm_kcalloc(&pdev->dev, card->n_ports, sizeof(*ports), GFP_KERNEL); if (!ports) return -ENOMEM; diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index b3366c67dcd2..1ef97d80654d 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -2088,8 +2088,8 @@ static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned int event, if (!mdwc->num_gsi_event_buffers) break; - mdwc->gsi_ev_buff = devm_kzalloc(dwc->dev, - sizeof(*dwc->ev_buf) * mdwc->num_gsi_event_buffers, + mdwc->gsi_ev_buff = devm_kcalloc(dwc->dev, + mdwc->num_gsi_event_buffers, sizeof(*dwc->ev_buf), GFP_KERNEL); if (!mdwc->gsi_ev_buff) { dev_err(dwc->dev, "can't allocate gsi_ev_buff\n"); diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c index 8540e52c28a9..c13edfc71fe6 100644 --- a/drivers/usb/gadget/udc/atmel_usba_udc.c +++ b/drivers/usb/gadget/udc/atmel_usba_udc.c @@ -2095,7 +2095,7 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev, udc->num_ep = usba_config_fifo_table(udc); } - eps = devm_kzalloc(&pdev->dev, sizeof(struct usba_ep) * udc->num_ep, + eps = devm_kcalloc(&pdev->dev, udc->num_ep, sizeof(struct usba_ep), GFP_KERNEL); if (!eps) return ERR_PTR(-ENOMEM); @@ -2229,7 +2229,7 @@ static struct usba_ep * usba_udc_pdata(struct platform_device *pdev, if (!pdata) return ERR_PTR(-ENXIO); - eps = devm_kzalloc(&pdev->dev, sizeof(struct usba_ep) * pdata->num_ep, + eps = devm_kcalloc(&pdev->dev, pdata->num_ep, sizeof(struct usba_ep), GFP_KERNEL); if (!eps) return ERR_PTR(-ENOMEM); diff --git a/drivers/usb/gadget/udc/renesas_usb3.c b/drivers/usb/gadget/udc/renesas_usb3.c index 189d4e01010b..d34ddc44bfdd 100644 --- a/drivers/usb/gadget/udc/renesas_usb3.c +++ b/drivers/usb/gadget/udc/renesas_usb3.c @@ -2447,7 +2447,8 @@ static int renesas_usb3_init_ep(struct renesas_usb3 *usb3, struct device *dev, if (usb3->num_usb3_eps > USB3_MAX_NUM_PIPES) usb3->num_usb3_eps = USB3_MAX_NUM_PIPES; - usb3->usb3_ep = devm_kzalloc(dev, sizeof(*usb3_ep) * usb3->num_usb3_eps, + usb3->usb3_ep = devm_kcalloc(dev, + usb3->num_usb3_eps, sizeof(*usb3_ep), GFP_KERNEL); if (!usb3->usb3_ep) return -ENOMEM; diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c index e45cfa42e5ad..e2d6dc16c6c3 100644 --- a/drivers/usb/phy/phy-msm-usb.c +++ b/drivers/usb/phy/phy-msm-usb.c @@ -3734,8 +3734,8 @@ struct msm_otg_platform_data *msm_otg_dt_to_pdata(struct platform_device *pdev) len = of_property_count_elems_of_size(node, "qcom,hsusb-otg-phy-init-seq", sizeof(len)); if (len > 0) { - pdata->phy_init_seq = devm_kzalloc(&pdev->dev, - len * sizeof(len), GFP_KERNEL); + pdata->phy_init_seq = devm_kcalloc(&pdev->dev, + len, sizeof(len), GFP_KERNEL); if (!pdata->phy_init_seq) return NULL; of_property_read_u32_array(node, "qcom,hsusb-otg-phy-init-seq", diff --git a/drivers/video/backlight/adp8860_bl.c b/drivers/video/backlight/adp8860_bl.c index e7315bf14d60..16119bde9750 100644 --- a/drivers/video/backlight/adp8860_bl.c +++ b/drivers/video/backlight/adp8860_bl.c @@ -223,7 +223,7 @@ static int adp8860_led_probe(struct i2c_client *client) struct led_info *cur_led; int ret, i; - led = devm_kzalloc(&client->dev, sizeof(*led) * pdata->num_leds, + led = devm_kcalloc(&client->dev, pdata->num_leds, sizeof(*led), GFP_KERNEL); if (led == NULL) return -ENOMEM; diff --git a/drivers/video/backlight/adp8870_bl.c b/drivers/video/backlight/adp8870_bl.c index 058d1def2d1f..4fec9aa92d9b 100644 --- a/drivers/video/backlight/adp8870_bl.c +++ b/drivers/video/backlight/adp8870_bl.c @@ -246,7 +246,7 @@ static int adp8870_led_probe(struct i2c_client *client) struct led_info *cur_led; int ret, i; - led = devm_kzalloc(&client->dev, pdata->num_leds * sizeof(*led), + led = devm_kcalloc(&client->dev, pdata->num_leds, sizeof(*led), GFP_KERNEL); if (led == NULL) return -ENOMEM; diff --git a/drivers/video/backlight/lp855x_bl.c b/drivers/video/backlight/lp855x_bl.c index 4cdc7a3f6dc5..bd43d8cff389 100644 --- a/drivers/video/backlight/lp855x_bl.c +++ b/drivers/video/backlight/lp855x_bl.c @@ -374,7 +374,7 @@ static int lp855x_parse_dt(struct lp855x *lp) struct device_node *child; int i = 0; - rom = devm_kzalloc(dev, sizeof(*rom) * rom_length, GFP_KERNEL); + rom = devm_kcalloc(dev, rom_length, sizeof(*rom), GFP_KERNEL); if (!rom) return -ENOMEM; diff --git a/drivers/video/fbdev/au1100fb.c b/drivers/video/fbdev/au1100fb.c index 8de42f617d16..de2bfc6c3e2d 100644 --- a/drivers/video/fbdev/au1100fb.c +++ b/drivers/video/fbdev/au1100fb.c @@ -504,7 +504,7 @@ static int au1100fb_drv_probe(struct platform_device *dev) fbdev->info.fix = au1100fb_fix; fbdev->info.pseudo_palette = - devm_kzalloc(&dev->dev, sizeof(u32) * 16, GFP_KERNEL); + devm_kcalloc(&dev->dev, 16, sizeof(u32), GFP_KERNEL); if (!fbdev->info.pseudo_palette) return -ENOMEM; diff --git a/drivers/video/fbdev/bf537-lq035.c b/drivers/video/fbdev/bf537-lq035.c index ef29fb425122..57e3a6814e6b 100644 --- a/drivers/video/fbdev/bf537-lq035.c +++ b/drivers/video/fbdev/bf537-lq035.c @@ -737,8 +737,8 @@ static int bfin_lq035_probe(struct platform_device *pdev) bfin_lq035_fb.flags = FBINFO_DEFAULT; - bfin_lq035_fb.pseudo_palette = devm_kzalloc(&pdev->dev, - sizeof(u32) * 16, + bfin_lq035_fb.pseudo_palette = devm_kcalloc(&pdev->dev, + 16, sizeof(u32), GFP_KERNEL); if (bfin_lq035_fb.pseudo_palette == NULL) { pr_err("failed to allocate pseudo_palette\n"); diff --git a/drivers/video/fbdev/bf54x-lq043fb.c b/drivers/video/fbdev/bf54x-lq043fb.c index 8f1f97c75619..9b5d0b358279 100644 --- a/drivers/video/fbdev/bf54x-lq043fb.c +++ b/drivers/video/fbdev/bf54x-lq043fb.c @@ -602,7 +602,7 @@ static int bfin_bf54x_probe(struct platform_device *pdev) fbinfo->fbops = &bfin_bf54x_fb_ops; - fbinfo->pseudo_palette = devm_kzalloc(&pdev->dev, sizeof(u32) * 16, + fbinfo->pseudo_palette = devm_kcalloc(&pdev->dev, 16, sizeof(u32), GFP_KERNEL); if (!fbinfo->pseudo_palette) { printk(KERN_ERR DRIVER_NAME diff --git a/drivers/video/fbdev/msm/dsi_v2.c b/drivers/video/fbdev/msm/dsi_v2.c index 60c57e45212d..5ac17eb2c383 100644 --- a/drivers/video/fbdev/msm/dsi_v2.c +++ b/drivers/video/fbdev/msm/dsi_v2.c @@ -286,8 +286,9 @@ static int mdss_dsi_get_dt_vreg_data(struct device *dev, pr_debug("%s: vreg found. count=%d\n", __func__, mp->num_vreg); } - mp->vreg_config = devm_kzalloc(dev, sizeof(struct dss_vreg) * - mp->num_vreg, GFP_KERNEL); + mp->vreg_config = devm_kcalloc(dev, + mp->num_vreg, sizeof(struct dss_vreg), + GFP_KERNEL); if (!mp->vreg_config) { rc = -ENOMEM; goto error; diff --git a/drivers/video/fbdev/msm/mdp3_ctrl.c b/drivers/video/fbdev/msm/mdp3_ctrl.c index 9a2b739e6b5e..29276da66a23 100644 --- a/drivers/video/fbdev/msm/mdp3_ctrl.c +++ b/drivers/video/fbdev/msm/mdp3_ctrl.c @@ -2222,22 +2222,22 @@ static int mdp3_alloc_lut_buffer(struct platform_device *pdev, void **cmap) memset(map, 0, sizeof(struct fb_cmap)); - map->red = devm_kzalloc(&pdev->dev, MDP_LUT_SIZE * sizeof(u16), + map->red = devm_kcalloc(&pdev->dev, MDP_LUT_SIZE, sizeof(u16), GFP_KERNEL); if (map->red == NULL) goto exit_red; memset(map->red, 0, sizeof(u16) * MDP_LUT_SIZE); - map->green = devm_kzalloc(&pdev->dev, MDP_LUT_SIZE * sizeof(u16), - GFP_KERNEL); + map->green = devm_kcalloc(&pdev->dev, MDP_LUT_SIZE, sizeof(u16), + GFP_KERNEL); if (map->green == NULL) goto exit_green; memset(map->green, 0, sizeof(u16) * MDP_LUT_SIZE); - map->blue = devm_kzalloc(&pdev->dev, MDP_LUT_SIZE * sizeof(u16), - GFP_KERNEL); + map->blue = devm_kcalloc(&pdev->dev, MDP_LUT_SIZE, sizeof(u16), + GFP_KERNEL); if (map->blue == NULL) goto exit_blue; diff --git a/drivers/video/fbdev/msm/mdss_dsi.c b/drivers/video/fbdev/msm/mdss_dsi.c index f578c73ac394..0461f821027d 100644 --- a/drivers/video/fbdev/msm/mdss_dsi.c +++ b/drivers/video/fbdev/msm/mdss_dsi.c @@ -559,8 +559,9 @@ int mdss_dsi_get_dt_vreg_data(struct device *dev, pr_debug("%s: vreg found. count=%d\n", __func__, mp->num_vreg); } - mp->vreg_config = devm_kzalloc(dev, sizeof(struct dss_vreg) * - mp->num_vreg, GFP_KERNEL); + mp->vreg_config = devm_kcalloc(dev, + mp->num_vreg, sizeof(struct dss_vreg), + GFP_KERNEL); if (!mp->vreg_config) { rc = -ENOMEM; goto error; diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c index 918fe6a12f06..b8594852b5f0 100644 --- a/drivers/video/fbdev/msm/mdss_fb.c +++ b/drivers/video/fbdev/msm/mdss_fb.c @@ -1189,8 +1189,8 @@ static int mdss_fb_init_panel_modes(struct msm_fb_data_type *mfd, list_for_each(pos, &pdata->timings_list) num_timings++; - modedb = devm_kzalloc(fbi->dev, num_timings * sizeof(*modedb), - GFP_KERNEL); + modedb = devm_kcalloc(fbi->dev, num_timings, sizeof(*modedb), + GFP_KERNEL); if (!modedb) return -ENOMEM; diff --git a/drivers/video/fbdev/msm/mdss_hdmi_tx.c b/drivers/video/fbdev/msm/mdss_hdmi_tx.c index e634fffcf1e4..7cc3c49dbe5d 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_tx.c +++ b/drivers/video/fbdev/msm/mdss_hdmi_tx.c @@ -4191,8 +4191,10 @@ static int hdmi_tx_init_power_data(struct device *dev, } hpd_power_data->num_clk = hpd_clk_count; - hpd_power_data->clk_config = devm_kzalloc(dev, sizeof(struct dss_clk) * - hpd_power_data->num_clk, GFP_KERNEL); + hpd_power_data->clk_config = devm_kcalloc(dev, + hpd_power_data->num_clk, + sizeof(struct dss_clk), + GFP_KERNEL); if (!hpd_power_data->clk_config) { rc = -EINVAL; goto exit; @@ -4206,8 +4208,10 @@ static int hdmi_tx_init_power_data(struct device *dev, } core_power_data->num_clk = core_clk_count; - core_power_data->clk_config = devm_kzalloc(dev, sizeof(struct dss_clk) * - core_power_data->num_clk, GFP_KERNEL); + core_power_data->clk_config = devm_kcalloc(dev, + core_power_data->num_clk, + sizeof(struct dss_clk), + GFP_KERNEL); if (!core_power_data->clk_config) { core_power_data->num_clk = 0; rc = -EINVAL; @@ -4386,8 +4390,10 @@ static int hdmi_tx_get_dt_vreg_data(struct device *dev, if (mod_vreg_total > 0) { mp->num_vreg = mod_vreg_total; - mp->vreg_config = devm_kzalloc(dev, sizeof(struct dss_vreg) * - mod_vreg_total, GFP_KERNEL); + mp->vreg_config = devm_kcalloc(dev, + mod_vreg_total, + sizeof(struct dss_vreg), + GFP_KERNEL); if (!mp->vreg_config) { DEV_ERR("%s: can't alloc '%s' vreg mem\n", __func__, hdmi_tx_pm_name(module_type)); @@ -4398,7 +4404,7 @@ static int hdmi_tx_get_dt_vreg_data(struct device *dev, return 0; } - val_array = devm_kzalloc(dev, sizeof(u32) * dt_vreg_total, GFP_KERNEL); + val_array = devm_kcalloc(dev, dt_vreg_total, sizeof(u32), GFP_KERNEL); if (!val_array) { DEV_ERR("%s: can't allocate vreg scratch mem\n", __func__); rc = -ENOMEM; @@ -4570,8 +4576,9 @@ static int hdmi_tx_get_dt_gpio_data(struct device *dev, DEV_DBG("%s: mp_gpio_cnt = %d\n", __func__, mp_gpio_cnt); mp->num_gpio = mp_gpio_cnt; - mp->gpio_config = devm_kzalloc(dev, sizeof(struct dss_gpio) * - mp_gpio_cnt, GFP_KERNEL); + mp->gpio_config = devm_kcalloc(dev, + mp_gpio_cnt, sizeof(struct dss_gpio), + GFP_KERNEL); if (!mp->gpio_config) { DEV_ERR("%s: can't alloc '%s' gpio mem\n", __func__, hdmi_tx_pm_name(module_type)); diff --git a/drivers/video/fbdev/msm/mdss_mdp.c b/drivers/video/fbdev/msm/mdss_mdp.c index afd11b5eb603..e9625d0636f9 100644 --- a/drivers/video/fbdev/msm/mdss_mdp.c +++ b/drivers/video/fbdev/msm/mdss_mdp.c @@ -2432,8 +2432,9 @@ static u32 mdss_mdp_scaler_init(struct mdss_data_type *mdata, mdata->scaler_off->ndest_scalers = len/sizeof(u32); mdata->scaler_off->dest_scaler_off = - devm_kzalloc(dev, sizeof(u32) * + devm_kcalloc(&mdata->pdev->dev, mdata->scaler_off->ndest_scalers, + sizeof(u32), GFP_KERNEL); if (!mdata->scaler_off->dest_scaler_off) return -ENOMEM; @@ -2446,8 +2447,9 @@ static u32 mdss_mdp_scaler_init(struct mdss_data_type *mdata, return ret; mdata->scaler_off->dest_scaler_lut_off = - devm_kzalloc(dev, sizeof(u32) * + devm_kcalloc(&mdata->pdev->dev, mdata->scaler_off->ndest_scalers, + sizeof(u32), GFP_KERNEL); if (!mdata->scaler_off->dest_scaler_lut_off) return -ENOMEM; @@ -3344,8 +3346,10 @@ int mdss_mdp_parse_dt_hw_settings(struct platform_device *pdev) if (!(mdp_len + vbif_len + vbif_nrt_len)) return 0; - hws = devm_kzalloc(&pdev->dev, sizeof(*hws) * (vbif_len + mdp_len + - vbif_nrt_len + 1), GFP_KERNEL); + hws = devm_kcalloc(&pdev->dev, + vbif_len + mdp_len + vbif_nrt_len + 1, + sizeof(*hws), + GFP_KERNEL); if (!hws) return -ENOMEM; @@ -3909,10 +3913,9 @@ static int mdss_mdp_cdm_addr_setup(struct mdss_data_type *mdata, struct mdss_mdp_cdm *head; u32 i = 0; - head = devm_kzalloc(&mdata->pdev->dev, sizeof(struct mdss_mdp_cdm) * - len, GFP_KERNEL); - if (!head) { - pr_err("%s: no memory for CDM info\n", __func__); + head = devm_kcalloc(&mdata->pdev->dev, + len, sizeof(struct mdss_mdp_cdm), GFP_KERNEL); + if (!head) return -ENOMEM; } @@ -3978,8 +3981,8 @@ static int mdss_mdp_dsc_addr_setup(struct mdss_data_type *mdata, struct mdss_mdp_dsc *head; u32 i = 0; - head = devm_kzalloc(&mdata->pdev->dev, sizeof(struct mdss_mdp_dsc) * - len, GFP_KERNEL); + head = devm_kcalloc(&mdata->pdev->dev, + len, sizeof(struct mdss_mdp_dsc), GFP_KERNEL); if (!head) return -ENOMEM; @@ -4408,10 +4411,11 @@ static void mdss_mdp_parse_max_bandwidth(struct platform_device *pdev) max_bw_settings_cnt /= 2 * sizeof(u32); - max_bw_settings = devm_kzalloc(&pdev->dev, sizeof(*max_bw_settings) - * max_bw_settings_cnt, GFP_KERNEL); - if (!max_bw_settings) { - pr_err("Memory allocation failed for max_bw_settings\n"); + max_bw_settings = devm_kcalloc(&pdev->dev, + max_bw_settings_cnt, + sizeof(*max_bw_settings), + GFP_KERNEL); + if (!max_bw_settings) return; } @@ -4450,8 +4454,8 @@ static void mdss_mdp_parse_per_pipe_bandwidth(struct platform_device *pdev) max_bw_settings_cnt /= 2 * sizeof(u32); - max_bw_per_pipe_settings = devm_kzalloc(&pdev->dev, - sizeof(struct mdss_max_bw_settings) * max_bw_settings_cnt, + max_bw_per_pipe_settings = devm_kcalloc(&pdev->dev, + max_bw_settings_cnt, sizeof(struct mdss_max_bw_settings), GFP_KERNEL); if (!max_bw_per_pipe_settings) { pr_err("Memory allocation failed for max_bw_settings\n"); @@ -4710,8 +4714,8 @@ static int mdss_mdp_parse_dt_ppb_off(struct platform_device *pdev) arr = of_get_property(pdev->dev.of_node, "qcom,mdss-ppb-ctl-off", &len); if (arr) { mdata->nppb_ctl = len / sizeof(u32); - mdata->ppb_ctl = devm_kzalloc(&mdata->pdev->dev, - sizeof(u32) * mdata->nppb_ctl, GFP_KERNEL); + mdata->ppb_ctl = devm_kcalloc(&mdata->pdev->dev, + mdata->nppb_ctl, sizeof(u32), GFP_KERNEL); if (mdata->ppb_ctl == NULL) return -ENOMEM; @@ -4723,8 +4727,8 @@ static int mdss_mdp_parse_dt_ppb_off(struct platform_device *pdev) arr = of_get_property(pdev->dev.of_node, "qcom,mdss-ppb-cfg-off", &len); if (arr) { mdata->nppb_cfg = len / sizeof(u32); - mdata->ppb_cfg = devm_kzalloc(&mdata->pdev->dev, - sizeof(u32) * mdata->nppb_cfg, GFP_KERNEL); + mdata->ppb_cfg = devm_kcalloc(&mdata->pdev->dev, + mdata->nppb_cfg, sizeof(u32), GFP_KERNEL); if (mdata->ppb_cfg == NULL) return -ENOMEM; diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c index 758f97197f84..b4962b0eb2e5 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c +++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c @@ -5248,8 +5248,8 @@ int mdss_mdp_mixer_addr_setup(struct mdss_data_type *mdata, (mdata->wfd_mode == MDSS_MDP_WFD_SHARED)) size++; - head = devm_kzalloc(&mdata->pdev->dev, sizeof(struct mdss_mdp_mixer) * - size, GFP_KERNEL); + head = devm_kcalloc(&mdata->pdev->dev, + size, sizeof(struct mdss_mdp_mixer), GFP_KERNEL); if (!head) { pr_err("unable to setup mixer type=%d :kzalloc fail\n", @@ -5319,8 +5319,8 @@ int mdss_mdp_ctl_addr_setup(struct mdss_data_type *mdata, mutex_init(shared_lock); } - head = devm_kzalloc(&mdata->pdev->dev, sizeof(struct mdss_mdp_ctl) * - size, GFP_KERNEL); + head = devm_kcalloc(&mdata->pdev->dev, + size, sizeof(struct mdss_mdp_ctl), GFP_KERNEL); if (!head) { pr_err("unable to setup ctl and wb: kzalloc fail\n"); @@ -5355,10 +5355,10 @@ int mdss_mdp_wb_addr_setup(struct mdss_data_type *mdata, u32 total, i; total = num_block_wb + num_intf_wb; - wb = devm_kzalloc(&mdata->pdev->dev, sizeof(struct mdss_mdp_writeback) * - total, GFP_KERNEL); - if (!wb) { - pr_err("unable to setup wb: kzalloc fail\n"); + wb = devm_kcalloc(&mdata->pdev->dev, + total, sizeof(struct mdss_mdp_writeback), + GFP_KERNEL); + if (!wb) return -ENOMEM; } diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c index 1ae6ebbf001e..e17a6ee2076e 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c +++ b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c @@ -317,8 +317,8 @@ int mdss_mdp_video_addr_setup(struct mdss_data_type *mdata, struct mdss_mdp_video_ctx *head; u32 i; - head = devm_kzalloc(&mdata->pdev->dev, - sizeof(struct mdss_mdp_video_ctx) * count, GFP_KERNEL); + head = devm_kcalloc(&mdata->pdev->dev, + count, sizeof(struct mdss_mdp_video_ctx), GFP_KERNEL); if (!head) return -ENOMEM; diff --git a/drivers/video/fbdev/msm/mdss_mdp_pp.c b/drivers/video/fbdev/msm/mdss_mdp_pp.c index 4581d2538bb8..6f0d8fa4738d 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_pp.c +++ b/drivers/video/fbdev/msm/mdss_mdp_pp.c @@ -3186,9 +3186,9 @@ int mdss_mdp_pp_init(struct device *dev) goto pp_exit; } pp_ops = pp_driver_ops.pp_ops; - hist = devm_kzalloc(dev, - sizeof(struct pp_hist_col_info) * + hist = devm_kcalloc(dev, mdata->ndspp, + sizeof(struct pp_hist_col_info), GFP_KERNEL); if (hist == NULL) { pr_err("dspp histogram allocation failed!\n"); @@ -6805,8 +6805,8 @@ int mdss_mdp_ad_addr_setup(struct mdss_data_type *mdata, u32 *ad_offsets) u32 i; int rc = 0; - mdata->ad_off = devm_kzalloc(&mdata->pdev->dev, - sizeof(struct mdss_mdp_ad) * mdata->nad_cfgs, + mdata->ad_off = devm_kcalloc(&mdata->pdev->dev, + mdata->nad_cfgs, sizeof(struct mdss_mdp_ad), GFP_KERNEL); if (!mdata->ad_off) { @@ -6814,8 +6814,8 @@ int mdss_mdp_ad_addr_setup(struct mdss_data_type *mdata, u32 *ad_offsets) return -ENOMEM; } - mdata->ad_cfgs = devm_kzalloc(&mdata->pdev->dev, - sizeof(struct mdss_ad_info) * mdata->nad_cfgs, + mdata->ad_cfgs = devm_kcalloc(&mdata->pdev->dev, + mdata->nad_cfgs, sizeof(struct mdss_ad_info), GFP_KERNEL); if (!mdata->ad_cfgs) { diff --git a/drivers/video/fbdev/msm/mdss_rotator.c b/drivers/video/fbdev/msm/mdss_rotator.c index f285d793d520..0997384531af 100644 --- a/drivers/video/fbdev/msm/mdss_rotator.c +++ b/drivers/video/fbdev/msm/mdss_rotator.c @@ -1942,8 +1942,8 @@ static int mdss_rotator_open_session(struct mdss_rot_mgr *mgr, return -ENOMEM; ATRACE_BEGIN(__func__); /* Open session votes for bw */ - perf->work_distribution = devm_kzalloc(&mgr->pdev->dev, - sizeof(u32) * mgr->queue_count, GFP_KERNEL); + perf->work_distribution = devm_kcalloc(&mgr->pdev->dev, + mgr->queue_count, sizeof(u32), GFP_KERNEL); if (!perf->work_distribution) { ret = -ENOMEM; goto alloc_err; @@ -2696,8 +2696,9 @@ static int mdss_rotator_get_dt_vreg_data(struct device *dev, return 0; } mp->num_vreg = dt_vreg_total; - mp->vreg_config = devm_kzalloc(dev, sizeof(struct dss_vreg) * - dt_vreg_total, GFP_KERNEL); + mp->vreg_config = devm_kcalloc(dev, + dt_vreg_total, sizeof(struct dss_vreg), + GFP_KERNEL); if (!mp->vreg_config) { DEV_ERR("%s: can't alloc vreg mem\n", __func__); return -ENOMEM; diff --git a/drivers/video/fbdev/msm/mdss_smmu.c b/drivers/video/fbdev/msm/mdss_smmu.c index 79554f9a10b0..1fd7e5f7ff1c 100644 --- a/drivers/video/fbdev/msm/mdss_smmu.c +++ b/drivers/video/fbdev/msm/mdss_smmu.c @@ -196,8 +196,8 @@ static int mdss_smmu_util_parse_dt_clock(struct platform_device *pdev, } mp->num_clk = num_clk; - mp->clk_config = devm_kzalloc(&pdev->dev, - sizeof(struct dss_clk) * mp->num_clk, GFP_KERNEL); + mp->clk_config = devm_kcalloc(&pdev->dev, + mp->num_clk, sizeof(struct dss_clk), GFP_KERNEL); if (!mp->clk_config) { pr_err("clock configuration allocation failed\n"); rc = -ENOMEM; diff --git a/drivers/video/fbdev/msm/mdss_spi_panel.c b/drivers/video/fbdev/msm/mdss_spi_panel.c index 5f4f4eab0547..b973e97c109a 100644 --- a/drivers/video/fbdev/msm/mdss_spi_panel.c +++ b/drivers/video/fbdev/msm/mdss_spi_panel.c @@ -732,10 +732,12 @@ static void mdss_spi_parse_esd_params(struct device_node *np, ctrl->status_cmds_rlen = (!rc ? tmp : 1); - ctrl->exp_status_value = devm_kzalloc(&mdss_pdev->dev, sizeof(u8) * - (ctrl->status_cmds_rlen + 1), GFP_KERNEL); - ctrl->act_status_value = devm_kzalloc(&mdss_pdev->dev, sizeof(u8) * - (ctrl->status_cmds_rlen + 1), GFP_KERNEL); + ctrl->exp_status_value = devm_kzalloc(&mdss_pdev->dev, + ctrl->status_cmds_rlen + 1, + GFP_KERNEL); + ctrl->act_status_value = devm_kzalloc(&mdss_pdev->dev, + ctrl->status_cmds_rlen + 1, + GFP_KERNEL); if (!ctrl->exp_status_value || !ctrl->act_status_value) { pinfo->esd_check_enabled = false; diff --git a/drivers/video/fbdev/msm/msm_dba/adv7533.c b/drivers/video/fbdev/msm/msm_dba/adv7533.c index 49303625c3d9..50648aa5fc69 100644 --- a/drivers/video/fbdev/msm/msm_dba/adv7533.c +++ b/drivers/video/fbdev/msm/msm_dba/adv7533.c @@ -449,12 +449,13 @@ static void adv7533_parse_vreg_dt(struct device *dev, goto end; } mp->num_vreg = dt_vreg_total; - mp->vreg_config = devm_kzalloc(dev, sizeof(struct dss_vreg) * - dt_vreg_total, GFP_KERNEL); + mp->vreg_config = devm_kcalloc(dev, + dt_vreg_total, sizeof(struct dss_vreg), + GFP_KERNEL); if (!mp->vreg_config) goto end; - val_array = devm_kzalloc(dev, sizeof(u32) * dt_vreg_total, GFP_KERNEL); + val_array = devm_kcalloc(dev, dt_vreg_total, sizeof(u32), GFP_KERNEL); if (!val_array) goto end; diff --git a/drivers/video/fbdev/mxsfb.c b/drivers/video/fbdev/mxsfb.c index 7846f0e8bbbb..f3657d093ce5 100644 --- a/drivers/video/fbdev/mxsfb.c +++ b/drivers/video/fbdev/mxsfb.c @@ -925,7 +925,7 @@ static int mxsfb_probe(struct platform_device *pdev) if (IS_ERR(host->reg_lcd)) host->reg_lcd = NULL; - fb_info->pseudo_palette = devm_kzalloc(&pdev->dev, sizeof(u32) * 16, + fb_info->pseudo_palette = devm_kcalloc(&pdev->dev, 16, sizeof(u32), GFP_KERNEL); if (!fb_info->pseudo_palette) { ret = -ENOMEM; diff --git a/drivers/video/fbdev/omap2/omapfb/vrfb.c b/drivers/video/fbdev/omap2/omapfb/vrfb.c index f346b02eee1d..f355ecfac3b1 100644 --- a/drivers/video/fbdev/omap2/omapfb/vrfb.c +++ b/drivers/video/fbdev/omap2/omapfb/vrfb.c @@ -359,8 +359,8 @@ static int __init vrfb_probe(struct platform_device *pdev) num_ctxs = pdev->num_resources - 1; - ctxs = devm_kzalloc(&pdev->dev, - sizeof(struct vrfb_ctx) * num_ctxs, + ctxs = devm_kcalloc(&pdev->dev, + num_ctxs, sizeof(struct vrfb_ctx), GFP_KERNEL); if (!ctxs) diff --git a/drivers/vservices/transport/axon.c b/drivers/vservices/transport/axon.c index 4604b2831922..a66d3f013f26 100644 --- a/drivers/vservices/transport/axon.c +++ b/drivers/vservices/transport/axon.c @@ -3056,8 +3056,8 @@ static int transport_axon_setup_descs(struct vs_transport_axon *transport) } /* Array of pointers to the source TX pool for each outgoing buffer. */ - transport->tx_pools = devm_kzalloc(transport->axon_dev, - sizeof(*transport->tx_pools) * transport->queue_size, + transport->tx_pools = devm_kcalloc(transport->axon_dev, + transport->queue_size, sizeof(*transport->tx_pools), GFP_KERNEL); if (!transport->tx_pools) { err = -ENOMEM; diff --git a/sound/soc/au1x/dbdma2.c b/sound/soc/au1x/dbdma2.c index 6a035ca0f521..42e6e6f89411 100644 --- a/sound/soc/au1x/dbdma2.c +++ b/sound/soc/au1x/dbdma2.c @@ -336,8 +336,8 @@ static int au1xpsc_pcm_drvprobe(struct platform_device *pdev) { struct au1xpsc_audio_dmadata *dmadata; - dmadata = devm_kzalloc(&pdev->dev, - 2 * sizeof(struct au1xpsc_audio_dmadata), + dmadata = devm_kcalloc(&pdev->dev, + 2, sizeof(struct au1xpsc_audio_dmadata), GFP_KERNEL); if (!dmadata) return -ENOMEM; diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c index e00f5f49f21d..9195573b01a8 100644 --- a/sound/soc/codecs/hdmi-codec.c +++ b/sound/soc/codecs/hdmi-codec.c @@ -774,7 +774,7 @@ static int hdmi_codec_probe(struct platform_device *pdev) hcp->hcd = *hcd; mutex_init(&hcp->current_stream_lock); - hcp->daidrv = devm_kzalloc(dev, dai_count * sizeof(*hcp->daidrv), + hcp->daidrv = devm_kcalloc(dev, dai_count, sizeof(*hcp->daidrv), GFP_KERNEL); if (!hcp->daidrv) return -ENOMEM; diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index a98647ac497c..1000b50bd435 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c @@ -3383,8 +3383,9 @@ static int rt5645_probe(struct snd_soc_codec *codec) snd_soc_dapm_sync(dapm); } - rt5645->eq_param = devm_kzalloc(codec->dev, - RT5645_HWEQ_NUM * sizeof(struct rt5645_eq_param_s), GFP_KERNEL); + rt5645->eq_param = devm_kcalloc(codec->dev, + RT5645_HWEQ_NUM, sizeof(struct rt5645_eq_param_s), + GFP_KERNEL); return 0; } diff --git a/sound/soc/codecs/tfa98xx.c b/sound/soc/codecs/tfa98xx.c index 15e9a0c6cf5e..ed31bc4fa5a4 100644 --- a/sound/soc/codecs/tfa98xx.c +++ b/sound/soc/codecs/tfa98xx.c @@ -1428,8 +1428,8 @@ static int tfa98xx_create_controls(struct tfa98xx *tfa98xx) nr_controls++; /* Playback Volume control */ } - tfa98xx_controls = devm_kzalloc(tfa98xx->codec->dev, - nr_controls * sizeof(tfa98xx_controls[0]), GFP_KERNEL); + tfa98xx_controls = devm_kcalloc(tfa98xx->codec->dev, + nr_controls, sizeof(tfa98xx_controls[0]), GFP_KERNEL); if (!tfa98xx_controls) return -ENOMEM; diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index f289762cd676..fb7e77e51441 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -3297,8 +3297,8 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994) }; /* We need an array of texts for the enum API */ - wm8994->drc_texts = devm_kzalloc(wm8994->hubs.codec->dev, - sizeof(char *) * pdata->num_drc_cfgs, GFP_KERNEL); + wm8994->drc_texts = devm_kcalloc(wm8994->hubs.codec->dev, + pdata->num_drc_cfgs, sizeof(char *), GFP_KERNEL); if (!wm8994->drc_texts) return; diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index 6991718d7c8a..08af1d925f28 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -1877,8 +1877,8 @@ static int davinci_mcasp_probe(struct platform_device *pdev) mcasp->num_serializer = pdata->num_serializer; #ifdef CONFIG_PM_SLEEP - mcasp->context.xrsr_regs = devm_kzalloc(&pdev->dev, - sizeof(u32) * mcasp->num_serializer, + mcasp->context.xrsr_regs = devm_kcalloc(&pdev->dev, + mcasp->num_serializer, sizeof(u32), GFP_KERNEL); if (!mcasp->context.xrsr_regs) { ret = -ENOMEM; @@ -2013,13 +2013,15 @@ static int davinci_mcasp_probe(struct platform_device *pdev) * bytes. */ mcasp->chconstr[SNDRV_PCM_STREAM_PLAYBACK].list = - devm_kzalloc(mcasp->dev, sizeof(unsigned int) * - (32 + mcasp->num_serializer - 1), + devm_kcalloc(mcasp->dev, + 32 + mcasp->num_serializer - 1, + sizeof(unsigned int), GFP_KERNEL); mcasp->chconstr[SNDRV_PCM_STREAM_CAPTURE].list = - devm_kzalloc(mcasp->dev, sizeof(unsigned int) * - (32 + mcasp->num_serializer - 1), + devm_kcalloc(mcasp->dev, + 32 + mcasp->num_serializer - 1, + sizeof(unsigned int), GFP_KERNEL); if (!mcasp->chconstr[SNDRV_PCM_STREAM_PLAYBACK].list || diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index 488c52f9405f..a31bbef377e5 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -265,8 +265,8 @@ static int asoc_graph_card_probe(struct platform_device *pdev) if (num == 0) return -EINVAL; - dai_props = devm_kzalloc(dev, sizeof(*dai_props) * num, GFP_KERNEL); - dai_link = devm_kzalloc(dev, sizeof(*dai_link) * num, GFP_KERNEL); + dai_props = devm_kcalloc(dev, num, sizeof(*dai_props), GFP_KERNEL); + dai_link = devm_kcalloc(dev, num, sizeof(*dai_link), GFP_KERNEL); if (!dai_props || !dai_link) return -ENOMEM; diff --git a/sound/soc/generic/audio-graph-scu-card.c b/sound/soc/generic/audio-graph-scu-card.c index a967aa143d51..095ef6426d42 100644 --- a/sound/soc/generic/audio-graph-scu-card.c +++ b/sound/soc/generic/audio-graph-scu-card.c @@ -348,8 +348,8 @@ static int asoc_graph_card_probe(struct platform_device *pdev) if (num == 0) return -EINVAL; - dai_props = devm_kzalloc(dev, sizeof(*dai_props) * num, GFP_KERNEL); - dai_link = devm_kzalloc(dev, sizeof(*dai_link) * num, GFP_KERNEL); + dai_props = devm_kcalloc(dev, num, sizeof(*dai_props), GFP_KERNEL); + dai_link = devm_kcalloc(dev, num, sizeof(*dai_link), GFP_KERNEL); if (!dai_props || !dai_link) return -ENOMEM; diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 6959a74a6f49..ca8dcda0906a 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -319,8 +319,8 @@ static int asoc_simple_card_parse_aux_devs(struct device_node *node, if (n <= 0) return -EINVAL; - card->aux_dev = devm_kzalloc(dev, - n * sizeof(*card->aux_dev), GFP_KERNEL); + card->aux_dev = devm_kcalloc(dev, + n, sizeof(*card->aux_dev), GFP_KERNEL); if (!card->aux_dev) return -ENOMEM; @@ -414,8 +414,8 @@ static int asoc_simple_card_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; - dai_props = devm_kzalloc(dev, sizeof(*dai_props) * num, GFP_KERNEL); - dai_link = devm_kzalloc(dev, sizeof(*dai_link) * num, GFP_KERNEL); + dai_props = devm_kcalloc(dev, num, sizeof(*dai_props), GFP_KERNEL); + dai_link = devm_kcalloc(dev, num, sizeof(*dai_link), GFP_KERNEL); if (!dai_props || !dai_link) return -ENOMEM; diff --git a/sound/soc/generic/simple-scu-card.c b/sound/soc/generic/simple-scu-card.c index 48606c63562a..487716559deb 100644 --- a/sound/soc/generic/simple-scu-card.c +++ b/sound/soc/generic/simple-scu-card.c @@ -246,8 +246,8 @@ static int asoc_simple_card_probe(struct platform_device *pdev) num = of_get_child_count(np); - dai_props = devm_kzalloc(dev, sizeof(*dai_props) * num, GFP_KERNEL); - dai_link = devm_kzalloc(dev, sizeof(*dai_link) * num, GFP_KERNEL); + dai_props = devm_kcalloc(dev, num, sizeof(*dai_props), GFP_KERNEL); + dai_link = devm_kcalloc(dev, num, sizeof(*dai_link), GFP_KERNEL); if (!dai_props || !dai_link) return -ENOMEM; diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index b45c1ae60f94..be189a34efdd 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -2334,8 +2334,10 @@ static int skl_tplg_get_token(struct device *dev, case SKL_TKN_U8_DYN_IN_PIN: if (!mconfig->m_in_pin) - mconfig->m_in_pin = devm_kzalloc(dev, MAX_IN_QUEUE * - sizeof(*mconfig->m_in_pin), GFP_KERNEL); + mconfig->m_in_pin = devm_kcalloc(dev, + MAX_IN_QUEUE, + sizeof(*mconfig->m_in_pin), + GFP_KERNEL); if (!mconfig->m_in_pin) return -ENOMEM; @@ -2345,8 +2347,10 @@ static int skl_tplg_get_token(struct device *dev, case SKL_TKN_U8_DYN_OUT_PIN: if (!mconfig->m_out_pin) - mconfig->m_out_pin = devm_kzalloc(dev, MAX_IN_QUEUE * - sizeof(*mconfig->m_in_pin), GFP_KERNEL); + mconfig->m_out_pin = devm_kcalloc(dev, + MAX_IN_QUEUE, + sizeof(*mconfig->m_in_pin), + GFP_KERNEL); if (!mconfig->m_out_pin) return -ENOMEM; diff --git a/sound/soc/pxa/mmp-sspa.c b/sound/soc/pxa/mmp-sspa.c index 64b85e30c1f8..566080770889 100644 --- a/sound/soc/pxa/mmp-sspa.c +++ b/sound/soc/pxa/mmp-sspa.c @@ -426,8 +426,8 @@ static int asoc_mmp_sspa_probe(struct platform_device *pdev) if (priv->sspa == NULL) return -ENOMEM; - priv->dma_params = devm_kzalloc(&pdev->dev, - 2 * sizeof(struct snd_dmaengine_dai_dma_data), + priv->dma_params = devm_kcalloc(&pdev->dev, + 2, sizeof(struct snd_dmaengine_dai_dma_data), GFP_KERNEL); if (priv->dma_params == NULL) return -ENOMEM; diff --git a/sound/soc/sh/rcar/cmd.c b/sound/soc/sh/rcar/cmd.c index f1d4fb566892..6c65b6e295d1 100644 --- a/sound/soc/sh/rcar/cmd.c +++ b/sound/soc/sh/rcar/cmd.c @@ -156,7 +156,7 @@ int rsnd_cmd_probe(struct rsnd_priv *priv) if (!nr) return 0; - cmd = devm_kzalloc(dev, sizeof(*cmd) * nr, GFP_KERNEL); + cmd = devm_kcalloc(dev, nr, sizeof(*cmd), GFP_KERNEL); if (!cmd) return -ENOMEM; diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index f203c0878e69..6a4a49199b36 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -1094,8 +1094,8 @@ static int rsnd_dai_probe(struct rsnd_priv *priv) if (!nr) return -EINVAL; - rdrv = devm_kzalloc(dev, sizeof(*rdrv) * nr, GFP_KERNEL); - rdai = devm_kzalloc(dev, sizeof(*rdai) * nr, GFP_KERNEL); + rdrv = devm_kcalloc(dev, nr, sizeof(*rdrv), GFP_KERNEL); + rdai = devm_kcalloc(dev, nr, sizeof(*rdai), GFP_KERNEL); if (!rdrv || !rdai) return -ENOMEM; diff --git a/sound/soc/sh/rcar/ctu.c b/sound/soc/sh/rcar/ctu.c index e7f53f44165d..0fb32c49fc24 100644 --- a/sound/soc/sh/rcar/ctu.c +++ b/sound/soc/sh/rcar/ctu.c @@ -370,7 +370,7 @@ int rsnd_ctu_probe(struct rsnd_priv *priv) goto rsnd_ctu_probe_done; } - ctu = devm_kzalloc(dev, sizeof(*ctu) * nr, GFP_KERNEL); + ctu = devm_kcalloc(dev, nr, sizeof(*ctu), GFP_KERNEL); if (!ctu) { ret = -ENOMEM; goto rsnd_ctu_probe_done; diff --git a/sound/soc/sh/rcar/dvc.c b/sound/soc/sh/rcar/dvc.c index 1743ade3cc55..edec2e245245 100644 --- a/sound/soc/sh/rcar/dvc.c +++ b/sound/soc/sh/rcar/dvc.c @@ -360,7 +360,7 @@ int rsnd_dvc_probe(struct rsnd_priv *priv) goto rsnd_dvc_probe_done; } - dvc = devm_kzalloc(dev, sizeof(*dvc) * nr, GFP_KERNEL); + dvc = devm_kcalloc(dev, nr, sizeof(*dvc), GFP_KERNEL); if (!dvc) { ret = -ENOMEM; goto rsnd_dvc_probe_done; diff --git a/sound/soc/sh/rcar/mix.c b/sound/soc/sh/rcar/mix.c index 6c4826c189a4..b716207aab8e 100644 --- a/sound/soc/sh/rcar/mix.c +++ b/sound/soc/sh/rcar/mix.c @@ -148,7 +148,7 @@ int rsnd_mix_probe(struct rsnd_priv *priv) goto rsnd_mix_probe_done; } - mix = devm_kzalloc(dev, sizeof(*mix) * nr, GFP_KERNEL); + mix = devm_kcalloc(dev, nr, sizeof(*mix), GFP_KERNEL); if (!mix) { ret = -ENOMEM; goto rsnd_mix_probe_done; diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index 510b68a483b4..0e71e8ed08f6 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c @@ -557,7 +557,7 @@ int rsnd_src_probe(struct rsnd_priv *priv) goto rsnd_src_probe_done; } - src = devm_kzalloc(dev, sizeof(*src) * nr, GFP_KERNEL); + src = devm_kcalloc(dev, nr, sizeof(*src), GFP_KERNEL); if (!src) { ret = -ENOMEM; goto rsnd_src_probe_done; diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index cae9ed6a0cdb..3eac3bc49e94 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -1112,7 +1112,7 @@ int rsnd_ssi_probe(struct rsnd_priv *priv) goto rsnd_ssi_probe_done; } - ssi = devm_kzalloc(dev, sizeof(*ssi) * nr, GFP_KERNEL); + ssi = devm_kcalloc(dev, nr, sizeof(*ssi), GFP_KERNEL); if (!ssi) { ret = -ENOMEM; goto rsnd_ssi_probe_done; diff --git a/sound/soc/sh/rcar/ssiu.c b/sound/soc/sh/rcar/ssiu.c index 5e5ed5475473..5f4469b67125 100644 --- a/sound/soc/sh/rcar/ssiu.c +++ b/sound/soc/sh/rcar/ssiu.c @@ -255,7 +255,7 @@ int rsnd_ssiu_probe(struct rsnd_priv *priv) /* same number to SSI */ nr = priv->ssi_nr; - ssiu = devm_kzalloc(dev, sizeof(*ssiu) * nr, GFP_KERNEL); + ssiu = devm_kcalloc(dev, nr, sizeof(*ssiu), GFP_KERNEL); if (!ssiu) return -ENOMEM; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 9de75e5a0b3f..1c6858be01ce 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -4094,7 +4094,7 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, return -EINVAL; } - routes = devm_kzalloc(card->dev, num_routes * sizeof(*routes), + routes = devm_kcalloc(card->dev, num_routes, sizeof(*routes), GFP_KERNEL); if (!routes) { dev_err(card->dev, @@ -4446,8 +4446,8 @@ int snd_soc_of_get_dai_link_codecs(struct device *dev, dev_err(dev, "Bad phandle in 'sound-dai'\n"); return num_codecs; } - component = devm_kzalloc(dev, - sizeof *component * num_codecs, + component = devm_kcalloc(dev, + num_codecs, sizeof(*component), GFP_KERNEL); if (!component) return -ENOMEM; diff --git a/techpack/audio/4.0/asoc/codecs/bolero/bolero-cdc.c b/techpack/audio/4.0/asoc/codecs/bolero/bolero-cdc.c index a09bbaec5f56..bfecc5651ee3 100644 --- a/techpack/audio/4.0/asoc/codecs/bolero/bolero-cdc.c +++ b/techpack/audio/4.0/asoc/codecs/bolero/bolero-cdc.c @@ -389,10 +389,9 @@ static int bolero_copy_dais_from_macro(struct bolero_priv *priv) /* memcpy into bolero_dais all macro dais */ if (!priv->bolero_dais) - priv->bolero_dais = devm_kzalloc(priv->dev, - priv->num_dais * - sizeof( - struct snd_soc_dai_driver), + priv->bolero_dais = devm_kcalloc(priv->dev, + priv->num_dais, + sizeof(struct snd_soc_dai_driver), GFP_KERNEL); if (!priv->bolero_dais) return -ENOMEM; diff --git a/techpack/audio/4.0/asoc/codecs/bolero/bolero-clk-rsc.c b/techpack/audio/4.0/asoc/codecs/bolero/bolero-clk-rsc.c index b134819e0c16..54f2ac6a6daf 100644 --- a/techpack/audio/4.0/asoc/codecs/bolero/bolero-clk-rsc.c +++ b/techpack/audio/4.0/asoc/codecs/bolero/bolero-clk-rsc.c @@ -640,7 +640,7 @@ static int bolero_clk_rsc_probe(struct platform_device *pdev) ret = -EINVAL; goto err; } - clk_name_array = devm_kzalloc(&pdev->dev, clk_cnt * sizeof(char *), + clk_name_array = devm_kcalloc(&pdev->dev, clk_cnt, sizeof(char *), GFP_KERNEL); if (!clk_name_array) { ret = -ENOMEM; diff --git a/techpack/audio/4.0/asoc/msm-dai-slim.c b/techpack/audio/4.0/asoc/msm-dai-slim.c index 545590fa3735..3bebf565c2f0 100644 --- a/techpack/audio/4.0/asoc/msm-dai-slim.c +++ b/techpack/audio/4.0/asoc/msm-dai-slim.c @@ -492,8 +492,8 @@ static int msm_dai_slim_populate_dai_data(struct device *dev, SET_DAI_STATE(dai_data_t->status, DAI_STATE_INITIALIZED); - dai_data_t->chan_h = devm_kzalloc(dev, - sizeof(u16) * num_ch, + dai_data_t->chan_h = devm_kcalloc(dev, + num_ch, sizeof(u16), GFP_KERNEL); if (!dai_data_t->chan_h) { dev_err(dev, @@ -503,8 +503,8 @@ static int msm_dai_slim_populate_dai_data(struct device *dev, goto err_mem_alloc; } - dai_data_t->sh_ch = devm_kzalloc(dev, - sizeof(u16) * num_ch, + dai_data_t->sh_ch = devm_kcalloc(dev, + num_ch, sizeof(u16), GFP_KERNEL); if (!dai_data_t->sh_ch) { dev_err(dev, diff --git a/techpack/audio/4.0/dsp/adsp-loader.c b/techpack/audio/4.0/dsp/adsp-loader.c index c0dbe3f4f438..673fbff0eb14 100644 --- a/techpack/audio/4.0/dsp/adsp-loader.c +++ b/techpack/audio/4.0/dsp/adsp-loader.c @@ -371,8 +371,8 @@ static int adsp_loader_probe(struct platform_device *pdev) goto wqueue; } - adsp_fw_bit_values = devm_kzalloc(&pdev->dev, - adsp_fw_cnt * sizeof(u32), GFP_KERNEL); + adsp_fw_bit_values = devm_kcalloc(&pdev->dev, + adsp_fw_cnt, sizeof(u32), GFP_KERNEL); if (!adsp_fw_bit_values) goto wqueue; @@ -387,8 +387,8 @@ static int adsp_loader_probe(struct platform_device *pdev) goto wqueue; } - adsp_fw_name_array = devm_kzalloc(&pdev->dev, - adsp_fw_cnt * sizeof(char *), GFP_KERNEL); + adsp_fw_name_array = devm_kcalloc(&pdev->dev, + adsp_fw_cnt, sizeof(char *), GFP_KERNEL); if (!adsp_fw_name_array) goto wqueue; diff --git a/techpack/audio/4.0/soc/pinctrl-wcd.c b/techpack/audio/4.0/soc/pinctrl-wcd.c index 437563f0a8a0..ff4c4718b8ab 100644 --- a/techpack/audio/4.0/soc/pinctrl-wcd.c +++ b/techpack/audio/4.0/soc/pinctrl-wcd.c @@ -331,7 +331,8 @@ static int wcd_pinctrl_probe(struct platform_device *pdev) goto err_name_alloc; } for (i = 0; i < npins; i++, pindesc++) { - name[i] = devm_kzalloc(dev, sizeof(char) * WCD_GPIO_STRING_LEN, + name[i] = devm_kzalloc(dev, + WCD_GPIO_STRING_LEN, GFP_KERNEL); if (!name[i]) { ret = -ENOMEM; diff --git a/techpack/audio/4.0/soc/swr-mstr-ctrl.c b/techpack/audio/4.0/soc/swr-mstr-ctrl.c index 847c90d71fb3..cfb6777cc30f 100644 --- a/techpack/audio/4.0/soc/swr-mstr-ctrl.c +++ b/techpack/audio/4.0/soc/swr-mstr-ctrl.c @@ -3204,8 +3204,8 @@ static int swrm_alloc_port_mem(struct device *dev, struct swr_mstr_ctrl *swrm, u32 uc, u32 size) { if (!swrm->port_param) { - swrm->port_param = devm_kzalloc(dev, - sizeof(swrm->port_param) * SWR_UC_MAX, + swrm->port_param = devm_kcalloc(dev, + SWR_UC_MAX, sizeof(swrm->port_param), GFP_KERNEL); if (!swrm->port_param) return -ENOMEM; diff --git a/techpack/audio/asoc/codecs/bolero/bolero-cdc.c b/techpack/audio/asoc/codecs/bolero/bolero-cdc.c index 02998fc4373a..7d5b1ccb0d58 100644 --- a/techpack/audio/asoc/codecs/bolero/bolero-cdc.c +++ b/techpack/audio/asoc/codecs/bolero/bolero-cdc.c @@ -288,10 +288,9 @@ static int bolero_copy_dais_from_macro(struct bolero_priv *priv) /* memcpy into bolero_dais all macro dais */ if (!priv->bolero_dais) - priv->bolero_dais = devm_kzalloc(priv->dev, - priv->num_dais * - sizeof( - struct snd_soc_dai_driver), + priv->bolero_dais = devm_kcalloc(priv->dev, + priv->num_dais, + sizeof(struct snd_soc_dai_driver), GFP_KERNEL); if (!priv->bolero_dais) return -ENOMEM; diff --git a/techpack/audio/asoc/codecs/sdm660_cdc/msm-analog-cdc.c b/techpack/audio/asoc/codecs/sdm660_cdc/msm-analog-cdc.c index abfa4b7e3f44..26827fb00075 100644 --- a/techpack/audio/asoc/codecs/sdm660_cdc/msm-analog-cdc.c +++ b/techpack/audio/asoc/codecs/sdm660_cdc/msm-analog-cdc.c @@ -4313,9 +4313,9 @@ static int msm_anlg_cdc_init_supplies(struct sdm660_cdc_priv *sdm660_cdc, int ret; int i; - sdm660_cdc->supplies = devm_kzalloc(sdm660_cdc->dev, - sizeof(struct regulator_bulk_data) * + sdm660_cdc->supplies = devm_kcalloc(sdm660_cdc->dev, ARRAY_SIZE(pdata->regulator), + sizeof(struct regulator_bulk_data), GFP_KERNEL); if (!sdm660_cdc->supplies) { ret = -ENOMEM; diff --git a/techpack/audio/asoc/msm-dai-slim.c b/techpack/audio/asoc/msm-dai-slim.c index e8bdf13fdc6c..906a86f6b007 100644 --- a/techpack/audio/asoc/msm-dai-slim.c +++ b/techpack/audio/asoc/msm-dai-slim.c @@ -500,8 +500,8 @@ static int msm_dai_slim_populate_dai_data(struct device *dev, SET_DAI_STATE(dai_data_t->status, DAI_STATE_INITIALIZED); - dai_data_t->chan_h = devm_kzalloc(dev, - sizeof(u16) * num_ch, + dai_data_t->chan_h = devm_kcalloc(dev, + num_ch, sizeof(u16), GFP_KERNEL); if (!dai_data_t->chan_h) { dev_err(dev, @@ -511,8 +511,8 @@ static int msm_dai_slim_populate_dai_data(struct device *dev, goto err_mem_alloc; } - dai_data_t->sh_ch = devm_kzalloc(dev, - sizeof(u16) * num_ch, + dai_data_t->sh_ch = devm_kcalloc(dev, + num_ch, sizeof(u16), GFP_KERNEL); if (!dai_data_t->sh_ch) { dev_err(dev, diff --git a/techpack/audio/soc/pinctrl-wcd.c b/techpack/audio/soc/pinctrl-wcd.c index d7695dbe77b8..18881f09d566 100644 --- a/techpack/audio/soc/pinctrl-wcd.c +++ b/techpack/audio/soc/pinctrl-wcd.c @@ -339,7 +339,8 @@ static int wcd_pinctrl_probe(struct platform_device *pdev) goto err_name_alloc; } for (i = 0; i < npins; i++, pindesc++) { - name[i] = devm_kzalloc(dev, sizeof(char) * WCD_GPIO_STRING_LEN, + name[i] = devm_kzalloc(dev, + WCD_GPIO_STRING_LEN, GFP_KERNEL); if (!name[i]) { ret = -ENOMEM; From f0a8bd5618c9dc3fd8cb43e372401e73fe72ae54 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 12 Jun 2018 14:27:11 -0700 Subject: [PATCH 580/592] treewide: Use array_size() in vmalloc() The vmalloc() function has no 2-factor argument form, so multiplication factors need to be wrapped in array_size(). This patch replaces cases of: vmalloc(a * b) with: vmalloc(array_size(a, b)) as well as handling cases of: vmalloc(a * b * c) with: vmalloc(array3_size(a, b, c)) This does, however, attempt to ignore constant size factors like: vmalloc(4 * 1024) though any constants defined via macros get caught up in the conversion. Any factors with a sizeof() of "unsigned char", "char", and "u8" were dropped, since they're redundant. The Coccinelle script used for this was: // Fix redundant parens around sizeof(). @@ type TYPE; expression THING, E; @@ ( vmalloc( - (sizeof(TYPE)) * E + sizeof(TYPE) * E , ...) | vmalloc( - (sizeof(THING)) * E + sizeof(THING) * E , ...) ) // Drop single-byte sizes and redundant parens. @@ expression COUNT; typedef u8; typedef __u8; @@ ( vmalloc( - sizeof(u8) * (COUNT) + COUNT , ...) | vmalloc( - sizeof(__u8) * (COUNT) + COUNT , ...) | vmalloc( - sizeof(char) * (COUNT) + COUNT , ...) | vmalloc( - sizeof(unsigned char) * (COUNT) + COUNT , ...) | vmalloc( - sizeof(u8) * COUNT + COUNT , ...) | vmalloc( - sizeof(__u8) * COUNT + COUNT , ...) | vmalloc( - sizeof(char) * COUNT + COUNT , ...) | vmalloc( - sizeof(unsigned char) * COUNT + COUNT , ...) ) // 2-factor product with sizeof(type/expression) and identifier or constant. @@ type TYPE; expression THING; identifier COUNT_ID; constant COUNT_CONST; @@ ( vmalloc( - sizeof(TYPE) * (COUNT_ID) + array_size(COUNT_ID, sizeof(TYPE)) , ...) | vmalloc( - sizeof(TYPE) * COUNT_ID + array_size(COUNT_ID, sizeof(TYPE)) , ...) | vmalloc( - sizeof(TYPE) * (COUNT_CONST) + array_size(COUNT_CONST, sizeof(TYPE)) , ...) | vmalloc( - sizeof(TYPE) * COUNT_CONST + array_size(COUNT_CONST, sizeof(TYPE)) , ...) | vmalloc( - sizeof(THING) * (COUNT_ID) + array_size(COUNT_ID, sizeof(THING)) , ...) | vmalloc( - sizeof(THING) * COUNT_ID + array_size(COUNT_ID, sizeof(THING)) , ...) | vmalloc( - sizeof(THING) * (COUNT_CONST) + array_size(COUNT_CONST, sizeof(THING)) , ...) | vmalloc( - sizeof(THING) * COUNT_CONST + array_size(COUNT_CONST, sizeof(THING)) , ...) ) // 2-factor product, only identifiers. @@ identifier SIZE, COUNT; @@ vmalloc( - SIZE * COUNT + array_size(COUNT, SIZE) , ...) // 3-factor product with 1 sizeof(type) or sizeof(expression), with // redundant parens removed. @@ expression THING; identifier STRIDE, COUNT; type TYPE; @@ ( vmalloc( - sizeof(TYPE) * (COUNT) * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | vmalloc( - sizeof(TYPE) * (COUNT) * STRIDE + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | vmalloc( - sizeof(TYPE) * COUNT * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | vmalloc( - sizeof(TYPE) * COUNT * STRIDE + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | vmalloc( - sizeof(THING) * (COUNT) * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) | vmalloc( - sizeof(THING) * (COUNT) * STRIDE + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) | vmalloc( - sizeof(THING) * COUNT * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) | vmalloc( - sizeof(THING) * COUNT * STRIDE + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) ) // 3-factor product with 2 sizeof(variable), with redundant parens removed. @@ expression THING1, THING2; identifier COUNT; type TYPE1, TYPE2; @@ ( vmalloc( - sizeof(TYPE1) * sizeof(TYPE2) * COUNT + array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2)) , ...) | vmalloc( - sizeof(TYPE1) * sizeof(THING2) * (COUNT) + array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2)) , ...) | vmalloc( - sizeof(THING1) * sizeof(THING2) * COUNT + array3_size(COUNT, sizeof(THING1), sizeof(THING2)) , ...) | vmalloc( - sizeof(THING1) * sizeof(THING2) * (COUNT) + array3_size(COUNT, sizeof(THING1), sizeof(THING2)) , ...) | vmalloc( - sizeof(TYPE1) * sizeof(THING2) * COUNT + array3_size(COUNT, sizeof(TYPE1), sizeof(THING2)) , ...) | vmalloc( - sizeof(TYPE1) * sizeof(THING2) * (COUNT) + array3_size(COUNT, sizeof(TYPE1), sizeof(THING2)) , ...) ) // 3-factor product, only identifiers, with redundant parens removed. @@ identifier STRIDE, SIZE, COUNT; @@ ( vmalloc( - (COUNT) * STRIDE * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) | vmalloc( - COUNT * (STRIDE) * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) | vmalloc( - COUNT * STRIDE * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | vmalloc( - (COUNT) * (STRIDE) * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) | vmalloc( - COUNT * (STRIDE) * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | vmalloc( - (COUNT) * STRIDE * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | vmalloc( - (COUNT) * (STRIDE) * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | vmalloc( - COUNT * STRIDE * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) ) // Any remaining multi-factor products, first at least 3-factor products // when they're not all constants... @@ expression E1, E2, E3; constant C1, C2, C3; @@ ( vmalloc(C1 * C2 * C3, ...) | vmalloc( - E1 * E2 * E3 + array3_size(E1, E2, E3) , ...) ) // And then all remaining 2 factors products when they're not all constants. @@ expression E1, E2; constant C1, C2; @@ ( vmalloc(C1 * C2, ...) | vmalloc( - E1 * E2 + array_size(E1, E2) , ...) ) Signed-off-by: Kees Cook Signed-off-by: Adam W. Willis Signed-off-by: UtsavBalar1231 --- arch/powerpc/kernel/rtasd.c | 2 +- arch/powerpc/kvm/book3s_64_mmu_hv.c | 2 +- arch/s390/hypfs/hypfs_diag.c | 2 +- arch/s390/kernel/module.c | 3 +-- arch/s390/kvm/gaccess.c | 2 +- arch/s390/kvm/kvm-s390.c | 2 +- arch/s390/kvm/sthyi.c | 2 +- arch/x86/kvm/cpuid.c | 3 +-- drivers/base/firmware_class.c | 2 +- drivers/dma/ipu/ipu_idmac.c | 2 +- drivers/gpu/drm/drm_memory.c | 2 +- drivers/gpu/drm/nouveau/nv84_fence.c | 2 +- drivers/gpu/drm/qxl/qxl_fb.c | 2 +- drivers/gpu/drm/radeon/radeon_gart.c | 3 +-- drivers/gpu/drm/selftests/test-drm_mm.c | 2 +- drivers/gpu/msm/adreno_cp_parser.c | 3 +-- drivers/iommu/io-pgtable-fast.c | 2 +- drivers/iommu/tegra-gart.c | 2 +- drivers/isdn/i4l/isdn_bsdcomp.c | 4 ++-- drivers/lightnvm/pblk-gc.c | 2 +- drivers/lightnvm/pblk-init.c | 2 +- drivers/lightnvm/rrpc.c | 3 +-- drivers/md/dm-cache-policy-smq.c | 2 +- drivers/md/dm-region-hash.c | 2 +- drivers/md/dm-switch.c | 2 +- drivers/md/dm-thin.c | 2 +- drivers/media/dvb-core/dmxdev.c | 2 +- drivers/media/dvb-core/dvb_demux.c | 7 +++---- drivers/media/pci/meye/meye.c | 2 +- drivers/media/pci/pt1/pt1.c | 2 +- drivers/media/pci/ttpci/av7110_ipack.c | 2 +- drivers/media/pci/zoran/zoran_driver.c | 2 +- .../platform/msm/dvb/demux/mpq_dmx_plugin_common.c | 3 +-- drivers/media/platform/soc_camera/soc_camera.c | 2 +- drivers/media/v4l2-core/videobuf-dma-sg.c | 2 +- drivers/mtd/ftl.c | 2 +- drivers/mtd/mtdoops.c | 3 +-- drivers/mtd/mtdswap.c | 4 ++-- drivers/mtd/nand/nandsim.c | 2 +- drivers/mtd/rfd_ftl.c | 2 +- drivers/net/ethernet/cavium/liquidio/request_manager.c | 3 +-- drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c | 2 +- drivers/net/ethernet/intel/igb/igb_ethtool.c | 6 ++---- drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c | 2 +- drivers/net/ethernet/intel/ixgbevf/ethtool.c | 4 ++-- drivers/net/ethernet/netronome/nfp/flower/metadata.c | 2 +- drivers/net/ppp/bsd_comp.c | 4 ++-- drivers/net/wireless/ath/ath5k/debug.c | 2 +- drivers/net/wireless/marvell/mwifiex/cfg80211.c | 3 +-- drivers/oprofile/event_buffer.c | 2 +- drivers/rapidio/devices/rio_mport_cdev.c | 2 +- drivers/scsi/fnic/fnic_debugfs.c | 5 ++--- drivers/scsi/fnic/fnic_trace.c | 9 +++------ drivers/scsi/ipr.c | 4 ++-- drivers/scsi/osst.c | 2 +- drivers/scsi/qla2xxx/tcm_qla2xxx.c | 3 +-- drivers/scsi/scsi_debug.c | 2 +- drivers/staging/android/ion/ion_heap.c | 2 +- drivers/staging/comedi/comedi_buf.c | 2 +- drivers/staging/greybus/camera.c | 3 +-- drivers/staging/media/lirc/lirc_zilog.c | 3 +-- .../utils/logging/src/wlan_logging_sock_svc.c | 2 +- .../staging/qca-wifi-host-cmn/utils/pktlog/linux_ac.c | 2 +- drivers/staging/rts5208/ms.c | 2 +- drivers/staging/rts5208/rtsx_chip.c | 2 +- drivers/usb/misc/sisusbvga/sisusb_con.c | 2 +- drivers/video/fbdev/msm/mdss_mdp_pp_cache_config.c | 3 +-- drivers/video/fbdev/xen-fbfront.c | 2 +- fs/binfmt_elf.c | 2 +- fs/cifs/misc.c | 4 ++-- fs/dlm/lockspace.c | 2 +- fs/reiserfs/bitmap.c | 2 +- fs/ubifs/lpt.c | 6 +++--- kernel/cgroup/cgroup-v1.c | 2 +- kernel/power/swap.c | 6 +++--- kernel/rcu/rcutorture.c | 3 +-- kernel/trace/tracing_map.c | 2 +- mm/percpu-stats.c | 2 +- net/bridge/netfilter/ebtables.c | 10 +++++----- net/netfilter/ipvs/ip_vs_conn.c | 2 +- sound/core/seq/seq_memory.c | 2 +- sound/oss/sequencer.c | 4 ++-- sound/pci/cs46xx/dsp_spos.c | 3 +-- sound/pci/emu10k1/emu10k1_main.c | 7 +++---- sound/pci/emu10k1/emufx.c | 2 +- sound/pci/emu10k1/p16v.c | 2 +- sound/pci/maestro3.c | 2 +- sound/pci/trident/trident_main.c | 2 +- virt/kvm/kvm_main.c | 2 +- 89 files changed, 112 insertions(+), 135 deletions(-) diff --git a/arch/powerpc/kernel/rtasd.c b/arch/powerpc/kernel/rtasd.c index 7caeae73348d..777566fcb5d9 100644 --- a/arch/powerpc/kernel/rtasd.c +++ b/arch/powerpc/kernel/rtasd.c @@ -548,7 +548,7 @@ static int __init rtas_event_scan_init(void) rtas_error_log_max = rtas_get_error_log_max(); rtas_error_log_buffer_max = rtas_error_log_max + sizeof(int); - rtas_log_buf = vmalloc(rtas_error_log_buffer_max*LOG_NUMBER); + rtas_log_buf = vmalloc(array_size(LOG_NUMBER, rtas_error_log_buffer_max)); if (!rtas_log_buf) { printk(KERN_ERR "rtasd: no memory\n"); return -ENOMEM; diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c index 7ac7e21b137e..39a00397d97b 100644 --- a/arch/powerpc/kvm/book3s_64_mmu_hv.c +++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c @@ -110,7 +110,7 @@ int kvmppc_allocate_hpt(struct kvm_hpt_info *info, u32 order) npte = 1ul << (order - 4); /* Allocate reverse map array */ - rev = vmalloc(sizeof(struct revmap_entry) * npte); + rev = vmalloc(array_size(npte, sizeof(struct revmap_entry))); if (!rev) { pr_err("kvmppc_allocate_hpt: Couldn't alloc reverse map array\n"); if (cma) diff --git a/arch/s390/hypfs/hypfs_diag.c b/arch/s390/hypfs/hypfs_diag.c index be8cc53204b5..a2945b289a29 100644 --- a/arch/s390/hypfs/hypfs_diag.c +++ b/arch/s390/hypfs/hypfs_diag.c @@ -239,7 +239,7 @@ static void *page_align_ptr(void *ptr) static void *diag204_alloc_vbuf(int pages) { /* The buffer has to be page aligned! */ - diag204_buf_vmalloc = vmalloc(PAGE_SIZE * (pages + 1)); + diag204_buf_vmalloc = vmalloc(array_size(PAGE_SIZE, (pages + 1))); if (!diag204_buf_vmalloc) return ERR_PTR(-ENOMEM); diag204_buf = page_align_ptr(diag204_buf_vmalloc); diff --git a/arch/s390/kernel/module.c b/arch/s390/kernel/module.c index b441e069e674..eb234eeae192 100644 --- a/arch/s390/kernel/module.c +++ b/arch/s390/kernel/module.c @@ -136,8 +136,7 @@ int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, /* Allocate one syminfo structure per symbol. */ me->arch.nsyms = symtab->sh_size / sizeof(Elf_Sym); - me->arch.syminfo = vmalloc(me->arch.nsyms * - sizeof(struct mod_arch_syminfo)); + me->arch.syminfo = vmalloc(array_size(sizeof(struct mod_arch_syminfo), me->arch.nsyms)); if (!me->arch.syminfo) return -ENOMEM; symbols = (void *) hdr + symtab->sh_offset; diff --git a/arch/s390/kvm/gaccess.c b/arch/s390/kvm/gaccess.c index c24bfa72baf7..f6df3b9820e5 100644 --- a/arch/s390/kvm/gaccess.c +++ b/arch/s390/kvm/gaccess.c @@ -847,7 +847,7 @@ int access_guest(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar, void *data, nr_pages = (((ga & ~PAGE_MASK) + len - 1) >> PAGE_SHIFT) + 1; pages = pages_array; if (nr_pages > ARRAY_SIZE(pages_array)) - pages = vmalloc(nr_pages * sizeof(unsigned long)); + pages = vmalloc(array_size(nr_pages, sizeof(unsigned long))); if (!pages) return -ENOMEM; need_ipte_lock = psw_bits(*psw).dat && !asce.r; diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 46fee3f4dedd..749158f2d1b3 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -1671,7 +1671,7 @@ static int kvm_s390_set_cmma_bits(struct kvm *kvm, if (args->count == 0) return 0; - bits = vmalloc(sizeof(*bits) * args->count); + bits = vmalloc(array_size(sizeof(*bits), args->count)); if (!bits) return -ENOMEM; diff --git a/arch/s390/kvm/sthyi.c b/arch/s390/kvm/sthyi.c index ffba4617d108..3fdf1962d3bf 100644 --- a/arch/s390/kvm/sthyi.c +++ b/arch/s390/kvm/sthyi.c @@ -308,7 +308,7 @@ static void fill_diag(struct sthyi_sctns *sctns) if (pages <= 0) return; - diag204_buf = vmalloc(PAGE_SIZE * pages); + diag204_buf = vmalloc(array_size(pages, PAGE_SIZE)); if (!diag204_buf) return; diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index 6ec1cfd0addd..41ff7444a2ff 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -198,8 +198,7 @@ int kvm_vcpu_ioctl_set_cpuid(struct kvm_vcpu *vcpu, goto out; r = -ENOMEM; if (cpuid->nent) { - cpuid_entries = vmalloc(sizeof(struct kvm_cpuid_entry) * - cpuid->nent); + cpuid_entries = vmalloc(array_size(sizeof(struct kvm_cpuid_entry), cpuid->nent)); if (!cpuid_entries) goto out; r = -EFAULT; diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 364181591f77..7d1cb5e59338 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -898,7 +898,7 @@ static int fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size) buf->page_array_size * 2); struct page **new_pages; - new_pages = vmalloc(new_array_size * sizeof(void *)); + new_pages = vmalloc(array_size(new_array_size, sizeof(void *))); if (!new_pages) { fw_load_abort(fw_priv); return -ENOMEM; diff --git a/drivers/dma/ipu/ipu_idmac.c b/drivers/dma/ipu/ipu_idmac.c index ed76044ce4b9..8fb7268fd53c 100644 --- a/drivers/dma/ipu/ipu_idmac.c +++ b/drivers/dma/ipu/ipu_idmac.c @@ -910,7 +910,7 @@ out: /* Called with ichan->chan_mutex held */ static int idmac_desc_alloc(struct idmac_channel *ichan, int n) { - struct idmac_tx_desc *desc = vmalloc(n * sizeof(struct idmac_tx_desc)); + struct idmac_tx_desc *desc = vmalloc(array_size(n, sizeof(struct idmac_tx_desc))); struct idmac *idmac = to_idmac(ichan->dma_chan.device); if (!desc) diff --git a/drivers/gpu/drm/drm_memory.c b/drivers/gpu/drm/drm_memory.c index fc0ebd273ef8..b3a37807629c 100644 --- a/drivers/gpu/drm/drm_memory.c +++ b/drivers/gpu/drm/drm_memory.c @@ -80,7 +80,7 @@ static void *agp_remap(unsigned long offset, unsigned long size, * page-table instead (that's probably faster anyhow...). */ /* note: use vmalloc() because num_pages could be large... */ - page_map = vmalloc(num_pages * sizeof(struct page *)); + page_map = vmalloc(array_size(num_pages, sizeof(struct page *))); if (!page_map) return NULL; diff --git a/drivers/gpu/drm/nouveau/nv84_fence.c b/drivers/gpu/drm/nouveau/nv84_fence.c index bd7a8a1e4ad9..4f70573163ad 100644 --- a/drivers/gpu/drm/nouveau/nv84_fence.c +++ b/drivers/gpu/drm/nouveau/nv84_fence.c @@ -155,7 +155,7 @@ nv84_fence_suspend(struct nouveau_drm *drm) struct nv84_fence_priv *priv = drm->fence; int i; - priv->suspend = vmalloc(priv->base.contexts * sizeof(u32)); + priv->suspend = vmalloc(array_size(sizeof(u32), priv->base.contexts)); if (priv->suspend) { for (i = 0; i < priv->base.contexts; i++) priv->suspend[i] = nouveau_bo_rd32(priv->bo, i*4); diff --git a/drivers/gpu/drm/qxl/qxl_fb.c b/drivers/gpu/drm/qxl/qxl_fb.c index 844c4a31ca13..70dfb847ab71 100644 --- a/drivers/gpu/drm/qxl/qxl_fb.c +++ b/drivers/gpu/drm/qxl/qxl_fb.c @@ -243,7 +243,7 @@ static int qxlfb_create(struct qxl_fbdev *qfbdev, QXL_INFO(qdev, "%s: %dx%d %d\n", __func__, mode_cmd.width, mode_cmd.height, mode_cmd.pitches[0]); - shadow = vmalloc(mode_cmd.pitches[0] * mode_cmd.height); + shadow = vmalloc(array_size(mode_cmd.pitches[0], mode_cmd.height)); /* TODO: what's the usual response to memory allocation errors? */ BUG_ON(!shadow); QXL_INFO(qdev, diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index 0b3ec35515f3..771b1fff1c2c 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c @@ -352,8 +352,7 @@ int radeon_gart_init(struct radeon_device *rdev) radeon_gart_fini(rdev); return -ENOMEM; } - rdev->gart.pages_entry = vmalloc(sizeof(uint64_t) * - rdev->gart.num_gpu_pages); + rdev->gart.pages_entry = vmalloc(array_size(sizeof(uint64_t), rdev->gart.num_gpu_pages)); if (rdev->gart.pages_entry == NULL) { radeon_gart_fini(rdev); return -ENOMEM; diff --git a/drivers/gpu/drm/selftests/test-drm_mm.c b/drivers/gpu/drm/selftests/test-drm_mm.c index 63a02c68a2c5..6e2609771f62 100644 --- a/drivers/gpu/drm/selftests/test-drm_mm.c +++ b/drivers/gpu/drm/selftests/test-drm_mm.c @@ -579,7 +579,7 @@ static int __igt_insert(unsigned int count, u64 size, bool replace) DRM_MM_BUG_ON(!size); ret = -ENOMEM; - nodes = vmalloc(count * sizeof(*nodes)); + nodes = vmalloc(array_size(count, sizeof(*nodes))); if (!nodes) goto err; diff --git a/drivers/gpu/msm/adreno_cp_parser.c b/drivers/gpu/msm/adreno_cp_parser.c index 3f484b98577d..58064925e6a5 100644 --- a/drivers/gpu/msm/adreno_cp_parser.c +++ b/drivers/gpu/msm/adreno_cp_parser.c @@ -1019,8 +1019,7 @@ int adreno_ib_create_object_list(struct kgsl_device *device, if (!ib_obj_list) return -ENOMEM; - ib_obj_list->obj_list = vmalloc(MAX_IB_OBJS * - sizeof(struct adreno_ib_object)); + ib_obj_list->obj_list = vmalloc(array_size(MAX_IB_OBJS, sizeof(struct adreno_ib_object))); if (!ib_obj_list->obj_list) { kfree(ib_obj_list); diff --git a/drivers/iommu/io-pgtable-fast.c b/drivers/iommu/io-pgtable-fast.c index 93d8c2d34b62..60977727f37f 100644 --- a/drivers/iommu/io-pgtable-fast.c +++ b/drivers/iommu/io-pgtable-fast.c @@ -442,7 +442,7 @@ av8l_fast_prepopulate_pgtables(struct av8l_fast_io_pgtable *data, __GFP_NORETRY); if (!pages) - pages = vmalloc(sizeof(*pages) * NUM_PGTBL_PAGES); + pages = vmalloc(array_size(NUM_PGTBL_PAGES, sizeof(*pages))); if (!pages) return -ENOMEM; diff --git a/drivers/iommu/tegra-gart.c b/drivers/iommu/tegra-gart.c index b62f790ad1ba..708ec771a92f 100644 --- a/drivers/iommu/tegra-gart.c +++ b/drivers/iommu/tegra-gart.c @@ -454,7 +454,7 @@ static int tegra_gart_probe(struct platform_device *pdev) gart->iovmm_base = (dma_addr_t)res_remap->start; gart->page_count = (resource_size(res_remap) >> GART_PAGE_SHIFT); - gart->savedata = vmalloc(sizeof(u32) * gart->page_count); + gart->savedata = vmalloc(array_size(sizeof(u32), gart->page_count)); if (!gart->savedata) { dev_err(dev, "failed to allocate context save area\n"); return -ENOMEM; diff --git a/drivers/isdn/i4l/isdn_bsdcomp.c b/drivers/isdn/i4l/isdn_bsdcomp.c index 99012c047751..891e0d96c409 100644 --- a/drivers/isdn/i4l/isdn_bsdcomp.c +++ b/drivers/isdn/i4l/isdn_bsdcomp.c @@ -340,7 +340,7 @@ static void *bsd_alloc(struct isdn_ppp_comp_data *data) * Allocate space for the dictionary. This may be more than one page in * length. */ - db->dict = vmalloc(hsize * sizeof(struct bsd_dict)); + db->dict = vmalloc(array_size(hsize, sizeof(struct bsd_dict))); if (!db->dict) { bsd_free(db); return NULL; @@ -353,7 +353,7 @@ static void *bsd_alloc(struct isdn_ppp_comp_data *data) if (!decomp) db->lens = NULL; else { - db->lens = vmalloc((maxmaxcode + 1) * sizeof(db->lens[0])); + db->lens = vmalloc(array_size(sizeof(db->lens[0]), (maxmaxcode + 1))); if (!db->lens) { bsd_free(db); return (NULL); diff --git a/drivers/lightnvm/pblk-gc.c b/drivers/lightnvm/pblk-gc.c index d6bae085e1d2..2814788265c8 100644 --- a/drivers/lightnvm/pblk-gc.c +++ b/drivers/lightnvm/pblk-gc.c @@ -72,7 +72,7 @@ static int pblk_gc_move_valid_secs(struct pblk *pblk, struct pblk_gc_rq *gc_rq) unsigned int secs_to_gc; int ret = 0; - data = vmalloc(gc_rq->nr_secs * geo->sec_size); + data = vmalloc(array_size(gc_rq->nr_secs, geo->sec_size)); if (!data) { ret = -ENOMEM; goto out; diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c index 1b75675ee67b..9d565ef34f20 100644 --- a/drivers/lightnvm/pblk-init.c +++ b/drivers/lightnvm/pblk-init.c @@ -90,7 +90,7 @@ static int pblk_l2p_init(struct pblk *pblk) if (pblk->ppaf_bitsize < 32) entry_size = 4; - pblk->trans_map = vmalloc(entry_size * pblk->rl.nr_secs); + pblk->trans_map = vmalloc(array_size(entry_size, pblk->rl.nr_secs)); if (!pblk->trans_map) return -ENOMEM; diff --git a/drivers/lightnvm/rrpc.c b/drivers/lightnvm/rrpc.c index 267f01ae87e4..edfb02d13469 100644 --- a/drivers/lightnvm/rrpc.c +++ b/drivers/lightnvm/rrpc.c @@ -1144,8 +1144,7 @@ static int rrpc_map_init(struct rrpc *rrpc) if (!rrpc->trans_map) return -ENOMEM; - rrpc->rev_trans_map = vmalloc(sizeof(struct rrpc_rev_addr) - * rrpc->nr_sects); + rrpc->rev_trans_map = vmalloc(array_size(sizeof(struct rrpc_rev_addr), rrpc->nr_sects)); if (!rrpc->rev_trans_map) return -ENOMEM; diff --git a/drivers/md/dm-cache-policy-smq.c b/drivers/md/dm-cache-policy-smq.c index e5eb9c9b4bc8..c9674d351448 100644 --- a/drivers/md/dm-cache-policy-smq.c +++ b/drivers/md/dm-cache-policy-smq.c @@ -575,7 +575,7 @@ static int h_init(struct smq_hash_table *ht, struct entry_space *es, unsigned nr nr_buckets = roundup_pow_of_two(max(nr_entries / 4u, 16u)); ht->hash_bits = __ffs(nr_buckets); - ht->buckets = vmalloc(sizeof(*ht->buckets) * nr_buckets); + ht->buckets = vmalloc(array_size(nr_buckets, sizeof(*ht->buckets))); if (!ht->buckets) return -ENOMEM; diff --git a/drivers/md/dm-region-hash.c b/drivers/md/dm-region-hash.c index 91c6f6d72eee..fb5582c7087e 100644 --- a/drivers/md/dm-region-hash.c +++ b/drivers/md/dm-region-hash.c @@ -201,7 +201,7 @@ struct dm_region_hash *dm_region_hash_create( rh->shift = RH_HASH_SHIFT; rh->prime = RH_HASH_MULT; - rh->buckets = vmalloc(nr_buckets * sizeof(*rh->buckets)); + rh->buckets = vmalloc(array_size(nr_buckets, sizeof(*rh->buckets))); if (!rh->buckets) { DMERR("unable to allocate region hash bucket memory"); kfree(rh); diff --git a/drivers/md/dm-switch.c b/drivers/md/dm-switch.c index 4c8de1ff78ca..56ff981570b0 100644 --- a/drivers/md/dm-switch.c +++ b/drivers/md/dm-switch.c @@ -114,7 +114,7 @@ static int alloc_region_table(struct dm_target *ti, unsigned nr_paths) return -EINVAL; } - sctx->region_table = vmalloc(nr_slots * sizeof(region_table_slot_t)); + sctx->region_table = vmalloc(array_size(nr_slots, sizeof(region_table_slot_t))); if (!sctx->region_table) { ti->error = "Cannot allocate region table"; return -ENOMEM; diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index 0ee5eae71690..7a8ec9bceeda 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c @@ -3041,7 +3041,7 @@ static struct pool *pool_create(struct mapped_device *pool_md, goto bad_mapping_pool; } - pool->cell_sort_array = vmalloc(sizeof(*pool->cell_sort_array) * CELL_SORT_ARRAY_SIZE); + pool->cell_sort_array = vmalloc(array_size(CELL_SORT_ARRAY_SIZE, sizeof(*pool->cell_sort_array))); if (!pool->cell_sort_array) { *error = "Error allocating cell sort array"; err_p = ERR_PTR(-ENOMEM); diff --git a/drivers/media/dvb-core/dmxdev.c b/drivers/media/dvb-core/dmxdev.c index ff6a5cf93eb8..436ecd3992ba 100644 --- a/drivers/media/dvb-core/dmxdev.c +++ b/drivers/media/dvb-core/dmxdev.c @@ -4848,7 +4848,7 @@ int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter) if (dmxdev->demux->open(dmxdev->demux) < 0) return -EUSERS; - dmxdev->filter = vmalloc(dmxdev->filternum * sizeof(struct dmxdev_filter)); + dmxdev->filter = vmalloc(array_size(sizeof(struct dmxdev_filter), dmxdev->filternum)); if (!dmxdev->filter) return -ENOMEM; diff --git a/drivers/media/dvb-core/dvb_demux.c b/drivers/media/dvb-core/dvb_demux.c index 99f47ab4064e..5a2ed4ac572b 100644 --- a/drivers/media/dvb-core/dvb_demux.c +++ b/drivers/media/dvb-core/dvb_demux.c @@ -3298,20 +3298,19 @@ int dvb_dmx_init(struct dvb_demux *dvbdemux) dvbdemux->cnt_storage = NULL; dvbdemux->users = 0; - dvbdemux->filter = vmalloc(dvbdemux->filternum * sizeof(struct dvb_demux_filter)); + dvbdemux->filter = vmalloc(array_size(sizeof(struct dvb_demux_filter), dvbdemux->filternum)); if (!dvbdemux->filter) return -ENOMEM; - dvbdemux->feed = vmalloc(dvbdemux->feednum * sizeof(struct dvb_demux_feed)); + dvbdemux->feed = vmalloc(array_size(sizeof(struct dvb_demux_feed), dvbdemux->feednum)); if (!dvbdemux->feed) { vfree(dvbdemux->filter); dvbdemux->filter = NULL; return -ENOMEM; } - dvbdemux->rec_info_pool = vmalloc(dvbdemux->feednum * - sizeof(struct dvb_demux_rec_info)); + dvbdemux->rec_info_pool = vmalloc(array_size(sizeof(struct dvb_demux_rec_info), dvbdemux->feednum)); if (!dvbdemux->rec_info_pool) { vfree(dvbdemux->feed); vfree(dvbdemux->filter); diff --git a/drivers/media/pci/meye/meye.c b/drivers/media/pci/meye/meye.c index 926707c997ac..dc0335e74d31 100644 --- a/drivers/media/pci/meye/meye.c +++ b/drivers/media/pci/meye/meye.c @@ -1625,7 +1625,7 @@ static int meye_probe(struct pci_dev *pcidev, const struct pci_device_id *ent) ret = -ENOMEM; meye.mchip_dev = pcidev; - meye.grab_temp = vmalloc(MCHIP_NB_PAGES_MJPEG * PAGE_SIZE); + meye.grab_temp = vmalloc(array_size(PAGE_SIZE, MCHIP_NB_PAGES_MJPEG)); if (!meye.grab_temp) { v4l2_err(v4l2_dev, "grab buffer allocation failed\n"); goto outvmalloc; diff --git a/drivers/media/pci/pt1/pt1.c b/drivers/media/pci/pt1/pt1.c index b6b1a8d20d86..b9c25fd2ccf1 100644 --- a/drivers/media/pci/pt1/pt1.c +++ b/drivers/media/pci/pt1/pt1.c @@ -443,7 +443,7 @@ static int pt1_init_tables(struct pt1 *pt1) int i, ret; u32 first_pfn, pfn; - tables = vmalloc(sizeof(struct pt1_table) * pt1_nr_tables); + tables = vmalloc(array_size(pt1_nr_tables, sizeof(struct pt1_table))); if (tables == NULL) return -ENOMEM; diff --git a/drivers/media/pci/ttpci/av7110_ipack.c b/drivers/media/pci/ttpci/av7110_ipack.c index 5aff26574fe1..ec528fae7333 100644 --- a/drivers/media/pci/ttpci/av7110_ipack.c +++ b/drivers/media/pci/ttpci/av7110_ipack.c @@ -24,7 +24,7 @@ void av7110_ipack_reset(struct ipack *p) int av7110_ipack_init(struct ipack *p, int size, void (*func)(u8 *buf, int size, void *priv)) { - if (!(p->buf = vmalloc(size*sizeof(u8)))) { + if (!(p->buf = vmalloc(size))) { printk(KERN_WARNING "Couldn't allocate memory for ipack\n"); return -ENOMEM; } diff --git a/drivers/media/pci/zoran/zoran_driver.c b/drivers/media/pci/zoran/zoran_driver.c index 1b74fb7bee48..ffb689e9dcfb 100644 --- a/drivers/media/pci/zoran/zoran_driver.c +++ b/drivers/media/pci/zoran/zoran_driver.c @@ -1220,7 +1220,7 @@ static int setup_window(struct zoran_fh *fh, } } else if (clipcount) { /* write our own bitmap from the clips */ - vcp = vmalloc(sizeof(struct v4l2_clip) * (clipcount + 4)); + vcp = vmalloc(array_size(sizeof(struct v4l2_clip), (clipcount + 4))); if (vcp == NULL) { dprintk(1, KERN_ERR diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c index 4cc9623b1b9a..7146d24c1f95 100644 --- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c +++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c @@ -3723,8 +3723,7 @@ static int mpq_sdmx_filter_setup(struct mpq_demux *mpq_demux, MPQ_DVB_DBG_PRINT("%s: SDMX_PES_FILTER\n", __func__); } - data_buff_desc = vmalloc( - sizeof(*data_buff_desc)*DMX_MAX_DECODER_BUFFER_NUM); + data_buff_desc = vmalloc(array_size(DMX_MAX_DECODER_BUFFER_NUM, sizeof(*data_buff_desc))); if (!data_buff_desc) { MPQ_DVB_ERR_PRINT( "%s: failed to allocate memory for data buffer\n", diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c index 1f3c450c7a69..d76477806d2d 100644 --- a/drivers/media/platform/soc_camera/soc_camera.c +++ b/drivers/media/platform/soc_camera/soc_camera.c @@ -481,7 +481,7 @@ static int soc_camera_init_user_formats(struct soc_camera_device *icd) return -ENXIO; icd->user_formats = - vmalloc(fmts * sizeof(struct soc_camera_format_xlate)); + vmalloc(array_size(fmts, sizeof(struct soc_camera_format_xlate))); if (!icd->user_formats) return -ENOMEM; diff --git a/drivers/media/v4l2-core/videobuf-dma-sg.c b/drivers/media/v4l2-core/videobuf-dma-sg.c index 6244ac97f343..10c78796c420 100644 --- a/drivers/media/v4l2-core/videobuf-dma-sg.c +++ b/drivers/media/v4l2-core/videobuf-dma-sg.c @@ -100,7 +100,7 @@ static struct scatterlist *videobuf_pages_to_sg(struct page **pages, if (NULL == pages[0]) return NULL; - sglist = vmalloc(nr_pages * sizeof(*sglist)); + sglist = vmalloc(array_size(nr_pages, sizeof(*sglist))); if (NULL == sglist) return NULL; sg_init_table(sglist, nr_pages); diff --git a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c index 132f36bf8e2a..cccdbc02c85a 100644 --- a/drivers/mtd/ftl.c +++ b/drivers/mtd/ftl.c @@ -269,7 +269,7 @@ static int build_maps(partition_t *part) /* Set up virtual page map */ blocks = le32_to_cpu(header.FormattedSize) >> header.BlockSize; - part->VirtualBlockMap = vmalloc(blocks * sizeof(uint32_t)); + part->VirtualBlockMap = vmalloc(array_size(blocks, sizeof(uint32_t))); if (!part->VirtualBlockMap) goto out_XferInfo; diff --git a/drivers/mtd/mtdoops.c b/drivers/mtd/mtdoops.c index 97bb8f6304d4..4bdeb598b02b 100644 --- a/drivers/mtd/mtdoops.c +++ b/drivers/mtd/mtdoops.c @@ -350,8 +350,7 @@ static void mtdoops_notify_add(struct mtd_info *mtd) } /* oops_page_used is a bit field */ - cxt->oops_page_used = vmalloc(DIV_ROUND_UP(mtdoops_pages, - BITS_PER_LONG) * sizeof(unsigned long)); + cxt->oops_page_used = vmalloc(array_size(sizeof(unsigned long), DIV_ROUND_UP(mtdoops_pages, BITS_PER_LONG))); if (!cxt->oops_page_used) { printk(KERN_ERR "mtdoops: could not allocate page array\n"); return; diff --git a/drivers/mtd/mtdswap.c b/drivers/mtd/mtdswap.c index d4282df0253e..dde9168feae2 100644 --- a/drivers/mtd/mtdswap.c +++ b/drivers/mtd/mtdswap.c @@ -1350,11 +1350,11 @@ static int mtdswap_init(struct mtdswap_dev *d, unsigned int eblocks, for (i = 0; i < MTDSWAP_TREE_CNT; i++) d->trees[i].root = RB_ROOT; - d->page_data = vmalloc(sizeof(int)*pages); + d->page_data = vmalloc(array_size(pages, sizeof(int))); if (!d->page_data) goto page_data_fail; - d->revmap = vmalloc(sizeof(int)*blocks); + d->revmap = vmalloc(array_size(blocks, sizeof(int))); if (!d->revmap) goto revmap_fail; diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index dbb0e47f5197..ed7332b135a0 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c @@ -583,7 +583,7 @@ static int __init alloc_device(struct nandsim *ns) return 0; } - ns->pages = vmalloc(ns->geom.pgnum * sizeof(union ns_mem)); + ns->pages = vmalloc(array_size(sizeof(union ns_mem), ns->geom.pgnum)); if (!ns->pages) { NS_ERR("alloc_device: unable to allocate page array\n"); return -ENOMEM; diff --git a/drivers/mtd/rfd_ftl.c b/drivers/mtd/rfd_ftl.c index d1cbf26db2c0..f2c788bec94f 100644 --- a/drivers/mtd/rfd_ftl.c +++ b/drivers/mtd/rfd_ftl.c @@ -189,7 +189,7 @@ static int scan_header(struct partition *part) if (!part->blocks) goto err; - part->sector_map = vmalloc(part->sector_count * sizeof(u_long)); + part->sector_map = vmalloc(array_size(sizeof(u_long), part->sector_count)); if (!part->sector_map) { printk(KERN_ERR PREFIX "'%s': unable to allocate memory for " "sector map", part->mbd.mtd->name); diff --git a/drivers/net/ethernet/cavium/liquidio/request_manager.c b/drivers/net/ethernet/cavium/liquidio/request_manager.c index 0ea623768783..ad7e451ae14d 100644 --- a/drivers/net/ethernet/cavium/liquidio/request_manager.c +++ b/drivers/net/ethernet/cavium/liquidio/request_manager.c @@ -98,8 +98,7 @@ int octeon_init_instr_queue(struct octeon_device *oct, iq->request_list = vmalloc_node((sizeof(*iq->request_list) * num_descs), numa_node); if (!iq->request_list) - iq->request_list = vmalloc(sizeof(*iq->request_list) * - num_descs); + iq->request_list = vmalloc(array_size(num_descs, sizeof(*iq->request_list))); if (!iq->request_list) { lio_dma_free(oct, q_size, iq->base_addr, iq->base_addr_dma); dev_err(&oct->pci_dev->dev, "Alloc failed for IQ[%d] nr free list\n", diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c b/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c index c7234f35f8ff..42778f53d475 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c @@ -577,7 +577,7 @@ static int fm10k_set_ringparam(struct net_device *netdev, /* allocate temporary buffer to store rings in */ i = max_t(int, interface->num_tx_queues, interface->num_rx_queues); - temp_ring = vmalloc(i * sizeof(struct fm10k_ring)); + temp_ring = vmalloc(array_size(i, sizeof(struct fm10k_ring))); if (!temp_ring) { err = -ENOMEM; diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c index bd8102ded442..98f3264d2e1e 100644 --- a/drivers/net/ethernet/intel/igb/igb_ethtool.c +++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c @@ -923,11 +923,9 @@ static int igb_set_ringparam(struct net_device *netdev, } if (adapter->num_tx_queues > adapter->num_rx_queues) - temp_ring = vmalloc(adapter->num_tx_queues * - sizeof(struct igb_ring)); + temp_ring = vmalloc(array_size(sizeof(struct igb_ring), adapter->num_tx_queues)); else - temp_ring = vmalloc(adapter->num_rx_queues * - sizeof(struct igb_ring)); + temp_ring = vmalloc(array_size(sizeof(struct igb_ring), adapter->num_rx_queues)); if (!temp_ring) { err = -ENOMEM; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c index 94d6f8bb9687..329ec6d8db00 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c @@ -1087,7 +1087,7 @@ static int ixgbe_set_ringparam(struct net_device *netdev, /* allocate temporary buffer to store rings in */ i = max_t(int, adapter->num_tx_queues + adapter->num_xdp_queues, adapter->num_rx_queues); - temp_ring = vmalloc(i * sizeof(struct ixgbe_ring)); + temp_ring = vmalloc(array_size(i, sizeof(struct ixgbe_ring))); if (!temp_ring) { err = -ENOMEM; diff --git a/drivers/net/ethernet/intel/ixgbevf/ethtool.c b/drivers/net/ethernet/intel/ixgbevf/ethtool.c index ff9d05f308ee..35bd7f8fa1d9 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ethtool.c +++ b/drivers/net/ethernet/intel/ixgbevf/ethtool.c @@ -289,7 +289,7 @@ static int ixgbevf_set_ringparam(struct net_device *netdev, } if (new_tx_count != adapter->tx_ring_count) { - tx_ring = vmalloc(adapter->num_tx_queues * sizeof(*tx_ring)); + tx_ring = vmalloc(array_size(sizeof(*tx_ring), adapter->num_tx_queues)); if (!tx_ring) { err = -ENOMEM; goto clear_reset; @@ -315,7 +315,7 @@ static int ixgbevf_set_ringparam(struct net_device *netdev, } if (new_rx_count != adapter->rx_ring_count) { - rx_ring = vmalloc(adapter->num_rx_queues * sizeof(*rx_ring)); + rx_ring = vmalloc(array_size(sizeof(*rx_ring), adapter->num_rx_queues)); if (!rx_ring) { err = -ENOMEM; goto clear_reset; diff --git a/drivers/net/ethernet/netronome/nfp/flower/metadata.c b/drivers/net/ethernet/netronome/nfp/flower/metadata.c index d9582ccc0025..18f46aa23622 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/metadata.c +++ b/drivers/net/ethernet/netronome/nfp/flower/metadata.c @@ -413,7 +413,7 @@ int nfp_flower_metadata_init(struct nfp_app *app) /* Init ring buffer and unallocated stats_ids. */ priv->stats_ids.free_list.buf = - vmalloc(NFP_FL_STATS_ENTRY_RS * NFP_FL_STATS_ELEM_RS); + vmalloc(array_size(NFP_FL_STATS_ELEM_RS, NFP_FL_STATS_ENTRY_RS)); if (!priv->stats_ids.free_list.buf) goto err_free_last_used; diff --git a/drivers/net/ppp/bsd_comp.c b/drivers/net/ppp/bsd_comp.c index a9b759add187..61fedb23d3cf 100644 --- a/drivers/net/ppp/bsd_comp.c +++ b/drivers/net/ppp/bsd_comp.c @@ -406,7 +406,7 @@ static void *bsd_alloc (unsigned char *options, int opt_len, int decomp) * Allocate space for the dictionary. This may be more than one page in * length. */ - db->dict = vmalloc(hsize * sizeof(struct bsd_dict)); + db->dict = vmalloc(array_size(hsize, sizeof(struct bsd_dict))); if (!db->dict) { bsd_free (db); @@ -425,7 +425,7 @@ static void *bsd_alloc (unsigned char *options, int opt_len, int decomp) */ else { - db->lens = vmalloc((maxmaxcode + 1) * sizeof(db->lens[0])); + db->lens = vmalloc(array_size(sizeof(db->lens[0]), (maxmaxcode + 1))); if (!db->lens) { bsd_free (db); diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c index bd7f6d7b199e..c607ee9275e8 100644 --- a/drivers/net/wireless/ath/ath5k/debug.c +++ b/drivers/net/wireless/ath/ath5k/debug.c @@ -931,7 +931,7 @@ static int open_file_eeprom(struct inode *inode, struct file *file) /* Create buffer and read in eeprom */ - buf = vmalloc(eesize * 2); + buf = vmalloc(array_size(eesize, 2)); if (!buf) { ret = -ENOMEM; goto err; diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c index 79c50aebffc4..4eb0615a24b6 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c @@ -4220,8 +4220,7 @@ int mwifiex_init_channel_scan_gap(struct mwifiex_adapter *adapter) n_channels_a = mwifiex_band_5ghz.n_channels; adapter->num_in_chan_stats = n_channels_bg + n_channels_a; - adapter->chan_stats = vmalloc(sizeof(*adapter->chan_stats) * - adapter->num_in_chan_stats); + adapter->chan_stats = vmalloc(array_size(sizeof(*adapter->chan_stats), adapter->num_in_chan_stats)); if (!adapter->chan_stats) return -ENOMEM; diff --git a/drivers/oprofile/event_buffer.c b/drivers/oprofile/event_buffer.c index 32888f2bd1a9..12ea4a4ad607 100644 --- a/drivers/oprofile/event_buffer.c +++ b/drivers/oprofile/event_buffer.c @@ -91,7 +91,7 @@ int alloc_event_buffer(void) return -EINVAL; buffer_pos = 0; - event_buffer = vmalloc(sizeof(unsigned long) * buffer_size); + event_buffer = vmalloc(array_size(buffer_size, sizeof(unsigned long))); if (!event_buffer) return -ENOMEM; diff --git a/drivers/rapidio/devices/rio_mport_cdev.c b/drivers/rapidio/devices/rio_mport_cdev.c index f15f6d1e1070..d802389acee2 100644 --- a/drivers/rapidio/devices/rio_mport_cdev.c +++ b/drivers/rapidio/devices/rio_mport_cdev.c @@ -1032,7 +1032,7 @@ static int rio_mport_transfer_ioctl(struct file *filp, void __user *arg) priv->md->properties.transfer_mode) == 0) return -ENODEV; - transfer = vmalloc(transaction.count * sizeof(*transfer)); + transfer = vmalloc(array_size(sizeof(*transfer), transaction.count)); if (!transfer) return -ENOMEM; diff --git a/drivers/scsi/fnic/fnic_debugfs.c b/drivers/scsi/fnic/fnic_debugfs.c index 5e3d909cfc53..997b76ffa948 100644 --- a/drivers/scsi/fnic/fnic_debugfs.c +++ b/drivers/scsi/fnic/fnic_debugfs.c @@ -251,8 +251,7 @@ static int fnic_trace_debugfs_open(struct inode *inode, return -ENOMEM; if (*rdata_ptr == fc_trc_flag->fnic_trace) { - fnic_dbg_prt->buffer = vmalloc(3 * - (trace_max_pages * PAGE_SIZE)); + fnic_dbg_prt->buffer = vmalloc(array_size(3, (trace_max_pages * PAGE_SIZE))); if (!fnic_dbg_prt->buffer) { kfree(fnic_dbg_prt); return -ENOMEM; @@ -262,7 +261,7 @@ static int fnic_trace_debugfs_open(struct inode *inode, fnic_dbg_prt->buffer_len = fnic_get_trace_data(fnic_dbg_prt); } else { fnic_dbg_prt->buffer = - vmalloc(3 * (fnic_fc_trace_max_pages * PAGE_SIZE)); + vmalloc(array_size(3, (fnic_fc_trace_max_pages * PAGE_SIZE))); if (!fnic_dbg_prt->buffer) { kfree(fnic_dbg_prt); return -ENOMEM; diff --git a/drivers/scsi/fnic/fnic_trace.c b/drivers/scsi/fnic/fnic_trace.c index 4826f596cb31..96670da466e2 100644 --- a/drivers/scsi/fnic/fnic_trace.c +++ b/drivers/scsi/fnic/fnic_trace.c @@ -477,8 +477,7 @@ int fnic_trace_buf_init(void) } memset((void *)fnic_trace_buf_p, 0, (trace_max_pages * PAGE_SIZE)); - fnic_trace_entries.page_offset = vmalloc(fnic_max_trace_entries * - sizeof(unsigned long)); + fnic_trace_entries.page_offset = vmalloc(array_size(fnic_max_trace_entries, sizeof(unsigned long))); if (!fnic_trace_entries.page_offset) { printk(KERN_ERR PFX "Failed to allocate memory for" " page_offset\n"); @@ -555,8 +554,7 @@ int fnic_fc_trace_init(void) fc_trace_max_entries = (fnic_fc_trace_max_pages * PAGE_SIZE)/ FC_TRC_SIZE_BYTES; - fnic_fc_ctlr_trace_buf_p = (unsigned long)vmalloc( - fnic_fc_trace_max_pages * PAGE_SIZE); + fnic_fc_ctlr_trace_buf_p = (unsigned long)vmalloc(array_size(PAGE_SIZE, fnic_fc_trace_max_pages)); if (!fnic_fc_ctlr_trace_buf_p) { pr_err("fnic: Failed to allocate memory for " "FC Control Trace Buf\n"); @@ -568,8 +566,7 @@ int fnic_fc_trace_init(void) fnic_fc_trace_max_pages * PAGE_SIZE); /* Allocate memory for page offset */ - fc_trace_entries.page_offset = vmalloc(fc_trace_max_entries * - sizeof(unsigned long)); + fc_trace_entries.page_offset = vmalloc(array_size(fc_trace_max_entries, sizeof(unsigned long))); if (!fc_trace_entries.page_offset) { pr_err("fnic:Failed to allocate memory for page_offset\n"); if (fnic_fc_ctlr_trace_buf_p) { diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 1d2fce8941c8..2d8ec317b662 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -4376,9 +4376,9 @@ static int ipr_alloc_dump(struct ipr_ioa_cfg *ioa_cfg) } if (ioa_cfg->sis64) - ioa_data = vmalloc(IPR_FMT3_MAX_NUM_DUMP_PAGES * sizeof(__be32 *)); + ioa_data = vmalloc(array_size(IPR_FMT3_MAX_NUM_DUMP_PAGES, sizeof(__be32 *))); else - ioa_data = vmalloc(IPR_FMT2_MAX_NUM_DUMP_PAGES * sizeof(__be32 *)); + ioa_data = vmalloc(array_size(IPR_FMT2_MAX_NUM_DUMP_PAGES, sizeof(__be32 *))); if (!ioa_data) { ipr_err("Dump memory allocation failed\n"); diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index b78158d8cab8..95400fc22bb0 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c @@ -1488,7 +1488,7 @@ static int osst_read_back_buffer_and_rewrite(struct osst_tape * STp, struct osst int dbg = debugging; #endif - if ((buffer = vmalloc((nframes + 1) * OS_DATA_SIZE)) == NULL) + if ((buffer = vmalloc(array_size((nframes + 1), OS_DATA_SIZE))) == NULL) return (-EIO); printk(KERN_INFO "%s:I: Reading back %d frames from drive buffer%s\n", diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index e7aee067b056..82533406e3db 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c @@ -1604,8 +1604,7 @@ static int tcm_qla2xxx_init_lport(struct tcm_qla2xxx_lport *lport) return rc; } - lport->lport_loopid_map = vmalloc(sizeof(struct tcm_qla2xxx_fc_loopid) * - 65536); + lport->lport_loopid_map = vmalloc(array_size(65536, sizeof(struct tcm_qla2xxx_fc_loopid))); if (!lport->lport_loopid_map) { pr_err("Unable to allocate lport->lport_loopid_map of %zu bytes\n", sizeof(struct tcm_qla2xxx_fc_loopid) * 65536); diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index ec2c5f07d362..30f77ca780fc 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -5072,7 +5072,7 @@ static int __init scsi_debug_init(void) } map_size = lba_to_map_index(sdebug_store_sectors - 1) + 1; - map_storep = vmalloc(BITS_TO_LONGS(map_size) * sizeof(long)); + map_storep = vmalloc(array_size(sizeof(long), BITS_TO_LONGS(map_size))); pr_info("%lu provisioning blocks\n", map_size); diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index bc60ee81225f..8970fe8d5f7e 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -34,7 +34,7 @@ void *ion_heap_map_kernel(struct ion_heap *heap, pgprot_t pgprot; struct sg_table *table = buffer->sg_table; int npages = PAGE_ALIGN(buffer->size) / PAGE_SIZE; - struct page **pages = vmalloc(sizeof(struct page *) * npages); + struct page **pages = vmalloc(array_size(npages, sizeof(struct page *))); struct page **tmp = pages; if (!pages) diff --git a/drivers/staging/comedi/comedi_buf.c b/drivers/staging/comedi/comedi_buf.c index b455ff6714eb..955d9eeea367 100644 --- a/drivers/staging/comedi/comedi_buf.c +++ b/drivers/staging/comedi/comedi_buf.c @@ -110,7 +110,7 @@ static void __comedi_buf_alloc(struct comedi_device *dev, bm->page_list = vzalloc(sizeof(*buf) * n_pages); if (bm->page_list) - pages = vmalloc(sizeof(struct page *) * n_pages); + pages = vmalloc(array_size(n_pages, sizeof(struct page *))); if (!pages) return; diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index a64517eabff4..4931fdd59a84 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -1181,8 +1181,7 @@ static int gb_camera_debugfs_init(struct gb_camera *gcam) return PTR_ERR(gcam->debugfs.root); } - gcam->debugfs.buffers = vmalloc(sizeof(*gcam->debugfs.buffers) * - GB_CAMERA_DEBUGFS_BUFFER_MAX); + gcam->debugfs.buffers = vmalloc(array_size(GB_CAMERA_DEBUGFS_BUFFER_MAX, sizeof(*gcam->debugfs.buffers))); if (!gcam->debugfs.buffers) return -ENOMEM; diff --git a/drivers/staging/media/lirc/lirc_zilog.c b/drivers/staging/media/lirc/lirc_zilog.c index e35e1b2160e3..3939409fcf5d 100644 --- a/drivers/staging/media/lirc/lirc_zilog.c +++ b/drivers/staging/media/lirc/lirc_zilog.c @@ -807,8 +807,7 @@ static int fw_load(struct IR_tx *tx) dev_dbg(tx->ir->l.dev, "%u IR blaster codesets loaded\n", tx_data->num_code_sets); - tx_data->code_sets = vmalloc( - tx_data->num_code_sets * sizeof(char *)); + tx_data->code_sets = vmalloc(array_size(sizeof(char *), tx_data->num_code_sets)); if (!tx_data->code_sets) { fw_unload_locked(); ret = -ENOMEM; diff --git a/drivers/staging/qca-wifi-host-cmn/utils/logging/src/wlan_logging_sock_svc.c b/drivers/staging/qca-wifi-host-cmn/utils/logging/src/wlan_logging_sock_svc.c index 7220ebf08019..dd0b59281232 100644 --- a/drivers/staging/qca-wifi-host-cmn/utils/logging/src/wlan_logging_sock_svc.c +++ b/drivers/staging/qca-wifi-host-cmn/utils/logging/src/wlan_logging_sock_svc.c @@ -798,7 +798,7 @@ int wlan_logging_sock_init_svc(void) /* Initialize the pktStats data structure here */ pkt_stats_size = sizeof(struct pkt_stats_msg); - gpkt_stats_buffers = vmalloc(MAX_PKTSTATS_BUFF * pkt_stats_size); + gpkt_stats_buffers = vmalloc(array_size(pkt_stats_size, MAX_PKTSTATS_BUFF)); if (!gpkt_stats_buffers) { pr_err("%s: Could not allocate memory for Pkt stats\n", __func__); diff --git a/drivers/staging/qca-wifi-host-cmn/utils/pktlog/linux_ac.c b/drivers/staging/qca-wifi-host-cmn/utils/pktlog/linux_ac.c index 0bbb9df0ecad..6cf9640d3025 100644 --- a/drivers/staging/qca-wifi-host-cmn/utils/pktlog/linux_ac.c +++ b/drivers/staging/qca-wifi-host-cmn/utils/pktlog/linux_ac.c @@ -120,7 +120,7 @@ int pktlog_alloc_buf(struct hif_opaque_softc *scn) } qdf_spin_unlock_bh(&pl_info->log_lock); - buffer = vmalloc((page_cnt + 2) * PAGE_SIZE); + buffer = vmalloc(array_size((page_cnt + 2), PAGE_SIZE)); if (buffer == NULL) { printk(PKTLOG_TAG "%s: Unable to allocate buffer " diff --git a/drivers/staging/rts5208/ms.c b/drivers/staging/rts5208/ms.c index 7cdce87f3051..3a19e43ed341 100644 --- a/drivers/staging/rts5208/ms.c +++ b/drivers/staging/rts5208/ms.c @@ -2618,7 +2618,7 @@ static int ms_build_l2p_tbl(struct rtsx_chip *chip, int seg_no) segment = &ms_card->segment[seg_no]; if (!segment->l2p_table) { - segment->l2p_table = vmalloc(table_size * 2); + segment->l2p_table = vmalloc(array_size(table_size, 2)); if (!segment->l2p_table) { rtsx_trace(chip); goto BUILD_FAIL; diff --git a/drivers/staging/rts5208/rtsx_chip.c b/drivers/staging/rts5208/rtsx_chip.c index 4ad472dd9daf..f8f9579cc679 100644 --- a/drivers/staging/rts5208/rtsx_chip.c +++ b/drivers/staging/rts5208/rtsx_chip.c @@ -1721,7 +1721,7 @@ int rtsx_read_cfg_seq(struct rtsx_chip *chip, u8 func, u16 addr, u8 *buf, dev_dbg(rtsx_dev(chip), "dw_len = %d\n", dw_len); - data = vmalloc(dw_len * 4); + data = vmalloc(array_size(dw_len, 4)); if (!data) { rtsx_trace(chip); return STATUS_NOMEM; diff --git a/drivers/usb/misc/sisusbvga/sisusb_con.c b/drivers/usb/misc/sisusbvga/sisusb_con.c index dc45cfc8eb10..e2ac7d84f236 100644 --- a/drivers/usb/misc/sisusbvga/sisusb_con.c +++ b/drivers/usb/misc/sisusbvga/sisusb_con.c @@ -1242,7 +1242,7 @@ sisusbcon_font_set(struct vc_data *c, struct console_font *font, } if (!sisusb->font_backup) - sisusb->font_backup = vmalloc(charcount * 32); + sisusb->font_backup = vmalloc(array_size(charcount, 32)); if (sisusb->font_backup) { memcpy(sisusb->font_backup, font->data, charcount * 32); diff --git a/drivers/video/fbdev/msm/mdss_mdp_pp_cache_config.c b/drivers/video/fbdev/msm/mdss_mdp_pp_cache_config.c index f13670e40ae6..f2d76d351834 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_pp_cache_config.c +++ b/drivers/video/fbdev/msm/mdss_mdp_pp_cache_config.c @@ -491,8 +491,7 @@ static int pp_gamut_cache_params_v1_7(struct mdp_gamut_cfg_data *config, } /* Allocate for fine mode other modes will fit */ if (!tbl_gamut) - tbl_gamut = vmalloc(GAMUT_TOTAL_TABLE_SIZE_V1_7 * - sizeof(u32)); + tbl_gamut = vmalloc(array_size(GAMUT_TOTAL_TABLE_SIZE_V1_7, sizeof(u32))); if (!tbl_gamut) { pr_err("failed to allocate buffer for gamut size %zd", (GAMUT_TOTAL_TABLE_SIZE_V1_7 * sizeof(u32))); diff --git a/drivers/video/fbdev/xen-fbfront.c b/drivers/video/fbdev/xen-fbfront.c index 46f63960fa9e..6a4bbc9e1fb0 100644 --- a/drivers/video/fbdev/xen-fbfront.c +++ b/drivers/video/fbdev/xen-fbfront.c @@ -412,7 +412,7 @@ static int xenfb_probe(struct xenbus_device *dev, info->nr_pages = (fb_size + PAGE_SIZE - 1) >> PAGE_SHIFT; - info->gfns = vmalloc(sizeof(unsigned long) * info->nr_pages); + info->gfns = vmalloc(array_size(sizeof(unsigned long), info->nr_pages)); if (!info->gfns) goto error_nomem; diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 19c42bd69aa6..0d010cd5fb38 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -2283,7 +2283,7 @@ static int elf_core_dump(struct coredump_params *cprm) if (segs - 1 > ULONG_MAX / sizeof(*vma_filesz)) goto end_coredump; - vma_filesz = vmalloc((segs - 1) * sizeof(*vma_filesz)); + vma_filesz = vmalloc(array_size(sizeof(*vma_filesz), (segs - 1))); if (!vma_filesz) goto end_coredump; diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 76f1649ab444..6ff2c88e45e5 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -815,7 +815,7 @@ setup_aio_ctx_iter(struct cifs_aio_ctx *ctx, struct iov_iter *iter, int rw) GFP_KERNEL); if (!bv) { - bv = vmalloc(max_pages * sizeof(struct bio_vec)); + bv = vmalloc(array_size(max_pages, sizeof(struct bio_vec))); if (!bv) return -ENOMEM; } @@ -825,7 +825,7 @@ setup_aio_ctx_iter(struct cifs_aio_ctx *ctx, struct iov_iter *iter, int rw) GFP_KERNEL); if (!pages) { - pages = vmalloc(max_pages * sizeof(struct page *)); + pages = vmalloc(array_size(max_pages, sizeof(struct page *))); if (!pages) { kvfree(bv); return -ENOMEM; diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c index 9c8c9a09b4a6..f1261fa0af8a 100644 --- a/fs/dlm/lockspace.c +++ b/fs/dlm/lockspace.c @@ -517,7 +517,7 @@ static int new_lockspace(const char *name, const char *cluster, size = dlm_config.ci_rsbtbl_size; ls->ls_rsbtbl_size = size; - ls->ls_rsbtbl = vmalloc(sizeof(struct dlm_rsbtable) * size); + ls->ls_rsbtbl = vmalloc(array_size(size, sizeof(struct dlm_rsbtable))); if (!ls->ls_rsbtbl) goto out_lsfree; for (i = 0; i < size; i++) { diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c index edc8ef78b63f..bf708ac287b4 100644 --- a/fs/reiserfs/bitmap.c +++ b/fs/reiserfs/bitmap.c @@ -1456,7 +1456,7 @@ int reiserfs_init_bitmap_cache(struct super_block *sb) struct reiserfs_bitmap_info *bitmap; unsigned int bmap_nr = reiserfs_bmap_count(sb); - bitmap = vmalloc(sizeof(*bitmap) * bmap_nr); + bitmap = vmalloc(array_size(bmap_nr, sizeof(*bitmap))); if (bitmap == NULL) return -ENOMEM; diff --git a/fs/ubifs/lpt.c b/fs/ubifs/lpt.c index d4e45adddf1e..b229f699ae01 100644 --- a/fs/ubifs/lpt.c +++ b/fs/ubifs/lpt.c @@ -632,7 +632,7 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first, pnode = kzalloc(sizeof(struct ubifs_pnode), GFP_KERNEL); nnode = kzalloc(sizeof(struct ubifs_nnode), GFP_KERNEL); buf = vmalloc(c->leb_size); - ltab = vmalloc(sizeof(struct ubifs_lpt_lprops) * c->lpt_lebs); + ltab = vmalloc(array_size(sizeof(struct ubifs_lpt_lprops), c->lpt_lebs)); if (!pnode || !nnode || !buf || !ltab || !lsave) { err = -ENOMEM; goto out; @@ -1626,7 +1626,7 @@ static int lpt_init_rd(struct ubifs_info *c) { int err, i; - c->ltab = vmalloc(sizeof(struct ubifs_lpt_lprops) * c->lpt_lebs); + c->ltab = vmalloc(array_size(sizeof(struct ubifs_lpt_lprops), c->lpt_lebs)); if (!c->ltab) return -ENOMEM; @@ -1690,7 +1690,7 @@ static int lpt_init_wr(struct ubifs_info *c) { int err, i; - c->ltab_cmt = vmalloc(sizeof(struct ubifs_lpt_lprops) * c->lpt_lebs); + c->ltab_cmt = vmalloc(array_size(sizeof(struct ubifs_lpt_lprops), c->lpt_lebs)); if (!c->ltab_cmt) return -ENOMEM; diff --git a/kernel/cgroup/cgroup-v1.c b/kernel/cgroup/cgroup-v1.c index ae2da7b9b3e8..7f53d00f19ae 100644 --- a/kernel/cgroup/cgroup-v1.c +++ b/kernel/cgroup/cgroup-v1.c @@ -195,7 +195,7 @@ struct cgroup_pidlist { static void *pidlist_allocate(int count) { if (PIDLIST_TOO_LARGE(count)) - return vmalloc(count * sizeof(pid_t)); + return vmalloc(array_size(count, sizeof(pid_t))); else return kmalloc_array(count, sizeof(pid_t), GFP_KERNEL); } diff --git a/kernel/power/swap.c b/kernel/power/swap.c index 75164e041b8e..d93e9e4db1f9 100644 --- a/kernel/power/swap.c +++ b/kernel/power/swap.c @@ -699,7 +699,7 @@ static int save_image_lzo(struct swap_map_handle *handle, goto out_clean; } - data = vmalloc(sizeof(*data) * nr_threads); + data = vmalloc(array_size(nr_threads, sizeof(*data))); if (!data) { printk(KERN_ERR "PM: Failed to allocate LZO data\n"); ret = -ENOMEM; @@ -1190,14 +1190,14 @@ static int load_image_lzo(struct swap_map_handle *handle, nr_threads = num_online_cpus() - 1; nr_threads = clamp_val(nr_threads, 1, LZO_THREADS); - page = vmalloc(sizeof(*page) * LZO_MAX_RD_PAGES); + page = vmalloc(array_size(LZO_MAX_RD_PAGES, sizeof(*page))); if (!page) { printk(KERN_ERR "PM: Failed to allocate LZO page\n"); ret = -ENOMEM; goto out_clean; } - data = vmalloc(sizeof(*data) * nr_threads); + data = vmalloc(array_size(nr_threads, sizeof(*data))); if (!data) { printk(KERN_ERR "PM: Failed to allocate LZO data\n"); ret = -ENOMEM; diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c index 8d342869f268..be72b5140343 100644 --- a/kernel/rcu/rcutorture.c +++ b/kernel/rcu/rcutorture.c @@ -830,8 +830,7 @@ rcu_torture_cbflood(void *arg) cbflood_intra_holdoff > 0 && cur_ops->call && cur_ops->cb_barrier) { - rhp = vmalloc(sizeof(*rhp) * - cbflood_n_burst * cbflood_n_per_burst); + rhp = vmalloc(array3_size(cbflood_n_burst, cbflood_n_per_burst, sizeof(*rhp))); err = !rhp; } if (err) { diff --git a/kernel/trace/tracing_map.c b/kernel/trace/tracing_map.c index 35b2ba07f3c6..300a97a90dcd 100644 --- a/kernel/trace/tracing_map.c +++ b/kernel/trace/tracing_map.c @@ -1003,7 +1003,7 @@ int tracing_map_sort_entries(struct tracing_map *map, struct tracing_map_sort_entry *sort_entry, **entries; int i, n_entries, ret; - entries = vmalloc(map->max_elts * sizeof(sort_entry)); + entries = vmalloc(array_size(sizeof(sort_entry), map->max_elts)); if (!entries) return -ENOMEM; diff --git a/mm/percpu-stats.c b/mm/percpu-stats.c index 7a58460bfd27..702acbea8a11 100644 --- a/mm/percpu-stats.c +++ b/mm/percpu-stats.c @@ -144,7 +144,7 @@ alloc_buffer: spin_unlock_irq(&pcpu_lock); /* there can be at most this many free and allocated fragments */ - buffer = vmalloc((2 * max_nr_alloc + 1) * sizeof(int)); + buffer = vmalloc(array_size(sizeof(int), (2 * max_nr_alloc + 1))); if (!buffer) return -ENOMEM; diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index a1834ad7422c..e94c52812ca1 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -873,12 +873,12 @@ static int translate_table(struct net *net, const char *name, * if an error occurs */ newinfo->chainstack = - vmalloc(nr_cpu_ids * sizeof(*(newinfo->chainstack))); + vmalloc(array_size(nr_cpu_ids, sizeof(*(newinfo->chainstack)))); if (!newinfo->chainstack) return -ENOMEM; for_each_possible_cpu(i) { newinfo->chainstack[i] = - vmalloc(udc_cnt * sizeof(*(newinfo->chainstack[0]))); + vmalloc(array_size(udc_cnt, sizeof(*(newinfo->chainstack[0])))); if (!newinfo->chainstack[i]) { while (i) vfree(newinfo->chainstack[--i]); @@ -888,7 +888,7 @@ static int translate_table(struct net *net, const char *name, } } - cl_s = vmalloc(udc_cnt * sizeof(*cl_s)); + cl_s = vmalloc(array_size(udc_cnt, sizeof(*cl_s))); if (!cl_s) return -ENOMEM; i = 0; /* the i'th udc */ @@ -1273,7 +1273,7 @@ static int do_update_counters(struct net *net, const char *name, if (num_counters == 0) return -EINVAL; - tmp = vmalloc(num_counters * sizeof(*tmp)); + tmp = vmalloc(array_size(num_counters, sizeof(*tmp))); if (!tmp) return -ENOMEM; @@ -1409,7 +1409,7 @@ static int copy_counters_to_user(struct ebt_table *t, if (num_counters != nentries) return -EINVAL; - counterstmp = vmalloc(nentries * sizeof(*counterstmp)); + counterstmp = vmalloc(array_size(nentries, sizeof(*counterstmp))); if (!counterstmp) return -ENOMEM; diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c index 3d2ac71a83ec..39c5c31622e8 100644 --- a/net/netfilter/ipvs/ip_vs_conn.c +++ b/net/netfilter/ipvs/ip_vs_conn.c @@ -1412,7 +1412,7 @@ int __init ip_vs_conn_init(void) /* * Allocate the connection hash table and initialize its list heads */ - ip_vs_conn_tab = vmalloc(ip_vs_conn_tab_size * sizeof(*ip_vs_conn_tab)); + ip_vs_conn_tab = vmalloc(array_size(ip_vs_conn_tab_size, sizeof(*ip_vs_conn_tab))); if (!ip_vs_conn_tab) return -ENOMEM; diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c index ab1112e90f88..148ffaaeace4 100644 --- a/sound/core/seq/seq_memory.c +++ b/sound/core/seq/seq_memory.c @@ -389,7 +389,7 @@ int snd_seq_pool_init(struct snd_seq_pool *pool) if (snd_BUG_ON(!pool)) return -EINVAL; - cellptr = vmalloc(sizeof(struct snd_seq_event_cell) * pool->size); + cellptr = vmalloc(array_size(sizeof(struct snd_seq_event_cell), pool->size)); if (!cellptr) return -ENOMEM; diff --git a/sound/oss/sequencer.c b/sound/oss/sequencer.c index f19da4b47c1d..5c8f62a5aaa6 100644 --- a/sound/oss/sequencer.c +++ b/sound/oss/sequencer.c @@ -1636,13 +1636,13 @@ void sequencer_init(void) { if (sequencer_ok) return; - queue = vmalloc(SEQ_MAX_QUEUE * EV_SZ); + queue = vmalloc(array_size(EV_SZ, SEQ_MAX_QUEUE)); if (queue == NULL) { printk(KERN_ERR "sequencer: Can't allocate memory for sequencer output queue\n"); return; } - iqueue = vmalloc(SEQ_MAX_QUEUE * IEV_SZ); + iqueue = vmalloc(array_size(IEV_SZ, SEQ_MAX_QUEUE)); if (iqueue == NULL) { printk(KERN_ERR "sequencer: Can't allocate memory for sequencer input queue\n"); diff --git a/sound/pci/cs46xx/dsp_spos.c b/sound/pci/cs46xx/dsp_spos.c index 5e9ab685ac82..4cc2500588e1 100644 --- a/sound/pci/cs46xx/dsp_spos.c +++ b/sound/pci/cs46xx/dsp_spos.c @@ -240,8 +240,7 @@ struct dsp_spos_instance *cs46xx_dsp_spos_create (struct snd_cs46xx * chip) return NULL; /* better to use vmalloc for this big table */ - ins->symbol_table.symbols = vmalloc(sizeof(struct dsp_symbol_entry) * - DSP_MAX_SYMBOLS); + ins->symbol_table.symbols = vmalloc(array_size(DSP_MAX_SYMBOLS, sizeof(struct dsp_symbol_entry))); ins->code.data = kmalloc(DSP_CODE_BYTE_SIZE, GFP_KERNEL); ins->modules = kmalloc_array(DSP_MAX_MODULES, sizeof(struct dsp_module_desc), diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index ccf4415a1c7b..027e3f7b23c9 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c @@ -1906,9 +1906,8 @@ int snd_emu10k1_create(struct snd_card *card, goto error; } - emu->page_ptr_table = vmalloc(emu->max_cache_pages * sizeof(void *)); - emu->page_addr_table = vmalloc(emu->max_cache_pages * - sizeof(unsigned long)); + emu->page_ptr_table = vmalloc(array_size(sizeof(void *), emu->max_cache_pages)); + emu->page_addr_table = vmalloc(array_size(sizeof(unsigned long), emu->max_cache_pages)); if (emu->page_ptr_table == NULL || emu->page_addr_table == NULL) { err = -ENOMEM; goto error; @@ -2064,7 +2063,7 @@ static int alloc_pm_buffer(struct snd_emu10k1 *emu) size = ARRAY_SIZE(saved_regs); if (emu->audigy) size += ARRAY_SIZE(saved_regs_audigy); - emu->saved_ptr = vmalloc(4 * NUM_G * size); + emu->saved_ptr = vmalloc(array3_size(4, NUM_G, size)); if (!emu->saved_ptr) return -ENOMEM; if (snd_emu10k1_efx_alloc_pm_buffer(emu) < 0) diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c index e300aa33ceec..d403c67d737b 100644 --- a/sound/pci/emu10k1/emufx.c +++ b/sound/pci/emu10k1/emufx.c @@ -2704,7 +2704,7 @@ int snd_emu10k1_efx_alloc_pm_buffer(struct snd_emu10k1 *emu) if (! emu->tram_val_saved || ! emu->tram_addr_saved) return -ENOMEM; len = emu->audigy ? 2 * 1024 : 2 * 512; - emu->saved_icode = vmalloc(len * 4); + emu->saved_icode = vmalloc(array_size(len, 4)); if (! emu->saved_icode) return -ENOMEM; return 0; diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c index a30da78a95b7..4948b95f6665 100644 --- a/sound/pci/emu10k1/p16v.c +++ b/sound/pci/emu10k1/p16v.c @@ -874,7 +874,7 @@ int snd_p16v_mixer(struct snd_emu10k1 *emu) int snd_p16v_alloc_pm_buffer(struct snd_emu10k1 *emu) { - emu->p16v_saved = vmalloc(NUM_CHS * 4 * 0x80); + emu->p16v_saved = vmalloc(array_size(NUM_CHS * 4, 0x80)); if (! emu->p16v_saved) return -ENOMEM; return 0; diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index 8f20dec97843..1bf81ad221ff 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c @@ -2657,7 +2657,7 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci, chip->irq = pci->irq; #ifdef CONFIG_PM_SLEEP - chip->suspend_mem = vmalloc(sizeof(u16) * (REV_B_CODE_MEMORY_LENGTH + REV_B_DATA_MEMORY_LENGTH)); + chip->suspend_mem = vmalloc(array_size(sizeof(u16), (REV_B_CODE_MEMORY_LENGTH + REV_B_DATA_MEMORY_LENGTH))); if (chip->suspend_mem == NULL) dev_warn(card->dev, "can't allocate apm buffer\n"); #endif diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c index eabd84d9ffee..c802f655efbb 100644 --- a/sound/pci/trident/trident_main.c +++ b/sound/pci/trident/trident_main.c @@ -3362,7 +3362,7 @@ static int snd_trident_tlb_alloc(struct snd_trident *trident) trident->tlb.entries = (unsigned int*)ALIGN((unsigned long)trident->tlb.buffer.area, SNDRV_TRIDENT_MAX_PAGES * 4); trident->tlb.entries_dmaaddr = ALIGN(trident->tlb.buffer.addr, SNDRV_TRIDENT_MAX_PAGES * 4); /* allocate shadow TLB page table (virtual addresses) */ - trident->tlb.shadow_entries = vmalloc(SNDRV_TRIDENT_MAX_PAGES*sizeof(unsigned long)); + trident->tlb.shadow_entries = vmalloc(array_size(SNDRV_TRIDENT_MAX_PAGES, sizeof(unsigned long))); if (!trident->tlb.shadow_entries) return -ENOMEM; diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 71f77ae6c2a6..60dad2a6cfbc 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -3167,7 +3167,7 @@ static long kvm_vm_ioctl(struct file *filp, goto out; if (routing.nr) { r = -ENOMEM; - entries = vmalloc(routing.nr * sizeof(*entries)); + entries = vmalloc(array_size(sizeof(*entries), routing.nr)); if (!entries) goto out; r = -EFAULT; From 3592eba0e6801ee1cb68f6fc8bc33ea6fbef1c21 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 12 Jun 2018 14:27:37 -0700 Subject: [PATCH 581/592] treewide: Use array_size() in vzalloc() The vzalloc() function has no 2-factor argument form, so multiplication factors need to be wrapped in array_size(). This patch replaces cases of: vzalloc(a * b) with: vzalloc(array_size(a, b)) as well as handling cases of: vzalloc(a * b * c) with: vzalloc(array3_size(a, b, c)) This does, however, attempt to ignore constant size factors like: vzalloc(4 * 1024) though any constants defined via macros get caught up in the conversion. Any factors with a sizeof() of "unsigned char", "char", and "u8" were dropped, since they're redundant. The Coccinelle script used for this was: // Fix redundant parens around sizeof(). @@ type TYPE; expression THING, E; @@ ( vzalloc( - (sizeof(TYPE)) * E + sizeof(TYPE) * E , ...) | vzalloc( - (sizeof(THING)) * E + sizeof(THING) * E , ...) ) // Drop single-byte sizes and redundant parens. @@ expression COUNT; typedef u8; typedef __u8; @@ ( vzalloc( - sizeof(u8) * (COUNT) + COUNT , ...) | vzalloc( - sizeof(__u8) * (COUNT) + COUNT , ...) | vzalloc( - sizeof(char) * (COUNT) + COUNT , ...) | vzalloc( - sizeof(unsigned char) * (COUNT) + COUNT , ...) | vzalloc( - sizeof(u8) * COUNT + COUNT , ...) | vzalloc( - sizeof(__u8) * COUNT + COUNT , ...) | vzalloc( - sizeof(char) * COUNT + COUNT , ...) | vzalloc( - sizeof(unsigned char) * COUNT + COUNT , ...) ) // 2-factor product with sizeof(type/expression) and identifier or constant. @@ type TYPE; expression THING; identifier COUNT_ID; constant COUNT_CONST; @@ ( vzalloc( - sizeof(TYPE) * (COUNT_ID) + array_size(COUNT_ID, sizeof(TYPE)) , ...) | vzalloc( - sizeof(TYPE) * COUNT_ID + array_size(COUNT_ID, sizeof(TYPE)) , ...) | vzalloc( - sizeof(TYPE) * (COUNT_CONST) + array_size(COUNT_CONST, sizeof(TYPE)) , ...) | vzalloc( - sizeof(TYPE) * COUNT_CONST + array_size(COUNT_CONST, sizeof(TYPE)) , ...) | vzalloc( - sizeof(THING) * (COUNT_ID) + array_size(COUNT_ID, sizeof(THING)) , ...) | vzalloc( - sizeof(THING) * COUNT_ID + array_size(COUNT_ID, sizeof(THING)) , ...) | vzalloc( - sizeof(THING) * (COUNT_CONST) + array_size(COUNT_CONST, sizeof(THING)) , ...) | vzalloc( - sizeof(THING) * COUNT_CONST + array_size(COUNT_CONST, sizeof(THING)) , ...) ) // 2-factor product, only identifiers. @@ identifier SIZE, COUNT; @@ vzalloc( - SIZE * COUNT + array_size(COUNT, SIZE) , ...) // 3-factor product with 1 sizeof(type) or sizeof(expression), with // redundant parens removed. @@ expression THING; identifier STRIDE, COUNT; type TYPE; @@ ( vzalloc( - sizeof(TYPE) * (COUNT) * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | vzalloc( - sizeof(TYPE) * (COUNT) * STRIDE + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | vzalloc( - sizeof(TYPE) * COUNT * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | vzalloc( - sizeof(TYPE) * COUNT * STRIDE + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | vzalloc( - sizeof(THING) * (COUNT) * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) | vzalloc( - sizeof(THING) * (COUNT) * STRIDE + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) | vzalloc( - sizeof(THING) * COUNT * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) | vzalloc( - sizeof(THING) * COUNT * STRIDE + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) ) // 3-factor product with 2 sizeof(variable), with redundant parens removed. @@ expression THING1, THING2; identifier COUNT; type TYPE1, TYPE2; @@ ( vzalloc( - sizeof(TYPE1) * sizeof(TYPE2) * COUNT + array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2)) , ...) | vzalloc( - sizeof(TYPE1) * sizeof(THING2) * (COUNT) + array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2)) , ...) | vzalloc( - sizeof(THING1) * sizeof(THING2) * COUNT + array3_size(COUNT, sizeof(THING1), sizeof(THING2)) , ...) | vzalloc( - sizeof(THING1) * sizeof(THING2) * (COUNT) + array3_size(COUNT, sizeof(THING1), sizeof(THING2)) , ...) | vzalloc( - sizeof(TYPE1) * sizeof(THING2) * COUNT + array3_size(COUNT, sizeof(TYPE1), sizeof(THING2)) , ...) | vzalloc( - sizeof(TYPE1) * sizeof(THING2) * (COUNT) + array3_size(COUNT, sizeof(TYPE1), sizeof(THING2)) , ...) ) // 3-factor product, only identifiers, with redundant parens removed. @@ identifier STRIDE, SIZE, COUNT; @@ ( vzalloc( - (COUNT) * STRIDE * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) | vzalloc( - COUNT * (STRIDE) * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) | vzalloc( - COUNT * STRIDE * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | vzalloc( - (COUNT) * (STRIDE) * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) | vzalloc( - COUNT * (STRIDE) * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | vzalloc( - (COUNT) * STRIDE * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | vzalloc( - (COUNT) * (STRIDE) * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | vzalloc( - COUNT * STRIDE * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) ) // Any remaining multi-factor products, first at least 3-factor products // when they're not all constants... @@ expression E1, E2, E3; constant C1, C2, C3; @@ ( vzalloc(C1 * C2 * C3, ...) | vzalloc( - E1 * E2 * E3 + array3_size(E1, E2, E3) , ...) ) // And then all remaining 2 factors products when they're not all constants. @@ expression E1, E2; constant C1, C2; @@ ( vzalloc(C1 * C2, ...) | vzalloc( - E1 * E2 + array_size(E1, E2) , ...) ) Signed-off-by: Kees Cook Signed-off-by: Adam W. Willis Signed-off-by: UtsavBalar1231 --- arch/powerpc/kvm/book3s_hv.c | 2 +- arch/powerpc/mm/mmu_context_iommu.c | 2 +- arch/x86/kvm/cpuid.c | 2 +- block/partitions/check.c | 2 +- drivers/block/zram/zram_drv.c | 2 +- drivers/bus/mhi/core/mhi_init.c | 3 +-- drivers/char/raw.c | 2 +- drivers/cpufreq/intel_pstate.c | 2 +- drivers/dma/mic_x100_dma.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c | 2 +- drivers/gpu/drm/drm_hashtab.c | 2 +- drivers/gpu/drm/i915/gvt/mmio.c | 2 +- .../gpu/drm/nouveau/nvkm/subdev/mmu/base.c | 2 +- drivers/gpu/drm/radeon/radeon_gart.c | 2 +- drivers/gpu/drm/selftests/test-drm_mm.c | 18 ++++++------- drivers/gpu/drm/via/via_dmablit.c | 2 +- drivers/infiniband/core/umem_odp.c | 10 +++----- drivers/infiniband/hw/hfi1/sdma.c | 4 +-- drivers/infiniband/hw/hns/hns_roce_mr.c | 2 +- drivers/infiniband/hw/qib/qib_init.c | 4 +-- drivers/infiniband/ulp/ipoib/ipoib_cm.c | 6 ++--- drivers/infiniband/ulp/ipoib/ipoib_main.c | 2 +- drivers/lightnvm/pblk-init.c | 2 +- drivers/lightnvm/pblk-recovery.c | 2 +- drivers/lightnvm/rrpc.c | 5 ++-- drivers/md/bcache/super.c | 3 +-- drivers/md/dm-cache-policy-smq.c | 2 +- drivers/media/common/v4l2-tpg/v4l2-tpg-core.c | 10 ++++---- drivers/media/pci/cx23885/cx23885-alsa.c | 2 +- drivers/media/pci/cx25821/cx25821-alsa.c | 2 +- drivers/media/pci/cx88/cx88-alsa.c | 2 +- drivers/media/pci/saa7134/saa7134-alsa.c | 2 +- .../cam_eeprom/cam_eeprom_core.c | 4 +-- .../cam_sensor_utils/cam_sensor_util.c | 2 +- .../cam_eeprom/cam_eeprom_core.c | 4 +-- .../cam_sensor_utils/cam_sensor_util.c | 25 ++++++++++++++----- .../platform/msm/camera_v2/fd/msm_fd_dev.c | 2 +- .../msm/dvb/demux/mpq_dmx_plugin_common.c | 2 +- drivers/media/platform/vivid/vivid-core.c | 4 +-- drivers/media/v4l2-core/videobuf-dma-sg.c | 2 +- drivers/mtd/nand/nandsim.c | 3 +-- .../ethernet/aquantia/atlantic-fwd/atl_ring.c | 2 +- drivers/net/ethernet/broadcom/bnx2.c | 5 ++-- .../ethernet/cavium/liquidio/octeon_droq.c | 3 +-- .../ethernet/hisilicon/hns/hns_dsaf_main.c | 3 +-- .../net/ethernet/huawei/hinic/hinic_hw_cmdq.c | 4 +-- .../net/ethernet/neterion/vxge/vxge-config.c | 11 ++++---- drivers/net/ethernet/qlogic/qed/qed_l2.c | 2 +- .../net/ethernet/qlogic/qede/qede_filter.c | 3 +-- .../ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 3 +-- .../net/ethernet/qlogic/qlcnic/qlcnic_main.c | 3 +-- drivers/net/ethernet/sfc/ef10.c | 2 +- drivers/net/ethernet/sfc/falcon/farch.c | 2 +- drivers/net/ethernet/sfc/farch.c | 2 +- drivers/net/ppp/pptp.c | 2 +- drivers/net/xen-netback/xenbus.c | 3 +-- drivers/scsi/megaraid/megaraid_sas_fusion.c | 3 +-- drivers/soc/fsl/qbman/qman.c | 2 +- drivers/spmi/simulator/spmi-sim.c | 2 +- drivers/staging/comedi/comedi_buf.c | 2 +- drivers/staging/rtl8188eu/core/rtw_mlme.c | 2 +- drivers/staging/rtl8723bs/core/rtw_mlme.c | 2 +- drivers/staging/rts5208/rtsx_chip.c | 4 +-- drivers/target/target_core_transport.c | 2 +- fs/nfsd/nfscache.c | 2 +- fs/reiserfs/journal.c | 2 +- fs/reiserfs/resize.c | 2 +- kernel/bpf/verifier.c | 8 +++--- kernel/kexec_file.c | 2 +- lib/test_firmware.c | 6 ++--- lib/test_kmod.c | 3 +-- lib/test_rhashtable.c | 4 +-- net/core/ethtool.c | 6 ++--- net/packet/af_packet.c | 2 +- 74 files changed, 125 insertions(+), 138 deletions(-) diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c index e4f81f014206..2b6de3ff8d89 100644 --- a/arch/powerpc/kvm/book3s_hv.c +++ b/arch/powerpc/kvm/book3s_hv.c @@ -3470,7 +3470,7 @@ static int kvmppc_core_create_memslot_hv(struct kvm_memory_slot *slot, return 0; } - slot->arch.rmap = vzalloc(npages * sizeof(*slot->arch.rmap)); + slot->arch.rmap = vzalloc(array_size(npages, sizeof(*slot->arch.rmap))); if (!slot->arch.rmap) return -ENOMEM; diff --git a/arch/powerpc/mm/mmu_context_iommu.c b/arch/powerpc/mm/mmu_context_iommu.c index d735937d975c..02370f72fc5f 100644 --- a/arch/powerpc/mm/mmu_context_iommu.c +++ b/arch/powerpc/mm/mmu_context_iommu.c @@ -171,7 +171,7 @@ long mm_iommu_get(struct mm_struct *mm, unsigned long ua, unsigned long entries, * smaller than huge pages but still bigger than PAGE_SIZE. */ mem->pageshift = __ffs(ua | (entries << PAGE_SHIFT)); - mem->hpas = vzalloc(entries * sizeof(mem->hpas[0])); + mem->hpas = vzalloc(array_size(entries, sizeof(mem->hpas[0]))); if (!mem->hpas) { kfree(mem); ret = -ENOMEM; diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index 41ff7444a2ff..2fc0e2619531 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -786,7 +786,7 @@ int kvm_dev_ioctl_get_cpuid(struct kvm_cpuid2 *cpuid, return -EINVAL; r = -ENOMEM; - cpuid_entries = vzalloc(sizeof(struct kvm_cpuid_entry2) * cpuid->nent); + cpuid_entries = vzalloc(array_size(sizeof(struct kvm_cpuid_entry2), cpuid->nent)); if (!cpuid_entries) goto out; diff --git a/block/partitions/check.c b/block/partitions/check.c index 720145c49066..ffe408fead0c 100644 --- a/block/partitions/check.c +++ b/block/partitions/check.c @@ -122,7 +122,7 @@ static struct parsed_partitions *allocate_partitions(struct gendisk *hd) return NULL; nr = disk_max_parts(hd); - state->parts = vzalloc(nr * sizeof(state->parts[0])); + state->parts = vzalloc(array_size(nr, sizeof(state->parts[0]))); if (!state->parts) { kfree(state); return NULL; diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c index 19247ee48cbd..35565a6c4997 100644 --- a/drivers/block/zram/zram_drv.c +++ b/drivers/block/zram/zram_drv.c @@ -1159,7 +1159,7 @@ static bool zram_meta_alloc(struct zram *zram, u64 disksize) size_t num_pages; num_pages = disksize >> PAGE_SHIFT; - zram->table = vzalloc(num_pages * sizeof(*zram->table)); + zram->table = vzalloc(array_size(num_pages, sizeof(*zram->table))); if (!zram->table) return false; diff --git a/drivers/bus/mhi/core/mhi_init.c b/drivers/bus/mhi/core/mhi_init.c index 10cf1a68fbbc..3d75e0748571 100644 --- a/drivers/bus/mhi/core/mhi_init.c +++ b/drivers/bus/mhi/core/mhi_init.c @@ -1289,8 +1289,7 @@ static int of_parse_ch_cfg(struct mhi_controller *mhi_cntrl, if (!of_node) return -EINVAL; - mhi_cntrl->mhi_chan = vzalloc(mhi_cntrl->max_chan * - sizeof(*mhi_cntrl->mhi_chan)); + mhi_cntrl->mhi_chan = vzalloc(array_size(sizeof(*mhi_cntrl->mhi_chan), mhi_cntrl->max_chan)); if (!mhi_cntrl->mhi_chan) return -ENOMEM; diff --git a/drivers/char/raw.c b/drivers/char/raw.c index 293167c6e254..9d4a917710b8 100644 --- a/drivers/char/raw.c +++ b/drivers/char/raw.c @@ -321,7 +321,7 @@ static int __init raw_init(void) max_raw_minors = MAX_RAW_MINORS; } - raw_devices = vzalloc(sizeof(struct raw_device_data) * max_raw_minors); + raw_devices = vzalloc(array_size(max_raw_minors, sizeof(struct raw_device_data))); if (!raw_devices) { printk(KERN_ERR "Not enough memory for raw device structures\n"); ret = -ENOMEM; diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 1aa0b05c8cbd..dd9c850c01ad 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -2338,7 +2338,7 @@ hwp_cpu_matched: pr_info("Intel P-state driver initializing\n"); - all_cpu_data = vzalloc(sizeof(void *) * num_possible_cpus()); + all_cpu_data = vzalloc(array_size(sizeof(void *), num_possible_cpus())); if (!all_cpu_data) return -ENOMEM; diff --git a/drivers/dma/mic_x100_dma.c b/drivers/dma/mic_x100_dma.c index 5ba5714d0b7c..54d9446c3df5 100644 --- a/drivers/dma/mic_x100_dma.c +++ b/drivers/dma/mic_x100_dma.c @@ -385,7 +385,7 @@ static int mic_dma_alloc_desc_ring(struct mic_dma_chan *ch) if (dma_mapping_error(dev, ch->desc_ring_micpa)) goto map_error; - ch->tx_array = vzalloc(MIC_DMA_DESC_RX_SIZE * sizeof(*ch->tx_array)); + ch->tx_array = vzalloc(array_size(MIC_DMA_DESC_RX_SIZE, sizeof(*ch->tx_array))); if (!ch->tx_array) goto tx_error; return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c index f4370081f6e6..eed93151b816 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c @@ -375,7 +375,7 @@ int amdgpu_gart_init(struct amdgpu_device *adev) #ifdef CONFIG_DRM_AMDGPU_GART_DEBUGFS /* Allocate pages table */ - adev->gart.pages = vzalloc(sizeof(void *) * adev->gart.num_cpu_pages); + adev->gart.pages = vzalloc(array_size(sizeof(void *), adev->gart.num_cpu_pages)); if (adev->gart.pages == NULL) { amdgpu_gart_fini(adev); return -ENOMEM; diff --git a/drivers/gpu/drm/drm_hashtab.c b/drivers/gpu/drm/drm_hashtab.c index dae18e58e79b..c92b00d42ece 100644 --- a/drivers/gpu/drm/drm_hashtab.c +++ b/drivers/gpu/drm/drm_hashtab.c @@ -47,7 +47,7 @@ int drm_ht_create(struct drm_open_hash *ht, unsigned int order) if (size <= PAGE_SIZE / sizeof(*ht->table)) ht->table = kcalloc(size, sizeof(*ht->table), GFP_KERNEL); else - ht->table = vzalloc(size*sizeof(*ht->table)); + ht->table = vzalloc(array_size(size, sizeof(*ht->table))); if (!ht->table) { DRM_ERROR("Out of memory for hash table\n"); return -ENOMEM; diff --git a/drivers/gpu/drm/i915/gvt/mmio.c b/drivers/gpu/drm/i915/gvt/mmio.c index 980ec8906b1e..9a432f0c7ca5 100644 --- a/drivers/gpu/drm/i915/gvt/mmio.c +++ b/drivers/gpu/drm/i915/gvt/mmio.c @@ -328,7 +328,7 @@ int intel_vgpu_init_mmio(struct intel_vgpu *vgpu) { const struct intel_gvt_device_info *info = &vgpu->gvt->device_info; - vgpu->mmio.vreg = vzalloc(info->mmio_size * 2); + vgpu->mmio.vreg = vzalloc(array_size(info->mmio_size, 2)); if (!vgpu->mmio.vreg) return -ENOMEM; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c index 455da298227f..5f70de882ed2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c @@ -382,7 +382,7 @@ nvkm_vm_create(struct nvkm_mmu *mmu, u64 offset, u64 length, u64 mm_offset, vm->fpde = offset >> (mmu->func->pgt_bits + 12); vm->lpde = (offset + length - 1) >> (mmu->func->pgt_bits + 12); - vm->pgt = vzalloc((vm->lpde - vm->fpde + 1) * sizeof(*vm->pgt)); + vm->pgt = vzalloc(array_size(sizeof(*vm->pgt), (vm->lpde - vm->fpde + 1))); if (!vm->pgt) { kfree(vm); return -ENOMEM; diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index 771b1fff1c2c..41746d0e80ad 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c @@ -347,7 +347,7 @@ int radeon_gart_init(struct radeon_device *rdev) DRM_INFO("GART: num cpu pages %u, num gpu pages %u\n", rdev->gart.num_cpu_pages, rdev->gart.num_gpu_pages); /* Allocate pages table */ - rdev->gart.pages = vzalloc(sizeof(void *) * rdev->gart.num_cpu_pages); + rdev->gart.pages = vzalloc(array_size(sizeof(void *), rdev->gart.num_cpu_pages)); if (rdev->gart.pages == NULL) { radeon_gart_fini(rdev); return -ENOMEM; diff --git a/drivers/gpu/drm/selftests/test-drm_mm.c b/drivers/gpu/drm/selftests/test-drm_mm.c index 6e2609771f62..c3ec1645751b 100644 --- a/drivers/gpu/drm/selftests/test-drm_mm.c +++ b/drivers/gpu/drm/selftests/test-drm_mm.c @@ -389,7 +389,7 @@ static int __igt_reserve(unsigned int count, u64 size) if (!order) goto err; - nodes = vzalloc(sizeof(*nodes) * count); + nodes = vzalloc(array_size(count, sizeof(*nodes))); if (!nodes) goto err_order; @@ -887,7 +887,7 @@ static int __igt_insert_range(unsigned int count, u64 size, u64 start, u64 end) */ ret = -ENOMEM; - nodes = vzalloc(count * sizeof(*nodes)); + nodes = vzalloc(array_size(count, sizeof(*nodes))); if (!nodes) goto err; @@ -1042,7 +1042,7 @@ static int igt_align(void *ignored) * meets our requirements. */ - nodes = vzalloc(max_count * sizeof(*nodes)); + nodes = vzalloc(array_size(max_count, sizeof(*nodes))); if (!nodes) goto err; @@ -1411,7 +1411,7 @@ static int igt_evict(void *ignored) */ ret = -ENOMEM; - nodes = vzalloc(size * sizeof(*nodes)); + nodes = vzalloc(array_size(size, sizeof(*nodes))); if (!nodes) goto err; @@ -1521,7 +1521,7 @@ static int igt_evict_range(void *ignored) */ ret = -ENOMEM; - nodes = vzalloc(size * sizeof(*nodes)); + nodes = vzalloc(array_size(size, sizeof(*nodes))); if (!nodes) goto err; @@ -1622,7 +1622,7 @@ static int igt_topdown(void *ignored) */ ret = -ENOMEM; - nodes = vzalloc(count * sizeof(*nodes)); + nodes = vzalloc(array_size(count, sizeof(*nodes))); if (!nodes) goto err; @@ -1736,7 +1736,7 @@ static int igt_bottomup(void *ignored) */ ret = -ENOMEM; - nodes = vzalloc(count * sizeof(*nodes)); + nodes = vzalloc(array_size(count, sizeof(*nodes))); if (!nodes) goto err; @@ -2093,7 +2093,7 @@ static int igt_color_evict(void *ignored) */ ret = -ENOMEM; - nodes = vzalloc(total_size * sizeof(*nodes)); + nodes = vzalloc(array_size(total_size, sizeof(*nodes))); if (!nodes) goto err; @@ -2194,7 +2194,7 @@ static int igt_color_evict_range(void *ignored) */ ret = -ENOMEM; - nodes = vzalloc(total_size * sizeof(*nodes)); + nodes = vzalloc(array_size(total_size, sizeof(*nodes))); if (!nodes) goto err; diff --git a/drivers/gpu/drm/via/via_dmablit.c b/drivers/gpu/drm/via/via_dmablit.c index 98aae9809249..3133a449b3d8 100644 --- a/drivers/gpu/drm/via/via_dmablit.c +++ b/drivers/gpu/drm/via/via_dmablit.c @@ -235,7 +235,7 @@ via_lock_all_dma_pages(drm_via_sg_info_t *vsg, drm_via_dmablit_t *xfer) vsg->num_pages = VIA_PFN(xfer->mem_addr + (xfer->num_lines * xfer->mem_stride - 1)) - first_pfn + 1; - vsg->pages = vzalloc(sizeof(struct page *) * vsg->num_pages); + vsg->pages = vzalloc(array_size(sizeof(struct page *), vsg->num_pages)); if (NULL == vsg->pages) return -ENOMEM; ret = get_user_pages_unlocked((unsigned long)xfer->mem_addr, diff --git a/drivers/infiniband/core/umem_odp.c b/drivers/infiniband/core/umem_odp.c index 688ce1846911..46a84d947918 100644 --- a/drivers/infiniband/core/umem_odp.c +++ b/drivers/infiniband/core/umem_odp.c @@ -252,13 +252,13 @@ struct ib_umem *ib_alloc_odp_umem(struct ib_ucontext *context, mutex_init(&odp_data->umem_mutex); init_completion(&odp_data->notifier_completion); - odp_data->page_list = vzalloc(pages * sizeof(*odp_data->page_list)); + odp_data->page_list = vzalloc(array_size(pages, sizeof(*odp_data->page_list))); if (!odp_data->page_list) { ret = -ENOMEM; goto out_odp_data; } - odp_data->dma_list = vzalloc(pages * sizeof(*odp_data->dma_list)); + odp_data->dma_list = vzalloc(array_size(pages, sizeof(*odp_data->dma_list))); if (!odp_data->dma_list) { ret = -ENOMEM; goto out_page_list; @@ -339,15 +339,13 @@ int ib_umem_odp_get(struct ib_ucontext *context, struct ib_umem *umem, init_completion(&umem->odp_data->notifier_completion); if (ib_umem_num_pages(umem)) { - umem->odp_data->page_list = vzalloc(ib_umem_num_pages(umem) * - sizeof(*umem->odp_data->page_list)); + umem->odp_data->page_list = vzalloc(array_size(sizeof(*umem->odp_data->page_list), ib_umem_num_pages(umem))); if (!umem->odp_data->page_list) { ret_val = -ENOMEM; goto out_odp_data; } - umem->odp_data->dma_list = vzalloc(ib_umem_num_pages(umem) * - sizeof(*umem->odp_data->dma_list)); + umem->odp_data->dma_list = vzalloc(array_size(sizeof(*umem->odp_data->dma_list), ib_umem_num_pages(umem))); if (!umem->odp_data->dma_list) { ret_val = -ENOMEM; goto out_page_list; diff --git a/drivers/infiniband/hw/hfi1/sdma.c b/drivers/infiniband/hw/hfi1/sdma.c index 741938409f8e..3ca4d228b91e 100644 --- a/drivers/infiniband/hw/hfi1/sdma.c +++ b/drivers/infiniband/hw/hfi1/sdma.c @@ -1469,9 +1469,7 @@ int sdma_init(struct hfi1_devdata *dd, u8 port) GFP_KERNEL); if (!sde->tx_ring) sde->tx_ring = - vzalloc( - sizeof(struct sdma_txreq *) * - descq_cnt); + vzalloc(array_size(descq_cnt, sizeof(struct sdma_txreq *))); if (!sde->tx_ring) goto bail; } diff --git a/drivers/infiniband/hw/hns/hns_roce_mr.c b/drivers/infiniband/hw/hns/hns_roce_mr.c index e387360e3780..0da6cea71f87 100644 --- a/drivers/infiniband/hw/hns/hns_roce_mr.c +++ b/drivers/infiniband/hw/hns/hns_roce_mr.c @@ -142,7 +142,7 @@ static int hns_roce_buddy_init(struct hns_roce_buddy *buddy, int max_order) buddy->bits[i] = kcalloc(s, sizeof(long), GFP_KERNEL | __GFP_NOWARN); if (!buddy->bits[i]) { - buddy->bits[i] = vzalloc(s * sizeof(long)); + buddy->bits[i] = vzalloc(array_size(s, sizeof(long))); if (!buddy->bits[i]) goto err_out_free; } diff --git a/drivers/infiniband/hw/qib/qib_init.c b/drivers/infiniband/hw/qib/qib_init.c index 9e1d9435d865..81d9ab511819 100644 --- a/drivers/infiniband/hw/qib/qib_init.c +++ b/drivers/infiniband/hw/qib/qib_init.c @@ -370,11 +370,11 @@ static void init_shadow_tids(struct qib_devdata *dd) struct page **pages; dma_addr_t *addrs; - pages = vzalloc(dd->cfgctxts * dd->rcvtidcnt * sizeof(struct page *)); + pages = vzalloc(array_size(sizeof(struct page *), (dd->cfgctxts * dd->rcvtidcnt))); if (!pages) goto bail; - addrs = vzalloc(dd->cfgctxts * dd->rcvtidcnt * sizeof(dma_addr_t)); + addrs = vzalloc(array_size(sizeof(dma_addr_t), (dd->cfgctxts * dd->rcvtidcnt))); if (!addrs) goto bail_free; diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c index 0e85b3445c07..c3f8dbe0a7da 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c @@ -358,7 +358,7 @@ static int ipoib_cm_nonsrq_init_rx(struct net_device *dev, struct ib_cm_id *cm_i int ret; int i; - rx->rx_ring = vzalloc(ipoib_recvq_size * sizeof *rx->rx_ring); + rx->rx_ring = vzalloc(array_size(ipoib_recvq_size, sizeof(*rx->rx_ring))); if (!rx->rx_ring) return -ENOMEM; @@ -1138,7 +1138,7 @@ static int ipoib_cm_tx_init(struct ipoib_cm_tx *p, u32 qpn, int ret; noio_flag = memalloc_noio_save(); - p->tx_ring = vzalloc(ipoib_sendq_size * sizeof(*p->tx_ring)); + p->tx_ring = vzalloc(array_size(ipoib_sendq_size, sizeof(*p->tx_ring))); if (!p->tx_ring) { ret = -ENOMEM; goto err_tx; @@ -1565,7 +1565,7 @@ static void ipoib_cm_create_srq(struct net_device *dev, int max_sge) return; } - priv->cm.srq_ring = vzalloc(ipoib_recvq_size * sizeof *priv->cm.srq_ring); + priv->cm.srq_ring = vzalloc(array_size(ipoib_recvq_size, sizeof(*priv->cm.srq_ring))); if (!priv->cm.srq_ring) { ib_destroy_srq(priv->cm.srq); priv->cm.srq = NULL; diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 9fbecfd96785..429336093a09 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -1675,7 +1675,7 @@ static int ipoib_dev_init_default(struct net_device *dev) if (!priv->rx_ring) goto out; - priv->tx_ring = vzalloc(ipoib_sendq_size * sizeof *priv->tx_ring); + priv->tx_ring = vzalloc(array_size(ipoib_sendq_size, sizeof(*priv->tx_ring))); if (!priv->tx_ring) { printk(KERN_WARNING "%s: failed to allocate TX ring (%d entries)\n", priv->ca->name, ipoib_sendq_size); diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c index 9d565ef34f20..6dcab44b49f2 100644 --- a/drivers/lightnvm/pblk-init.c +++ b/drivers/lightnvm/pblk-init.c @@ -121,7 +121,7 @@ static int pblk_rwb_init(struct pblk *pblk) nr_entries = pblk_rb_calculate_size(pblk->pgs_in_buffer); - entries = vzalloc(nr_entries * sizeof(struct pblk_rb_entry)); + entries = vzalloc(array_size(nr_entries, sizeof(struct pblk_rb_entry))); if (!entries) return -ENOMEM; diff --git a/drivers/lightnvm/pblk-recovery.c b/drivers/lightnvm/pblk-recovery.c index 5d0912bf9eab..81be0be821c9 100644 --- a/drivers/lightnvm/pblk-recovery.c +++ b/drivers/lightnvm/pblk-recovery.c @@ -376,7 +376,7 @@ static int pblk_recov_pad_oob(struct pblk *pblk, struct pblk_line *line, if (!pad_rq) return -ENOMEM; - data = vzalloc(pblk->max_write_pgs * geo->sec_size); + data = vzalloc(array_size(pblk->max_write_pgs, geo->sec_size)); if (!data) { ret = -ENOMEM; goto free_rq; diff --git a/drivers/lightnvm/rrpc.c b/drivers/lightnvm/rrpc.c index edfb02d13469..42e8bc44dc23 100644 --- a/drivers/lightnvm/rrpc.c +++ b/drivers/lightnvm/rrpc.c @@ -1140,7 +1140,7 @@ static int rrpc_map_init(struct rrpc *rrpc) sector_t i; int ret; - rrpc->trans_map = vzalloc(sizeof(struct rrpc_addr) * rrpc->nr_sects); + rrpc->trans_map = vzalloc(array_size(sizeof(struct rrpc_addr), rrpc->nr_sects)); if (!rrpc->trans_map) return -ENOMEM; @@ -1315,8 +1315,7 @@ static int rrpc_luns_init(struct rrpc *rrpc, struct ppa_addr *luns) rlun = &rrpc->luns[i]; rlun->id = i; rrpc_set_lun_ppa(rlun, luns[i]); - rlun->blocks = vzalloc(sizeof(struct rrpc_block) * - geo->blks_per_lun); + rlun->blocks = vzalloc(array_size(sizeof(struct rrpc_block), geo->blks_per_lun)); if (!rlun->blocks) { ret = -ENOMEM; goto err; diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c index a0dcfc7a83ab..f4d20deaec1b 100644 --- a/drivers/md/bcache/super.c +++ b/drivers/md/bcache/super.c @@ -1866,8 +1866,7 @@ static int cache_alloc(struct cache *ca) !init_fifo(&ca->free[RESERVE_NONE], free, GFP_KERNEL) || !init_fifo(&ca->free_inc, free << 2, GFP_KERNEL) || !init_heap(&ca->heap, free << 3, GFP_KERNEL) || - !(ca->buckets = vzalloc(sizeof(struct bucket) * - ca->sb.nbuckets)) || + !(ca->buckets = vzalloc(array_size(sizeof(struct bucket), ca->sb.nbuckets))) || !(ca->prio_buckets = kzalloc(array3_size(sizeof(uint64_t), prio_buckets(ca), 2), GFP_KERNEL)) || !(ca->disk_buckets = alloc_bucket_pages(GFP_KERNEL, ca))) return -ENOMEM; diff --git a/drivers/md/dm-cache-policy-smq.c b/drivers/md/dm-cache-policy-smq.c index c9674d351448..786bc064f24b 100644 --- a/drivers/md/dm-cache-policy-smq.c +++ b/drivers/md/dm-cache-policy-smq.c @@ -69,7 +69,7 @@ static int space_init(struct entry_space *es, unsigned nr_entries) return 0; } - es->begin = vzalloc(sizeof(struct entry) * nr_entries); + es->begin = vzalloc(array_size(nr_entries, sizeof(struct entry))); if (!es->begin) return -ENOMEM; diff --git a/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c b/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c index 664c4b8b1a6d..fae2c5230570 100644 --- a/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c +++ b/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c @@ -131,12 +131,12 @@ int tpg_alloc(struct tpg_data *tpg, unsigned max_w) for (plane = 0; plane < TPG_MAX_PLANES; plane++) { unsigned pixelsz = plane ? 2 : 4; - tpg->lines[pat][plane] = vzalloc(max_w * 2 * pixelsz); + tpg->lines[pat][plane] = vzalloc(array3_size(max_w, 2, pixelsz)); if (!tpg->lines[pat][plane]) return -ENOMEM; if (plane == 0) continue; - tpg->downsampled_lines[pat][plane] = vzalloc(max_w * 2 * pixelsz); + tpg->downsampled_lines[pat][plane] = vzalloc(array3_size(max_w, 2, pixelsz)); if (!tpg->downsampled_lines[pat][plane]) return -ENOMEM; } @@ -144,13 +144,13 @@ int tpg_alloc(struct tpg_data *tpg, unsigned max_w) for (plane = 0; plane < TPG_MAX_PLANES; plane++) { unsigned pixelsz = plane ? 2 : 4; - tpg->contrast_line[plane] = vzalloc(max_w * pixelsz); + tpg->contrast_line[plane] = vzalloc(array_size(pixelsz, max_w)); if (!tpg->contrast_line[plane]) return -ENOMEM; - tpg->black_line[plane] = vzalloc(max_w * pixelsz); + tpg->black_line[plane] = vzalloc(array_size(pixelsz, max_w)); if (!tpg->black_line[plane]) return -ENOMEM; - tpg->random_line[plane] = vzalloc(max_w * 2 * pixelsz); + tpg->random_line[plane] = vzalloc(array3_size(max_w, 2, pixelsz)); if (!tpg->random_line[plane]) return -ENOMEM; } diff --git a/drivers/media/pci/cx23885/cx23885-alsa.c b/drivers/media/pci/cx23885/cx23885-alsa.c index d8c3637e492e..11e1cdf5633f 100644 --- a/drivers/media/pci/cx23885/cx23885-alsa.c +++ b/drivers/media/pci/cx23885/cx23885-alsa.c @@ -96,7 +96,7 @@ static int cx23885_alsa_dma_init(struct cx23885_audio_dev *chip, int nr_pages) memset(buf->vaddr, 0, nr_pages << PAGE_SHIFT); buf->nr_pages = nr_pages; - buf->sglist = vzalloc(buf->nr_pages * sizeof(*buf->sglist)); + buf->sglist = vzalloc(array_size(sizeof(*buf->sglist), buf->nr_pages)); if (NULL == buf->sglist) goto vzalloc_err; diff --git a/drivers/media/pci/cx25821/cx25821-alsa.c b/drivers/media/pci/cx25821/cx25821-alsa.c index 2b34990e86f2..c16a81cecb82 100644 --- a/drivers/media/pci/cx25821/cx25821-alsa.c +++ b/drivers/media/pci/cx25821/cx25821-alsa.c @@ -159,7 +159,7 @@ static int cx25821_alsa_dma_init(struct cx25821_audio_dev *chip, int nr_pages) memset(buf->vaddr, 0, nr_pages << PAGE_SHIFT); buf->nr_pages = nr_pages; - buf->sglist = vzalloc(buf->nr_pages * sizeof(*buf->sglist)); + buf->sglist = vzalloc(array_size(sizeof(*buf->sglist), buf->nr_pages)); if (NULL == buf->sglist) goto vzalloc_err; diff --git a/drivers/media/pci/cx88/cx88-alsa.c b/drivers/media/pci/cx88/cx88-alsa.c index 9740326bc93f..7ac3c2b357da 100644 --- a/drivers/media/pci/cx88/cx88-alsa.c +++ b/drivers/media/pci/cx88/cx88-alsa.c @@ -298,7 +298,7 @@ static int cx88_alsa_dma_init(struct cx88_audio_dev *chip, int nr_pages) memset(buf->vaddr, 0, nr_pages << PAGE_SHIFT); buf->nr_pages = nr_pages; - buf->sglist = vzalloc(buf->nr_pages * sizeof(*buf->sglist)); + buf->sglist = vzalloc(array_size(sizeof(*buf->sglist), buf->nr_pages)); if (!buf->sglist) goto vzalloc_err; diff --git a/drivers/media/pci/saa7134/saa7134-alsa.c b/drivers/media/pci/saa7134/saa7134-alsa.c index c59b69f1af9d..5510cfbd0049 100644 --- a/drivers/media/pci/saa7134/saa7134-alsa.c +++ b/drivers/media/pci/saa7134/saa7134-alsa.c @@ -280,7 +280,7 @@ static int saa7134_alsa_dma_init(struct saa7134_dev *dev, int nr_pages) memset(dma->vaddr, 0, nr_pages << PAGE_SHIFT); dma->nr_pages = nr_pages; - dma->sglist = vzalloc(dma->nr_pages * sizeof(*dma->sglist)); + dma->sglist = vzalloc(array_size(sizeof(*dma->sglist), dma->nr_pages)); if (NULL == dma->sglist) goto vzalloc_err; diff --git a/drivers/media/platform/msm/ais/cam_sensor_module/cam_eeprom/cam_eeprom_core.c b/drivers/media/platform/msm/ais/cam_sensor_module/cam_eeprom/cam_eeprom_core.c index 1134189eead5..36ee4ecf0e02 100644 --- a/drivers/media/platform/msm/ais/cam_sensor_module/cam_eeprom/cam_eeprom_core.c +++ b/drivers/media/platform/msm/ais/cam_sensor_module/cam_eeprom/cam_eeprom_core.c @@ -580,9 +580,7 @@ static int32_t cam_eeprom_init_pkt_parser(struct cam_eeprom_ctrl_t *e_ctrl, (struct cam_eeprom_soc_private *)e_ctrl->soc_info.soc_private; struct cam_sensor_power_ctrl_t *power_info = &soc_private->power_info; - e_ctrl->cal_data.map = vzalloc((MSM_EEPROM_MEMORY_MAP_MAX_SIZE * - MSM_EEPROM_MAX_MEM_MAP_CNT) * - (sizeof(struct cam_eeprom_memory_map_t))); + e_ctrl->cal_data.map = vzalloc(array_size(sizeof(struct cam_eeprom_memory_map_t), (MSM_EEPROM_MEMORY_MAP_MAX_SIZE * MSM_EEPROM_MAX_MEM_MAP_CNT))); if (!e_ctrl->cal_data.map) { rc = -ENOMEM; CAM_ERR(CAM_EEPROM, "failed"); diff --git a/drivers/media/platform/msm/ais/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c b/drivers/media/platform/msm/ais/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c index 031cb4b87046..74e26a87283a 100644 --- a/drivers/media/platform/msm/ais/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c +++ b/drivers/media/platform/msm/ais/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c @@ -37,7 +37,7 @@ static struct i2c_settings_list* return NULL; tmp->i2c_settings.reg_setting = (struct cam_sensor_i2c_reg_array *) - vzalloc(size * sizeof(struct cam_sensor_i2c_reg_array)); + vzalloc(array_size(size, sizeof(struct cam_sensor_i2c_reg_array))); if (tmp->i2c_settings.reg_setting == NULL) { list_del(&(tmp->list)); kfree(tmp); diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c index f78a7177dcf3..53ee7ceefa50 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c @@ -580,9 +580,7 @@ static int32_t cam_eeprom_init_pkt_parser(struct cam_eeprom_ctrl_t *e_ctrl, (struct cam_eeprom_soc_private *)e_ctrl->soc_info.soc_private; struct cam_sensor_power_ctrl_t *power_info = &soc_private->power_info; - e_ctrl->cal_data.map = vzalloc((MSM_EEPROM_MEMORY_MAP_MAX_SIZE * - MSM_EEPROM_MAX_MEM_MAP_CNT) * - (sizeof(struct cam_eeprom_memory_map_t))); + e_ctrl->cal_data.map = vzalloc(array_size(sizeof(struct cam_eeprom_memory_map_t), (MSM_EEPROM_MEMORY_MAP_MAX_SIZE * MSM_EEPROM_MAX_MEM_MAP_CNT))); if (!e_ctrl->cal_data.map) { rc = -ENOMEM; CAM_ERR(CAM_EEPROM, "failed"); diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c index 98f9f121f4e9..f57c636797c3 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c @@ -36,12 +36,25 @@ static struct i2c_settings_list* else return NULL; - tmp->i2c_settings.reg_setting = (struct cam_sensor_i2c_reg_array *) - vzalloc(size * sizeof(struct cam_sensor_i2c_reg_array)); - if (tmp->i2c_settings.reg_setting == NULL) { - list_del(&(tmp->list)); - kvfree(tmp); - return NULL; + if ((sizeof(struct cam_sensor_i2c_reg_array) * size) < PAGE_SIZE) { + tmp->i2c_settings.reg_setting = + (struct cam_sensor_i2c_reg_array *) + kcalloc(size, sizeof(struct cam_sensor_i2c_reg_array), + GFP_KERNEL); + if (tmp->i2c_settings.reg_setting == NULL) { + list_del(&(tmp->list)); + kfree(tmp); + return NULL; + } + } else { + tmp->i2c_settings.reg_setting = + (struct cam_sensor_i2c_reg_array *) + vzalloc(array_size(size, sizeof(struct cam_sensor_i2c_reg_array))); + if (tmp->i2c_settings.reg_setting == NULL) { + list_del(&(tmp->list)); + kfree(tmp); + return NULL; + } } tmp->i2c_settings.size = size; diff --git a/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c b/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c index 6d96a0032f01..37ab9d680bfb 100644 --- a/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c +++ b/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c @@ -445,7 +445,7 @@ static int msm_fd_open(struct file *file) } ctx->mem_pool.fd_device = ctx->fd_device; - ctx->stats = vzalloc(sizeof(*ctx->stats) * MSM_FD_MAX_RESULT_BUFS); + ctx->stats = vzalloc(array_size(MSM_FD_MAX_RESULT_BUFS, sizeof(*ctx->stats))); if (!ctx->stats) { dev_err(device->dev, "No memory for face statistics\n"); ret = -ENOMEM; diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c index 7146d24c1f95..358a3e9017b0 100644 --- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c +++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c @@ -831,7 +831,7 @@ int mpq_dmx_plugin_init(mpq_dmx_init dmx_init_func, /* Allocate memory for all MPQ devices */ mpq_dmx_info.devices = - vzalloc(mpq_demux_device_num*sizeof(struct mpq_demux)); + vzalloc(array_size(mpq_demux_device_num, sizeof(struct mpq_demux))); if (!mpq_dmx_info.devices) { result = -ENOMEM; diff --git a/drivers/media/platform/vivid/vivid-core.c b/drivers/media/platform/vivid/vivid-core.c index df93058e72eb..0231f42b53fb 100644 --- a/drivers/media/platform/vivid/vivid-core.c +++ b/drivers/media/platform/vivid/vivid-core.c @@ -856,10 +856,10 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) tpg_init(&dev->tpg, 640, 360); if (tpg_alloc(&dev->tpg, MAX_ZOOM * MAX_WIDTH)) goto free_dev; - dev->scaled_line = vzalloc(MAX_ZOOM * MAX_WIDTH); + dev->scaled_line = vzalloc(array_size(MAX_WIDTH, MAX_ZOOM)); if (!dev->scaled_line) goto free_dev; - dev->blended_line = vzalloc(MAX_ZOOM * MAX_WIDTH); + dev->blended_line = vzalloc(array_size(MAX_WIDTH, MAX_ZOOM)); if (!dev->blended_line) goto free_dev; diff --git a/drivers/media/v4l2-core/videobuf-dma-sg.c b/drivers/media/v4l2-core/videobuf-dma-sg.c index 10c78796c420..fe44715fc84f 100644 --- a/drivers/media/v4l2-core/videobuf-dma-sg.c +++ b/drivers/media/v4l2-core/videobuf-dma-sg.c @@ -69,7 +69,7 @@ static struct scatterlist *videobuf_vmalloc_to_sg(unsigned char *virt, struct page *pg; int i; - sglist = vzalloc(nr_pages * sizeof(*sglist)); + sglist = vzalloc(array_size(nr_pages, sizeof(*sglist))); if (NULL == sglist) return NULL; sg_init_table(sglist, nr_pages); diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index ed7332b135a0..67a143051ed3 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c @@ -566,8 +566,7 @@ static int __init alloc_device(struct nandsim *ns) err = -EINVAL; goto err_close; } - ns->pages_written = vzalloc(BITS_TO_LONGS(ns->geom.pgnum) * - sizeof(unsigned long)); + ns->pages_written = vzalloc(array_size(sizeof(unsigned long), BITS_TO_LONGS(ns->geom.pgnum))); if (!ns->pages_written) { NS_ERR("alloc_device: unable to allocate pages written array\n"); err = -ENOMEM; diff --git a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_ring.c b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_ring.c index 93d99db69178..03ddf02f1017 100644 --- a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_ring.c +++ b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_ring.c @@ -1476,7 +1476,7 @@ static int atl_alloc_ring(struct atl_desc_ring *ring, size_t buf_size, return ret; } - ring->bufs = vzalloc(ring->hw.size * buf_size); + ring->bufs = vzalloc(array_size(ring->hw.size, buf_size)); if (!ring->bufs) { atl_nic_err("Couldn't alloc %s[%d] %sbufs\n", type, idx, type); ret = -ENOMEM; diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c index 01666afa9aad..10618f09bd57 100644 --- a/drivers/net/ethernet/broadcom/bnx2.c +++ b/drivers/net/ethernet/broadcom/bnx2.c @@ -778,7 +778,7 @@ bnx2_alloc_rx_mem(struct bnx2 *bp) int j; rxr->rx_buf_ring = - vzalloc(SW_RXBD_RING_SIZE * bp->rx_max_ring); + vzalloc(array_size(SW_RXBD_RING_SIZE, bp->rx_max_ring)); if (rxr->rx_buf_ring == NULL) return -ENOMEM; @@ -794,8 +794,7 @@ bnx2_alloc_rx_mem(struct bnx2 *bp) } if (bp->rx_pg_ring_size) { - rxr->rx_pg_ring = vzalloc(SW_RXPG_RING_SIZE * - bp->rx_max_pg_ring); + rxr->rx_pg_ring = vzalloc(array_size(SW_RXPG_RING_SIZE, bp->rx_max_pg_ring)); if (rxr->rx_pg_ring == NULL) return -ENOMEM; diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_droq.c b/drivers/net/ethernet/cavium/liquidio/octeon_droq.c index 9372d4ce9954..6b05cd62e26c 100644 --- a/drivers/net/ethernet/cavium/liquidio/octeon_droq.c +++ b/drivers/net/ethernet/cavium/liquidio/octeon_droq.c @@ -286,8 +286,7 @@ int octeon_init_droq(struct octeon_device *oct, numa_node); if (!droq->recv_buf_list) droq->recv_buf_list = (struct octeon_recv_buffer *) - vzalloc(droq->max_count * - OCT_DROQ_RECVBUF_SIZE); + vzalloc(array_size(droq->max_count, OCT_DROQ_RECVBUF_SIZE)); if (!droq->recv_buf_list) { dev_err(&oct->pci_dev->dev, "Output queue recv buf list alloc failed\n"); goto init_droq_fail; diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c index 9e1e2d5b80dc..3549269f6906 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c @@ -1462,8 +1462,7 @@ static int hns_dsaf_init(struct dsaf_device *dsaf_dev) return ret; /* malloc mem for tcam mac key(vlan+mac) */ - priv->soft_mac_tbl = vzalloc(sizeof(*priv->soft_mac_tbl) - * DSAF_TCAM_SUM); + priv->soft_mac_tbl = vzalloc(array_size(DSAF_TCAM_SUM, sizeof(*priv->soft_mac_tbl))); if (!priv->soft_mac_tbl) { ret = -ENOMEM; goto remove_hw; diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c index e1de97effcd2..9793720180ce 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c @@ -754,11 +754,11 @@ static int init_cmdq(struct hinic_cmdq *cmdq, struct hinic_wq *wq, spin_lock_init(&cmdq->cmdq_lock); - cmdq->done = vzalloc(wq->q_depth * sizeof(*cmdq->done)); + cmdq->done = vzalloc(array_size(sizeof(*cmdq->done), wq->q_depth)); if (!cmdq->done) return -ENOMEM; - cmdq->errcode = vzalloc(wq->q_depth * sizeof(*cmdq->errcode)); + cmdq->errcode = vzalloc(array_size(sizeof(*cmdq->errcode), wq->q_depth)); if (!cmdq->errcode) { err = -ENOMEM; goto err_errcode; diff --git a/drivers/net/ethernet/neterion/vxge/vxge-config.c b/drivers/net/ethernet/neterion/vxge/vxge-config.c index c9d02e6165c8..afa5c4ec9d10 100644 --- a/drivers/net/ethernet/neterion/vxge/vxge-config.c +++ b/drivers/net/ethernet/neterion/vxge/vxge-config.c @@ -2565,7 +2565,7 @@ __vxge_hw_mempool_grow(struct vxge_hw_mempool *mempool, u32 num_allocate, * allocate new memblock and its private part at once. * This helps to minimize memory usage a lot. */ mempool->memblocks_priv_arr[i] = - vzalloc(mempool->items_priv_size * n_items); + vzalloc(array_size(mempool->items_priv_size, n_items)); if (mempool->memblocks_priv_arr[i] == NULL) { status = VXGE_HW_ERR_OUT_OF_MEMORY; goto exit; @@ -2665,7 +2665,7 @@ __vxge_hw_mempool_create(struct __vxge_hw_device *devh, /* allocate array of memblocks */ mempool->memblocks_arr = - vzalloc(sizeof(void *) * mempool->memblocks_max); + vzalloc(array_size(sizeof(void *), mempool->memblocks_max)); if (mempool->memblocks_arr == NULL) { __vxge_hw_mempool_destroy(mempool); status = VXGE_HW_ERR_OUT_OF_MEMORY; @@ -2675,7 +2675,7 @@ __vxge_hw_mempool_create(struct __vxge_hw_device *devh, /* allocate array of private parts of items per memblocks */ mempool->memblocks_priv_arr = - vzalloc(sizeof(void *) * mempool->memblocks_max); + vzalloc(array_size(sizeof(void *), mempool->memblocks_max)); if (mempool->memblocks_priv_arr == NULL) { __vxge_hw_mempool_destroy(mempool); status = VXGE_HW_ERR_OUT_OF_MEMORY; @@ -2685,8 +2685,7 @@ __vxge_hw_mempool_create(struct __vxge_hw_device *devh, /* allocate array of memblocks DMA objects */ mempool->memblocks_dma_arr = - vzalloc(sizeof(struct vxge_hw_mempool_dma) * - mempool->memblocks_max); + vzalloc(array_size(sizeof(struct vxge_hw_mempool_dma), mempool->memblocks_max)); if (mempool->memblocks_dma_arr == NULL) { __vxge_hw_mempool_destroy(mempool); status = VXGE_HW_ERR_OUT_OF_MEMORY; @@ -2695,7 +2694,7 @@ __vxge_hw_mempool_create(struct __vxge_hw_device *devh, } /* allocate hash array of items */ - mempool->items_arr = vzalloc(sizeof(void *) * mempool->items_max); + mempool->items_arr = vzalloc(array_size(sizeof(void *), mempool->items_max)); if (mempool->items_arr == NULL) { __vxge_hw_mempool_destroy(mempool); status = VXGE_HW_ERR_OUT_OF_MEMORY; diff --git a/drivers/net/ethernet/qlogic/qed/qed_l2.c b/drivers/net/ethernet/qlogic/qed/qed_l2.c index 5e5ca14bb00f..844dc2a3589e 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_l2.c +++ b/drivers/net/ethernet/qlogic/qed/qed_l2.c @@ -2399,7 +2399,7 @@ static int qed_update_vport(struct qed_dev *cdev, if (!cdev) return -ENODEV; - rss = vzalloc(sizeof(*rss) * cdev->num_hwfns); + rss = vzalloc(array_size(sizeof(*rss), cdev->num_hwfns)); if (!rss) return -ENOMEM; diff --git a/drivers/net/ethernet/qlogic/qede/qede_filter.c b/drivers/net/ethernet/qlogic/qede/qede_filter.c index e7ad95de3da8..ab5a6709d00c 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_filter.c +++ b/drivers/net/ethernet/qlogic/qede/qede_filter.c @@ -307,8 +307,7 @@ int qede_alloc_arfs(struct qede_dev *edev) for (i = 0; i <= QEDE_RFS_FLW_MASK; i++) INIT_HLIST_HEAD(QEDE_ARFS_BUCKET_HEAD(edev, i)); - edev->arfs->arfs_fltr_bmap = vzalloc(BITS_TO_LONGS(QEDE_RFS_MAX_FLTR) * - sizeof(long)); + edev->arfs->arfs_fltr_bmap = vzalloc(array_size(sizeof(long), BITS_TO_LONGS(QEDE_RFS_MAX_FLTR))); if (!edev->arfs->arfs_fltr_bmap) { vfree(edev->arfs); edev->arfs = NULL; diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c index aae81226a0a4..7c9e45d4ff5b 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c @@ -386,8 +386,7 @@ int qlcnic_83xx_setup_intr(struct qlcnic_adapter *adapter) } /* setup interrupt mapping table for fw */ - ahw->intr_tbl = vzalloc(num_msix * - sizeof(struct qlcnic_intrpt_config)); + ahw->intr_tbl = vzalloc(array_size(num_msix, sizeof(struct qlcnic_intrpt_config))); if (!ahw->intr_tbl) return -ENOMEM; diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index 8c6724063231..58b6538dc7be 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c @@ -916,8 +916,7 @@ int qlcnic_82xx_mq_intrpt(struct qlcnic_adapter *adapter, int op_type) if (qlcnic_check_multi_tx(adapter) && !ahw->diag_test && (adapter->flags & QLCNIC_MSIX_ENABLED)) { - ahw->intr_tbl = vzalloc(ahw->num_msix * - sizeof(struct qlcnic_intrpt_config)); + ahw->intr_tbl = vzalloc(array_size(sizeof(struct qlcnic_intrpt_config), ahw->num_msix)); if (!ahw->intr_tbl) return -ENOMEM; diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index 2d92a9fe4606..9e504a27f0fa 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -4820,7 +4820,7 @@ static int efx_ef10_filter_table_probe(struct efx_nic *efx) net_dev->hw_features &= ~NETIF_F_HW_VLAN_CTAG_FILTER; } - table->entry = vzalloc(HUNT_FILTER_TBL_ROWS * sizeof(*table->entry)); + table->entry = vzalloc(array_size(HUNT_FILTER_TBL_ROWS, sizeof(*table->entry))); if (!table->entry) { rc = -ENOMEM; goto fail; diff --git a/drivers/net/ethernet/sfc/falcon/farch.c b/drivers/net/ethernet/sfc/falcon/farch.c index 05916c710d8c..2527cdc55863 100644 --- a/drivers/net/ethernet/sfc/falcon/farch.c +++ b/drivers/net/ethernet/sfc/falcon/farch.c @@ -2755,7 +2755,7 @@ int ef4_farch_filter_table_probe(struct ef4_nic *efx) GFP_KERNEL); if (!table->used_bitmap) goto fail; - table->spec = vzalloc(table->size * sizeof(*table->spec)); + table->spec = vzalloc(array_size(sizeof(*table->spec), table->size)); if (!table->spec) goto fail; } diff --git a/drivers/net/ethernet/sfc/farch.c b/drivers/net/ethernet/sfc/farch.c index ba45150f53c7..63b561a6de2c 100644 --- a/drivers/net/ethernet/sfc/farch.c +++ b/drivers/net/ethernet/sfc/farch.c @@ -2834,7 +2834,7 @@ int efx_farch_filter_table_probe(struct efx_nic *efx) GFP_KERNEL); if (!table->used_bitmap) goto fail; - table->spec = vzalloc(table->size * sizeof(*table->spec)); + table->spec = vzalloc(array_size(sizeof(*table->spec), table->size)); if (!table->spec) goto fail; } diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c index c22a7892648e..f7e102df23e8 100644 --- a/drivers/net/ppp/pptp.c +++ b/drivers/net/ppp/pptp.c @@ -650,7 +650,7 @@ static int __init pptp_init_module(void) int err = 0; pr_info("PPTP driver version " PPTP_DRIVER_VERSION "\n"); - callid_sock = vzalloc((MAX_CALLID + 1) * sizeof(void *)); + callid_sock = vzalloc(array_size(sizeof(void *), (MAX_CALLID + 1))); if (!callid_sock) return -ENOMEM; diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c index a56d3eab35dd..2e7919bbc250 100644 --- a/drivers/net/xen-netback/xenbus.c +++ b/drivers/net/xen-netback/xenbus.c @@ -977,8 +977,7 @@ static void connect(struct backend_info *be) } /* Use the number of queues requested by the frontend */ - be->vif->queues = vzalloc(requested_num_queues * - sizeof(struct xenvif_queue)); + be->vif->queues = vzalloc(array_size(requested_num_queues, sizeof(struct xenvif_queue))); if (!be->vif->queues) { xenbus_dev_fatal(dev, -ENOMEM, "allocating queues"); diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index 05a25aa4e112..081acc33955b 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c @@ -4508,8 +4508,7 @@ megasas_alloc_fusion_context(struct megasas_instance *instance) (struct LD_LOAD_BALANCE_INFO *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, fusion->load_balance_info_pages); if (!fusion->load_balance_info) { - fusion->load_balance_info = vzalloc(MAX_LOGICAL_DRIVES_EXT * - sizeof(struct LD_LOAD_BALANCE_INFO)); + fusion->load_balance_info = vzalloc(array_size(MAX_LOGICAL_DRIVES_EXT, sizeof(struct LD_LOAD_BALANCE_INFO))); if (!fusion->load_balance_info) dev_err(&instance->pdev->dev, "Failed to allocate load_balance_info, " "continuing without Load Balance support\n"); diff --git a/drivers/soc/fsl/qbman/qman.c b/drivers/soc/fsl/qbman/qman.c index 5a0a640323fd..6e03864e880b 100644 --- a/drivers/soc/fsl/qbman/qman.c +++ b/drivers/soc/fsl/qbman/qman.c @@ -989,7 +989,7 @@ int qman_alloc_fq_table(u32 _num_fqids) { num_fqids = _num_fqids; - fq_table = vzalloc(num_fqids * 2 * sizeof(struct qman_fq *)); + fq_table = vzalloc(array_size(sizeof(struct qman_fq *), (num_fqids * 2))); if (!fq_table) return -ENOMEM; diff --git a/drivers/spmi/simulator/spmi-sim.c b/drivers/spmi/simulator/spmi-sim.c index 19961154a787..db08e0e6df39 100644 --- a/drivers/spmi/simulator/spmi-sim.c +++ b/drivers/spmi/simulator/spmi-sim.c @@ -1201,7 +1201,7 @@ static int spmi_sim_probe(struct platform_device *pdev) } sim->range[i].start = res->start; sim->range[i].end = res->end; - sim->range[i].reg = vzalloc(len * sizeof(*sim->range[i].reg)); + sim->range[i].reg = vzalloc(array_size(len, sizeof(*sim->range[i].reg))); if (!sim->range[i].reg) { rc = -ENOMEM; goto err_free_ranges; diff --git a/drivers/staging/comedi/comedi_buf.c b/drivers/staging/comedi/comedi_buf.c index 955d9eeea367..f9a4b65485b0 100644 --- a/drivers/staging/comedi/comedi_buf.c +++ b/drivers/staging/comedi/comedi_buf.c @@ -108,7 +108,7 @@ static void __comedi_buf_alloc(struct comedi_device *dev, /* Need ref to hardware device to free buffer later. */ bm->dma_hw_dev = get_device(dev->hw_dev); - bm->page_list = vzalloc(sizeof(*buf) * n_pages); + bm->page_list = vzalloc(array_size(n_pages, sizeof(*buf))); if (bm->page_list) pages = vmalloc(array_size(n_pages, sizeof(struct page *))); diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme.c b/drivers/staging/rtl8188eu/core/rtw_mlme.c index f6d71587b803..02f286a580c3 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme.c @@ -53,7 +53,7 @@ int rtw_init_mlme_priv(struct adapter *padapter) memset(&pmlmepriv->assoc_ssid, 0, sizeof(struct ndis_802_11_ssid)); - pbuf = vzalloc(MAX_BSS_CNT * (sizeof(struct wlan_network))); + pbuf = vzalloc(array_size(MAX_BSS_CNT, sizeof(struct wlan_network))); if (!pbuf) { res = _FAIL; diff --git a/drivers/staging/rtl8723bs/core/rtw_mlme.c b/drivers/staging/rtl8723bs/core/rtw_mlme.c index cb8a95aabd6c..278edf4a93dd 100644 --- a/drivers/staging/rtl8723bs/core/rtw_mlme.c +++ b/drivers/staging/rtl8723bs/core/rtw_mlme.c @@ -47,7 +47,7 @@ sint _rtw_init_mlme_priv(struct adapter *padapter) memset(&pmlmepriv->assoc_ssid, 0, sizeof(struct ndis_802_11_ssid)); - pbuf = vzalloc(MAX_BSS_CNT * (sizeof(struct wlan_network))); + pbuf = vzalloc(array_size(MAX_BSS_CNT, sizeof(struct wlan_network))); if (pbuf == NULL) { res = _FAIL; diff --git a/drivers/staging/rts5208/rtsx_chip.c b/drivers/staging/rts5208/rtsx_chip.c index f8f9579cc679..8a823466ca2b 100644 --- a/drivers/staging/rts5208/rtsx_chip.c +++ b/drivers/staging/rts5208/rtsx_chip.c @@ -1660,13 +1660,13 @@ int rtsx_write_cfg_seq(struct rtsx_chip *chip, u8 func, u16 addr, u8 *buf, dev_dbg(rtsx_dev(chip), "dw_len = %d\n", dw_len); - data = vzalloc(dw_len * 4); + data = vzalloc(array_size(dw_len, 4)); if (!data) { rtsx_trace(chip); return STATUS_NOMEM; } - mask = vzalloc(dw_len * 4); + mask = vzalloc(array_size(dw_len, 4)); if (!mask) { vfree(data); rtsx_trace(chip); diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 4b41a3a4412c..b88d086c709a 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -254,7 +254,7 @@ int transport_alloc_session_tags(struct se_session *se_sess, se_sess->sess_cmd_map = kcalloc(tag_size, tag_num, GFP_KERNEL | __GFP_NOWARN | __GFP_RETRY_MAYFAIL); if (!se_sess->sess_cmd_map) { - se_sess->sess_cmd_map = vzalloc(tag_num * tag_size); + se_sess->sess_cmd_map = vzalloc(array_size(tag_size, tag_num)); if (!se_sess->sess_cmd_map) { pr_err("Unable to allocate se_sess->sess_cmd_map\n"); return -ENOMEM; diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c index 334f2ad60704..6a9e09b64fb7 100644 --- a/fs/nfsd/nfscache.c +++ b/fs/nfsd/nfscache.c @@ -177,7 +177,7 @@ int nfsd_reply_cache_init(void) drc_hashtbl = kcalloc(hashsize, sizeof(*drc_hashtbl), GFP_KERNEL); if (!drc_hashtbl) { - drc_hashtbl = vzalloc(hashsize * sizeof(*drc_hashtbl)); + drc_hashtbl = vzalloc(array_size(hashsize, sizeof(*drc_hashtbl))); if (!drc_hashtbl) goto out_nomem; } diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index 272ca73094c8..19dff5c26d3d 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c @@ -350,7 +350,7 @@ static struct reiserfs_journal_cnode *allocate_cnodes(int num_cnodes) if (num_cnodes <= 0) { return NULL; } - head = vzalloc(num_cnodes * sizeof(struct reiserfs_journal_cnode)); + head = vzalloc(array_size(num_cnodes, sizeof(struct reiserfs_journal_cnode))); if (!head) { return NULL; } diff --git a/fs/reiserfs/resize.c b/fs/reiserfs/resize.c index 6052d323bc9a..38bac15d7be8 100644 --- a/fs/reiserfs/resize.c +++ b/fs/reiserfs/resize.c @@ -120,7 +120,7 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new) * array of bitmap block pointers */ bitmap = - vzalloc(sizeof(struct reiserfs_bitmap_info) * bmap_nr_new); + vzalloc(array_size(bmap_nr_new, sizeof(struct reiserfs_bitmap_info))); if (!bitmap) { /* * Journal bitmaps are still supersized, but the diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 0af81da04e66..d8d4f77337ef 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -4560,7 +4560,7 @@ static int adjust_insn_aux_data(struct bpf_verifier_env *env, u32 prog_len, if (cnt == 1) return 0; - new_data = vzalloc(sizeof(struct bpf_insn_aux_data) * prog_len); + new_data = vzalloc(array_size(prog_len, sizeof(struct bpf_insn_aux_data))); if (!new_data) return -ENOMEM; memcpy(new_data, old_data, sizeof(struct bpf_insn_aux_data) * off); @@ -5012,8 +5012,7 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr) if (!env) return -ENOMEM; - env->insn_aux_data = vzalloc(sizeof(struct bpf_insn_aux_data) * - (*prog)->len); + env->insn_aux_data = vzalloc(array_size(sizeof(struct bpf_insn_aux_data), (*prog)->len)); ret = -ENOMEM; if (!env->insn_aux_data) goto err_free_env; @@ -5147,8 +5146,7 @@ int bpf_analyzer(struct bpf_prog *prog, const struct bpf_ext_analyzer_ops *ops, if (!env) return -ENOMEM; - env->insn_aux_data = vzalloc(sizeof(struct bpf_insn_aux_data) * - prog->len); + env->insn_aux_data = vzalloc(array_size(sizeof(struct bpf_insn_aux_data), prog->len)); ret = -ENOMEM; if (!env->insn_aux_data) goto err_free_env; diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c index 9f48f4412297..5eb030ab3004 100644 --- a/kernel/kexec_file.c +++ b/kernel/kexec_file.c @@ -660,7 +660,7 @@ static int __kexec_load_purgatory(struct kimage *image, unsigned long min, * ->sh_offset fields to keep track of permanent and temporary * locations of sections. */ - sechdrs = vzalloc(pi->ehdr->e_shnum * sizeof(Elf_Shdr)); + sechdrs = vzalloc(array_size(sizeof(Elf_Shdr), pi->ehdr->e_shnum)); if (!sechdrs) return -ENOMEM; diff --git a/lib/test_firmware.c b/lib/test_firmware.c index 2e5e18bbfd28..b31c7c82ce55 100644 --- a/lib/test_firmware.c +++ b/lib/test_firmware.c @@ -621,8 +621,7 @@ static ssize_t trigger_batched_requests_store(struct device *dev, mutex_lock(&test_fw_mutex); - test_fw_config->reqs = vzalloc(sizeof(struct test_batched_req) * - test_fw_config->num_requests * 2); + test_fw_config->reqs = vzalloc(array3_size(sizeof(struct test_batched_req), test_fw_config->num_requests, 2)); if (!test_fw_config->reqs) { rc = -ENOMEM; goto out_unlock; @@ -723,8 +722,7 @@ ssize_t trigger_batched_requests_async_store(struct device *dev, mutex_lock(&test_fw_mutex); - test_fw_config->reqs = vzalloc(sizeof(struct test_batched_req) * - test_fw_config->num_requests * 2); + test_fw_config->reqs = vzalloc(array3_size(sizeof(struct test_batched_req), test_fw_config->num_requests, 2)); if (!test_fw_config->reqs) { rc = -ENOMEM; goto out; diff --git a/lib/test_kmod.c b/lib/test_kmod.c index cf619795a182..dc1c2248ceda 100644 --- a/lib/test_kmod.c +++ b/lib/test_kmod.c @@ -781,8 +781,7 @@ static int kmod_config_sync_info(struct kmod_test_device *test_dev) struct test_config *config = &test_dev->config; free_test_dev_info(test_dev); - test_dev->info = vzalloc(config->num_threads * - sizeof(struct kmod_test_device_info)); + test_dev->info = vzalloc(array_size(sizeof(struct kmod_test_device_info), config->num_threads)); if (!test_dev->info) { dev_err(test_dev->dev, "Cannot alloc test_dev info\n"); return -ENOMEM; diff --git a/lib/test_rhashtable.c b/lib/test_rhashtable.c index 0ffca990a833..ed60c452e639 100644 --- a/lib/test_rhashtable.c +++ b/lib/test_rhashtable.c @@ -383,10 +383,10 @@ static int __init test_rht_init(void) pr_info("Testing concurrent rhashtable access from %d threads\n", tcount); sema_init(&prestart_sem, 1 - tcount); - tdata = vzalloc(tcount * sizeof(struct thread_data)); + tdata = vzalloc(array_size(tcount, sizeof(struct thread_data))); if (!tdata) return -ENOMEM; - objs = vzalloc(tcount * entries * sizeof(struct test_obj)); + objs = vzalloc(array_size(sizeof(struct test_obj), (tcount * entries))); if (!objs) { vfree(tdata); return -ENOMEM; diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 24ddcc194607..0f63b9077460 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -1832,7 +1832,7 @@ static int ethtool_get_strings(struct net_device *dev, void __user *useraddr) gstrings.len = ret; if (gstrings.len) { - data = vzalloc(gstrings.len * ETH_GSTRING_LEN); + data = vzalloc(array_size(gstrings.len, ETH_GSTRING_LEN)); if (!data) return -ENOMEM; @@ -1936,7 +1936,7 @@ static int ethtool_get_stats(struct net_device *dev, void __user *useraddr) stats.n_stats = n_stats; if (n_stats) { - data = vzalloc(n_stats * sizeof(u64)); + data = vzalloc(array_size(n_stats, sizeof(u64))); if (!data) return -ENOMEM; ops->get_ethtool_stats(dev, &stats, data); @@ -1979,7 +1979,7 @@ static int ethtool_get_phy_stats(struct net_device *dev, void __user *useraddr) stats.n_stats = n_stats; if (n_stats) { - data = vzalloc(n_stats * sizeof(u64)); + data = vzalloc(array_size(n_stats, sizeof(u64))); if (!data) return -ENOMEM; diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 42ee9a5bfc5c..6ee5988b44f8 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -4265,7 +4265,7 @@ static char *alloc_one_pg_vec_page(unsigned long order) return buffer; /* __get_free_pages failed, fall back to vmalloc */ - buffer = vzalloc((1 << order) * PAGE_SIZE); + buffer = vzalloc(array_size((1 << order), PAGE_SIZE)); if (buffer) return buffer; From 6ee1a90594af0de00bfee7c841d9aa06e6ac4c67 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 12 Jun 2018 14:27:52 -0700 Subject: [PATCH 582/592] treewide: Use array_size() in vzalloc_node() The vzalloc_node() function has no 2-factor argument form, so multiplication factors need to be wrapped in array_size(). This patch replaces cases of: vzalloc_node(a * b, node) with: vzalloc_node(array_size(a, b), node) as well as handling cases of: vzalloc_node(a * b * c, node) with: vzalloc_node(array3_size(a, b, c), node) This does, however, attempt to ignore constant size factors like: vzalloc_node(4 * 1024, node) though any constants defined via macros get caught up in the conversion. Any factors with a sizeof() of "unsigned char", "char", and "u8" were dropped, since they're redundant. The Coccinelle script used for this was: // Fix redundant parens around sizeof(). @@ type TYPE; expression THING, E; @@ ( vzalloc_node( - (sizeof(TYPE)) * E + sizeof(TYPE) * E , ...) | vzalloc_node( - (sizeof(THING)) * E + sizeof(THING) * E , ...) ) // Drop single-byte sizes and redundant parens. @@ expression COUNT; typedef u8; typedef __u8; @@ ( vzalloc_node( - sizeof(u8) * (COUNT) + COUNT , ...) | vzalloc_node( - sizeof(__u8) * (COUNT) + COUNT , ...) | vzalloc_node( - sizeof(char) * (COUNT) + COUNT , ...) | vzalloc_node( - sizeof(unsigned char) * (COUNT) + COUNT , ...) | vzalloc_node( - sizeof(u8) * COUNT + COUNT , ...) | vzalloc_node( - sizeof(__u8) * COUNT + COUNT , ...) | vzalloc_node( - sizeof(char) * COUNT + COUNT , ...) | vzalloc_node( - sizeof(unsigned char) * COUNT + COUNT , ...) ) // 2-factor product with sizeof(type/expression) and identifier or constant. @@ type TYPE; expression THING; identifier COUNT_ID; constant COUNT_CONST; @@ ( vzalloc_node( - sizeof(TYPE) * (COUNT_ID) + array_size(COUNT_ID, sizeof(TYPE)) , ...) | vzalloc_node( - sizeof(TYPE) * COUNT_ID + array_size(COUNT_ID, sizeof(TYPE)) , ...) | vzalloc_node( - sizeof(TYPE) * (COUNT_CONST) + array_size(COUNT_CONST, sizeof(TYPE)) , ...) | vzalloc_node( - sizeof(TYPE) * COUNT_CONST + array_size(COUNT_CONST, sizeof(TYPE)) , ...) | vzalloc_node( - sizeof(THING) * (COUNT_ID) + array_size(COUNT_ID, sizeof(THING)) , ...) | vzalloc_node( - sizeof(THING) * COUNT_ID + array_size(COUNT_ID, sizeof(THING)) , ...) | vzalloc_node( - sizeof(THING) * (COUNT_CONST) + array_size(COUNT_CONST, sizeof(THING)) , ...) | vzalloc_node( - sizeof(THING) * COUNT_CONST + array_size(COUNT_CONST, sizeof(THING)) , ...) ) // 2-factor product, only identifiers. @@ identifier SIZE, COUNT; @@ vzalloc_node( - SIZE * COUNT + array_size(COUNT, SIZE) , ...) // 3-factor product with 1 sizeof(type) or sizeof(expression), with // redundant parens removed. @@ expression THING; identifier STRIDE, COUNT; type TYPE; @@ ( vzalloc_node( - sizeof(TYPE) * (COUNT) * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | vzalloc_node( - sizeof(TYPE) * (COUNT) * STRIDE + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | vzalloc_node( - sizeof(TYPE) * COUNT * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | vzalloc_node( - sizeof(TYPE) * COUNT * STRIDE + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | vzalloc_node( - sizeof(THING) * (COUNT) * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) | vzalloc_node( - sizeof(THING) * (COUNT) * STRIDE + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) | vzalloc_node( - sizeof(THING) * COUNT * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) | vzalloc_node( - sizeof(THING) * COUNT * STRIDE + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) ) // 3-factor product with 2 sizeof(variable), with redundant parens removed. @@ expression THING1, THING2; identifier COUNT; type TYPE1, TYPE2; @@ ( vzalloc_node( - sizeof(TYPE1) * sizeof(TYPE2) * COUNT + array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2)) , ...) | vzalloc_node( - sizeof(TYPE1) * sizeof(THING2) * (COUNT) + array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2)) , ...) | vzalloc_node( - sizeof(THING1) * sizeof(THING2) * COUNT + array3_size(COUNT, sizeof(THING1), sizeof(THING2)) , ...) | vzalloc_node( - sizeof(THING1) * sizeof(THING2) * (COUNT) + array3_size(COUNT, sizeof(THING1), sizeof(THING2)) , ...) | vzalloc_node( - sizeof(TYPE1) * sizeof(THING2) * COUNT + array3_size(COUNT, sizeof(TYPE1), sizeof(THING2)) , ...) | vzalloc_node( - sizeof(TYPE1) * sizeof(THING2) * (COUNT) + array3_size(COUNT, sizeof(TYPE1), sizeof(THING2)) , ...) ) // 3-factor product, only identifiers, with redundant parens removed. @@ identifier STRIDE, SIZE, COUNT; @@ ( vzalloc_node( - (COUNT) * STRIDE * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) | vzalloc_node( - COUNT * (STRIDE) * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) | vzalloc_node( - COUNT * STRIDE * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | vzalloc_node( - (COUNT) * (STRIDE) * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) | vzalloc_node( - COUNT * (STRIDE) * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | vzalloc_node( - (COUNT) * STRIDE * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | vzalloc_node( - (COUNT) * (STRIDE) * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | vzalloc_node( - COUNT * STRIDE * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) ) // Any remaining multi-factor products, first at least 3-factor products // when they're not all constants... @@ expression E1, E2, E3; constant C1, C2, C3; @@ ( vzalloc_node(C1 * C2 * C3, ...) | vzalloc_node( - E1 * E2 * E3 + array3_size(E1, E2, E3) , ...) ) // And then all remaining 2 factors products when they're not all constants. @@ expression E1, E2; constant C1, C2; @@ ( vzalloc_node(C1 * C2, ...) | vzalloc_node( - E1 * E2 + array_size(E1, E2) , ...) ) Signed-off-by: Kees Cook Signed-off-by: Adam W. Willis Signed-off-by: UtsavBalar1231 --- drivers/infiniband/sw/rdmavt/qp.c | 2 +- drivers/net/ethernet/cavium/liquidio/octeon_droq.c | 3 +-- net/core/pktgen.c | 2 +- net/rds/ib_cm.c | 4 ++-- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/infiniband/sw/rdmavt/qp.c b/drivers/infiniband/sw/rdmavt/qp.c index 071496dac63e..0eef239f27d7 100644 --- a/drivers/infiniband/sw/rdmavt/qp.c +++ b/drivers/infiniband/sw/rdmavt/qp.c @@ -814,7 +814,7 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd, sz = sizeof(struct rvt_sge) * init_attr->cap.max_send_sge + sizeof(struct rvt_swqe); - swq = vzalloc_node(sqsize * sz, rdi->dparms.node); + swq = vzalloc_node(array_size(sz, sqsize), rdi->dparms.node); if (!swq) return ERR_PTR(-ENOMEM); diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_droq.c b/drivers/net/ethernet/cavium/liquidio/octeon_droq.c index 6b05cd62e26c..fe1eca433253 100644 --- a/drivers/net/ethernet/cavium/liquidio/octeon_droq.c +++ b/drivers/net/ethernet/cavium/liquidio/octeon_droq.c @@ -281,8 +281,7 @@ int octeon_init_droq(struct octeon_device *oct, droq->max_count); droq->recv_buf_list = (struct octeon_recv_buffer *) - vzalloc_node(droq->max_count * - OCT_DROQ_RECVBUF_SIZE, + vzalloc_node(array_size(droq->max_count, OCT_DROQ_RECVBUF_SIZE), numa_node); if (!droq->recv_buf_list) droq->recv_buf_list = (struct octeon_recv_buffer *) diff --git a/net/core/pktgen.c b/net/core/pktgen.c index bd98819b9c75..d8df2189145a 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -3696,7 +3696,7 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname) return -ENOMEM; strcpy(pkt_dev->odevname, ifname); - pkt_dev->flows = vzalloc_node(MAX_CFLOWS * sizeof(struct flow_state), + pkt_dev->flows = vzalloc_node(array_size(MAX_CFLOWS, sizeof(struct flow_state)), node); if (pkt_dev->flows == NULL) { kfree(pkt_dev); diff --git a/net/rds/ib_cm.c b/net/rds/ib_cm.c index e086395a2355..c56101219a5b 100644 --- a/net/rds/ib_cm.c +++ b/net/rds/ib_cm.c @@ -525,7 +525,7 @@ static int rds_ib_setup_qp(struct rds_connection *conn) goto recv_hdrs_dma_out; } - ic->i_sends = vzalloc_node(ic->i_send_ring.w_nr * sizeof(struct rds_ib_send_work), + ic->i_sends = vzalloc_node(array_size(sizeof(struct rds_ib_send_work), ic->i_send_ring.w_nr), ibdev_to_node(dev)); if (!ic->i_sends) { ret = -ENOMEM; @@ -533,7 +533,7 @@ static int rds_ib_setup_qp(struct rds_connection *conn) goto ack_dma_out; } - ic->i_recvs = vzalloc_node(ic->i_recv_ring.w_nr * sizeof(struct rds_ib_recv_work), + ic->i_recvs = vzalloc_node(array_size(sizeof(struct rds_ib_recv_work), ic->i_recv_ring.w_nr), ibdev_to_node(dev)); if (!ic->i_recvs) { ret = -ENOMEM; From 2f1ded7e127281fbde1ecfa24221b80bd346f9b7 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 12 Jun 2018 14:28:11 -0700 Subject: [PATCH 583/592] treewide: Use array_size() in sock_kmalloc() The sock_kmalloc() function has no 2-factor argument form, so multiplication factors need to be wrapped in array_size(). This patch replaces cases of: sock_kmalloc(handle, a * b, gfp) with: sock_kmalloc(handle, array_size(a, b), gfp) as well as handling cases of: sock_kmalloc(handle, a * b * c, gfp) with: sock_kmalloc(handle, array3_size(a, b, c), gfp) This does, however, attempt to ignore constant size factors like: sock_kmalloc(handle, 4 * 1024, gfp) though any constants defined via macros get caught up in the conversion. Any factors with a sizeof() of "unsigned char", "char", and "u8" were dropped, since they're redundant. The Coccinelle script used for this was: // Fix redundant parens around sizeof(). @@ expression HANDLE; type TYPE; expression THING, E; @@ ( sock_kmalloc(HANDLE, - (sizeof(TYPE)) * E + sizeof(TYPE) * E , ...) | sock_kmalloc(HANDLE, - (sizeof(THING)) * E + sizeof(THING) * E , ...) ) // Drop single-byte sizes and redundant parens. @@ expression HANDLE; expression COUNT; typedef u8; typedef __u8; @@ ( sock_kmalloc(HANDLE, - sizeof(u8) * (COUNT) + COUNT , ...) | sock_kmalloc(HANDLE, - sizeof(__u8) * (COUNT) + COUNT , ...) | sock_kmalloc(HANDLE, - sizeof(char) * (COUNT) + COUNT , ...) | sock_kmalloc(HANDLE, - sizeof(unsigned char) * (COUNT) + COUNT , ...) | sock_kmalloc(HANDLE, - sizeof(u8) * COUNT + COUNT , ...) | sock_kmalloc(HANDLE, - sizeof(__u8) * COUNT + COUNT , ...) | sock_kmalloc(HANDLE, - sizeof(char) * COUNT + COUNT , ...) | sock_kmalloc(HANDLE, - sizeof(unsigned char) * COUNT + COUNT , ...) ) // 2-factor product with sizeof(type/expression) and identifier or constant. @@ expression HANDLE; type TYPE; expression THING; identifier COUNT_ID; constant COUNT_CONST; @@ ( sock_kmalloc(HANDLE, - sizeof(TYPE) * (COUNT_ID) + array_size(COUNT_ID, sizeof(TYPE)) , ...) | sock_kmalloc(HANDLE, - sizeof(TYPE) * COUNT_ID + array_size(COUNT_ID, sizeof(TYPE)) , ...) | sock_kmalloc(HANDLE, - sizeof(TYPE) * (COUNT_CONST) + array_size(COUNT_CONST, sizeof(TYPE)) , ...) | sock_kmalloc(HANDLE, - sizeof(TYPE) * COUNT_CONST + array_size(COUNT_CONST, sizeof(TYPE)) , ...) | sock_kmalloc(HANDLE, - sizeof(THING) * (COUNT_ID) + array_size(COUNT_ID, sizeof(THING)) , ...) | sock_kmalloc(HANDLE, - sizeof(THING) * COUNT_ID + array_size(COUNT_ID, sizeof(THING)) , ...) | sock_kmalloc(HANDLE, - sizeof(THING) * (COUNT_CONST) + array_size(COUNT_CONST, sizeof(THING)) , ...) | sock_kmalloc(HANDLE, - sizeof(THING) * COUNT_CONST + array_size(COUNT_CONST, sizeof(THING)) , ...) ) // 2-factor product, only identifiers. @@ expression HANDLE; identifier SIZE, COUNT; @@ sock_kmalloc(HANDLE, - SIZE * COUNT + array_size(COUNT, SIZE) , ...) // 3-factor product with 1 sizeof(type) or sizeof(expression), with // redundant parens removed. @@ expression HANDLE; expression THING; identifier STRIDE, COUNT; type TYPE; @@ ( sock_kmalloc(HANDLE, - sizeof(TYPE) * (COUNT) * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | sock_kmalloc(HANDLE, - sizeof(TYPE) * (COUNT) * STRIDE + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | sock_kmalloc(HANDLE, - sizeof(TYPE) * COUNT * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | sock_kmalloc(HANDLE, - sizeof(TYPE) * COUNT * STRIDE + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | sock_kmalloc(HANDLE, - sizeof(THING) * (COUNT) * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) | sock_kmalloc(HANDLE, - sizeof(THING) * (COUNT) * STRIDE + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) | sock_kmalloc(HANDLE, - sizeof(THING) * COUNT * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) | sock_kmalloc(HANDLE, - sizeof(THING) * COUNT * STRIDE + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) ) // 3-factor product with 2 sizeof(variable), with redundant parens removed. @@ expression HANDLE; expression THING1, THING2; identifier COUNT; type TYPE1, TYPE2; @@ ( sock_kmalloc(HANDLE, - sizeof(TYPE1) * sizeof(TYPE2) * COUNT + array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2)) , ...) | sock_kmalloc(HANDLE, - sizeof(TYPE1) * sizeof(THING2) * (COUNT) + array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2)) , ...) | sock_kmalloc(HANDLE, - sizeof(THING1) * sizeof(THING2) * COUNT + array3_size(COUNT, sizeof(THING1), sizeof(THING2)) , ...) | sock_kmalloc(HANDLE, - sizeof(THING1) * sizeof(THING2) * (COUNT) + array3_size(COUNT, sizeof(THING1), sizeof(THING2)) , ...) | sock_kmalloc(HANDLE, - sizeof(TYPE1) * sizeof(THING2) * COUNT + array3_size(COUNT, sizeof(TYPE1), sizeof(THING2)) , ...) | sock_kmalloc(HANDLE, - sizeof(TYPE1) * sizeof(THING2) * (COUNT) + array3_size(COUNT, sizeof(TYPE1), sizeof(THING2)) , ...) ) // 3-factor product, only identifiers, with redundant parens removed. @@ expression HANDLE; identifier STRIDE, SIZE, COUNT; @@ ( sock_kmalloc(HANDLE, - (COUNT) * STRIDE * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) | sock_kmalloc(HANDLE, - COUNT * (STRIDE) * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) | sock_kmalloc(HANDLE, - COUNT * STRIDE * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | sock_kmalloc(HANDLE, - (COUNT) * (STRIDE) * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) | sock_kmalloc(HANDLE, - COUNT * (STRIDE) * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | sock_kmalloc(HANDLE, - (COUNT) * STRIDE * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | sock_kmalloc(HANDLE, - (COUNT) * (STRIDE) * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | sock_kmalloc(HANDLE, - COUNT * STRIDE * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) ) // Any remaining multi-factor products, first at least 3-factor products // when they're not all constants... @@ expression HANDLE; expression E1, E2, E3; constant C1, C2, C3; @@ ( sock_kmalloc(HANDLE, C1 * C2 * C3, ...) | sock_kmalloc(HANDLE, - E1 * E2 * E3 + array3_size(E1, E2, E3) , ...) ) // And then all remaining 2 factors products when they're not all constants. @@ expression HANDLE; expression E1, E2; constant C1, C2; @@ ( sock_kmalloc(HANDLE, C1 * C2, ...) | sock_kmalloc(HANDLE, - E1 * E2 + array_size(E1, E2) , ...) ) Signed-off-by: Kees Cook Signed-off-by: Adam W. Willis Signed-off-by: UtsavBalar1231 --- crypto/algif_aead.c | 4 ++-- crypto/algif_skcipher.c | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c index 379e83c8aa52..622e132d12bd 100644 --- a/crypto/algif_aead.c +++ b/crypto/algif_aead.c @@ -256,8 +256,8 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg, processed - as); if (!areq->tsgl_entries) areq->tsgl_entries = 1; - areq->tsgl = sock_kmalloc(sk, sizeof(*areq->tsgl) * - areq->tsgl_entries, + areq->tsgl = sock_kmalloc(sk, + array_size(sizeof(*areq->tsgl), areq->tsgl_entries), GFP_KERNEL); if (!areq->tsgl) { err = -ENOMEM; diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c index d9ec5dca8672..e328eecda03c 100644 --- a/crypto/algif_skcipher.c +++ b/crypto/algif_skcipher.c @@ -103,7 +103,8 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg, areq->tsgl_entries = af_alg_count_tsgl(sk, len, 0); if (!areq->tsgl_entries) areq->tsgl_entries = 1; - areq->tsgl = sock_kmalloc(sk, sizeof(*areq->tsgl) * areq->tsgl_entries, + areq->tsgl = sock_kmalloc(sk, + array_size(sizeof(*areq->tsgl), areq->tsgl_entries), GFP_KERNEL); if (!areq->tsgl) { err = -ENOMEM; From 68da78b60d8d555cd4609ac9f1d612d47385f082 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 12 Jun 2018 14:28:23 -0700 Subject: [PATCH 584/592] treewide: Use array_size() in f2fs_kzalloc() The f2fs_kzalloc() function has no 2-factor argument form, so multiplication factors need to be wrapped in array_size(). This patch replaces cases of: f2fs_kzalloc(handle, a * b, gfp) with: f2fs_kzalloc(handle, array_size(a, b), gfp) as well as handling cases of: f2fs_kzalloc(handle, a * b * c, gfp) with: f2fs_kzalloc(handle, array3_size(a, b, c), gfp) This does, however, attempt to ignore constant size factors like: f2fs_kzalloc(handle, 4 * 1024, gfp) though any constants defined via macros get caught up in the conversion. Any factors with a sizeof() of "unsigned char", "char", and "u8" were dropped, since they're redundant. The Coccinelle script used for this was: // Fix redundant parens around sizeof(). @@ expression HANDLE; type TYPE; expression THING, E; @@ ( f2fs_kzalloc(HANDLE, - (sizeof(TYPE)) * E + sizeof(TYPE) * E , ...) | f2fs_kzalloc(HANDLE, - (sizeof(THING)) * E + sizeof(THING) * E , ...) ) // Drop single-byte sizes and redundant parens. @@ expression HANDLE; expression COUNT; typedef u8; typedef __u8; @@ ( f2fs_kzalloc(HANDLE, - sizeof(u8) * (COUNT) + COUNT , ...) | f2fs_kzalloc(HANDLE, - sizeof(__u8) * (COUNT) + COUNT , ...) | f2fs_kzalloc(HANDLE, - sizeof(char) * (COUNT) + COUNT , ...) | f2fs_kzalloc(HANDLE, - sizeof(unsigned char) * (COUNT) + COUNT , ...) | f2fs_kzalloc(HANDLE, - sizeof(u8) * COUNT + COUNT , ...) | f2fs_kzalloc(HANDLE, - sizeof(__u8) * COUNT + COUNT , ...) | f2fs_kzalloc(HANDLE, - sizeof(char) * COUNT + COUNT , ...) | f2fs_kzalloc(HANDLE, - sizeof(unsigned char) * COUNT + COUNT , ...) ) // 2-factor product with sizeof(type/expression) and identifier or constant. @@ expression HANDLE; type TYPE; expression THING; identifier COUNT_ID; constant COUNT_CONST; @@ ( f2fs_kzalloc(HANDLE, - sizeof(TYPE) * (COUNT_ID) + array_size(COUNT_ID, sizeof(TYPE)) , ...) | f2fs_kzalloc(HANDLE, - sizeof(TYPE) * COUNT_ID + array_size(COUNT_ID, sizeof(TYPE)) , ...) | f2fs_kzalloc(HANDLE, - sizeof(TYPE) * (COUNT_CONST) + array_size(COUNT_CONST, sizeof(TYPE)) , ...) | f2fs_kzalloc(HANDLE, - sizeof(TYPE) * COUNT_CONST + array_size(COUNT_CONST, sizeof(TYPE)) , ...) | f2fs_kzalloc(HANDLE, - sizeof(THING) * (COUNT_ID) + array_size(COUNT_ID, sizeof(THING)) , ...) | f2fs_kzalloc(HANDLE, - sizeof(THING) * COUNT_ID + array_size(COUNT_ID, sizeof(THING)) , ...) | f2fs_kzalloc(HANDLE, - sizeof(THING) * (COUNT_CONST) + array_size(COUNT_CONST, sizeof(THING)) , ...) | f2fs_kzalloc(HANDLE, - sizeof(THING) * COUNT_CONST + array_size(COUNT_CONST, sizeof(THING)) , ...) ) // 2-factor product, only identifiers. @@ expression HANDLE; identifier SIZE, COUNT; @@ f2fs_kzalloc(HANDLE, - SIZE * COUNT + array_size(COUNT, SIZE) , ...) // 3-factor product with 1 sizeof(type) or sizeof(expression), with // redundant parens removed. @@ expression HANDLE; expression THING; identifier STRIDE, COUNT; type TYPE; @@ ( f2fs_kzalloc(HANDLE, - sizeof(TYPE) * (COUNT) * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | f2fs_kzalloc(HANDLE, - sizeof(TYPE) * (COUNT) * STRIDE + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | f2fs_kzalloc(HANDLE, - sizeof(TYPE) * COUNT * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | f2fs_kzalloc(HANDLE, - sizeof(TYPE) * COUNT * STRIDE + array3_size(COUNT, STRIDE, sizeof(TYPE)) , ...) | f2fs_kzalloc(HANDLE, - sizeof(THING) * (COUNT) * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) | f2fs_kzalloc(HANDLE, - sizeof(THING) * (COUNT) * STRIDE + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) | f2fs_kzalloc(HANDLE, - sizeof(THING) * COUNT * (STRIDE) + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) | f2fs_kzalloc(HANDLE, - sizeof(THING) * COUNT * STRIDE + array3_size(COUNT, STRIDE, sizeof(THING)) , ...) ) // 3-factor product with 2 sizeof(variable), with redundant parens removed. @@ expression HANDLE; expression THING1, THING2; identifier COUNT; type TYPE1, TYPE2; @@ ( f2fs_kzalloc(HANDLE, - sizeof(TYPE1) * sizeof(TYPE2) * COUNT + array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2)) , ...) | f2fs_kzalloc(HANDLE, - sizeof(TYPE1) * sizeof(THING2) * (COUNT) + array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2)) , ...) | f2fs_kzalloc(HANDLE, - sizeof(THING1) * sizeof(THING2) * COUNT + array3_size(COUNT, sizeof(THING1), sizeof(THING2)) , ...) | f2fs_kzalloc(HANDLE, - sizeof(THING1) * sizeof(THING2) * (COUNT) + array3_size(COUNT, sizeof(THING1), sizeof(THING2)) , ...) | f2fs_kzalloc(HANDLE, - sizeof(TYPE1) * sizeof(THING2) * COUNT + array3_size(COUNT, sizeof(TYPE1), sizeof(THING2)) , ...) | f2fs_kzalloc(HANDLE, - sizeof(TYPE1) * sizeof(THING2) * (COUNT) + array3_size(COUNT, sizeof(TYPE1), sizeof(THING2)) , ...) ) // 3-factor product, only identifiers, with redundant parens removed. @@ expression HANDLE; identifier STRIDE, SIZE, COUNT; @@ ( f2fs_kzalloc(HANDLE, - (COUNT) * STRIDE * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) | f2fs_kzalloc(HANDLE, - COUNT * (STRIDE) * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) | f2fs_kzalloc(HANDLE, - COUNT * STRIDE * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | f2fs_kzalloc(HANDLE, - (COUNT) * (STRIDE) * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) | f2fs_kzalloc(HANDLE, - COUNT * (STRIDE) * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | f2fs_kzalloc(HANDLE, - (COUNT) * STRIDE * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | f2fs_kzalloc(HANDLE, - (COUNT) * (STRIDE) * (SIZE) + array3_size(COUNT, STRIDE, SIZE) , ...) | f2fs_kzalloc(HANDLE, - COUNT * STRIDE * SIZE + array3_size(COUNT, STRIDE, SIZE) , ...) ) // Any remaining multi-factor products, first at least 3-factor products // when they're not all constants... @@ expression HANDLE; expression E1, E2, E3; constant C1, C2, C3; @@ ( f2fs_kzalloc(HANDLE, C1 * C2 * C3, ...) | f2fs_kzalloc(HANDLE, - E1 * E2 * E3 + array3_size(E1, E2, E3) , ...) ) // And then all remaining 2 factors products when they're not all constants. @@ expression HANDLE; expression E1, E2; constant C1, C2; @@ ( f2fs_kzalloc(HANDLE, C1 * C2, ...) | f2fs_kzalloc(HANDLE, - E1 * E2 + array_size(E1, E2) , ...) ) Signed-off-by: Kees Cook Signed-off-by: Adam W. Willis Signed-off-by: UtsavBalar1231 --- fs/f2fs/compress.c | 10 ++++++---- fs/f2fs/super.c | 5 ++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c index bd9d24189c14..1f1dbfb28b0b 100644 --- a/fs/f2fs/compress.c +++ b/fs/f2fs/compress.c @@ -576,8 +576,9 @@ static int f2fs_compress_pages(struct compress_ctx *cc) max_len = COMPRESS_HEADER_SIZE + cc->clen; cc->nr_cpages = DIV_ROUND_UP(max_len, PAGE_SIZE); - cc->cpages = f2fs_kzalloc(sbi, sizeof(struct page *) * - cc->nr_cpages, GFP_NOFS); + cc->cpages = f2fs_kzalloc(sbi, + array_size(sizeof(struct page *), cc->nr_cpages), + GFP_NOFS); if (!cc->cpages) { ret = -ENOMEM; goto destroy_compress_ctx; @@ -1450,8 +1451,9 @@ struct decompress_io_ctx *f2fs_alloc_dic(struct compress_ctx *cc) dic->rpages[i] = cc->rpages[i]; dic->nr_rpages = cc->cluster_size; - dic->cpages = f2fs_kzalloc(sbi, sizeof(struct page *) * - dic->nr_cpages, GFP_NOFS); + dic->cpages = f2fs_kzalloc(sbi, + array_size(sizeof(struct page *), dic->nr_cpages), + GFP_NOFS); if (!dic->cpages) goto out_free; diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index e22bdf35b540..c87e6e54cab2 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -3054,9 +3054,8 @@ static int init_blkz_info(struct f2fs_sb_info *sbi, int devi) if (nr_sectors & (bdev_zone_sectors(bdev) - 1)) FDEV(devi).nr_blkz++; - FDEV(devi).blkz_seq = f2fs_kvzalloc(sbi, - BITS_TO_LONGS(FDEV(devi).nr_blkz) - * sizeof(unsigned long), + FDEV(devi).blkz_seq = f2fs_kzalloc(sbi, + array_size(sizeof(unsigned long), BITS_TO_LONGS(FDEV(devi).nr_blkz)), GFP_KERNEL); if (!FDEV(devi).blkz_seq) return -ENOMEM; From c2f70e29f5bd43f76262e241f9894920b5f5dceb Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sun, 8 Dec 2019 19:43:46 -0500 Subject: [PATCH 585/592] ext4: optimize __ext4_check_dir_entry() Make __ext4_check_dir_entry() a bit easier to understand, and reduce the object size of the function by over 11%. Signed-off-by: Theodore Ts'o Link: https://lore.kernel.org/r/20191209004346.38526-1-tytso@mit.edu Signed-off-by: Theodore Ts'o Signed-off-by: UtsavBalar1231 --- fs/ext4/dir.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c index 6a5cbe0c4d20..c40e08632635 100644 --- a/fs/ext4/dir.c +++ b/fs/ext4/dir.c @@ -69,6 +69,7 @@ int __ext4_check_dir_entry(const char *function, unsigned int line, const char *error_msg = NULL; const int rlen = ext4_rec_len_from_disk(de->rec_len, dir->i_sb->s_blocksize); + const int next_offset = ((char *) de - buf) + rlen; if (unlikely(rlen < EXT4_DIR_REC_LEN(1))) error_msg = "rec_len is smaller than minimal"; @@ -76,13 +77,11 @@ int __ext4_check_dir_entry(const char *function, unsigned int line, error_msg = "rec_len % 4 != 0"; else if (unlikely(rlen < EXT4_DIR_REC_LEN(de->name_len))) error_msg = "rec_len is too small for name_len"; - else if (unlikely(((char *) de - buf) + rlen > size)) + else if (unlikely(next_offset > size)) error_msg = "directory entry overrun"; - else if (unlikely(((char *) de - buf) + rlen > - size - EXT4_DIR_REC_LEN(1) && - ((char *) de - buf) + rlen != size)) { + else if (unlikely(next_offset > size - EXT4_DIR_REC_LEN(1) && + next_offset != size)) error_msg = "directory entry too close to block end"; - } else if (unlikely(le32_to_cpu(de->inode) > le32_to_cpu(EXT4_SB(dir->i_sb)->s_es->s_inodes_count))) error_msg = "inode out of bounds"; From 2f8008b09d2ad433076ee19eceeb07bac33acea1 Mon Sep 17 00:00:00 2001 From: Vaibhav Jain Date: Mon, 15 Jun 2020 18:14:03 +0530 Subject: [PATCH 586/592] seq_buf: Export seq_buf_printf 'seq_buf' provides a very useful abstraction for writing to a string buffer without needing to worry about it over-flowing. However even though the API has been stable for couple of years now its still not exported to kernel loadable modules limiting its usage. Hence this patch proposes update to 'seq_buf.c' to mark seq_buf_printf() which is part of the seq_buf API to be exported to kernel loadable GPL modules. This symbol will be used in later parts of this patch-set to simplify content creation for a sysfs attribute. Signed-off-by: Vaibhav Jain Acked-by: Steven Rostedt (VMware) Cc: Piotr Maziarz Cc: Cezary Rojewski Cc: Christoph Hellwig Cc: Steven Rostedt Cc: Borislav Petkov Link: https://lore.kernel.org/r/20200615124407.32596-3-vaibhav@linux.ibm.com Signed-off-by: Dan Williams Signed-off-by: UtsavBalar1231 --- lib/seq_buf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/seq_buf.c b/lib/seq_buf.c index 6aabb609dd87..767958cc4c68 100644 --- a/lib/seq_buf.c +++ b/lib/seq_buf.c @@ -91,6 +91,7 @@ int seq_buf_printf(struct seq_buf *s, const char *fmt, ...) return ret; } +EXPORT_SYMBOL_GPL(seq_buf_printf); #ifdef CONFIG_BINARY_PRINTF /** From 3a5e34f19b0b0db73e78233999639c2a66a75abf Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Wed, 15 Nov 2017 17:38:03 -0800 Subject: [PATCH 587/592] mm: remove __GFP_COLD As the page free path makes no distinction between cache hot and cold pages, there is no real useful ordering of pages in the free list that allocation requests can take advantage of. Juding from the users of __GFP_COLD, it is likely that a number of them are the result of copying other sites instead of actually measuring the impact. Remove the __GFP_COLD parameter which simplifies a number of paths in the page allocator. This is potentially controversial but bear in mind that the size of the per-cpu pagelists versus modern cache sizes means that the whole per-cpu list can often fit in the L3 cache. Hence, there is only a potential benefit for microbenchmarks that alloc/free pages in a tight loop. It's even worse when THP is taken into account which has little or no chance of getting a cache-hot page as the per-cpu list is bypassed and the zeroing of multiple pages will thrash the cache anyway. The truncate microbenchmarks are not shown as this patch affects the allocation path and not the free path. A page fault microbenchmark was tested but it showed no sigificant difference which is not surprising given that the __GFP_COLD branches are a miniscule percentage of the fault path. Link: http://lkml.kernel.org/r/20171018075952.10627-9-mgorman@techsingularity.net Signed-off-by: Mel Gorman Acked-by: Vlastimil Babka Cc: Andi Kleen Cc: Dave Chinner Cc: Dave Hansen Cc: Jan Kara Cc: Johannes Weiner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds [UtsavBalar1231: port to 4.14] Signed-off-by: UtsavBalar1231 --- drivers/net/ethernet/amazon/ena/ena_netdev.c | 2 +- drivers/net/ethernet/amd/xgbe/xgbe-desc.c | 2 +- .../net/ethernet/aquantia/atlantic/aq_ring.c | 3 +-- .../ethernet/cavium/liquidio/octeon_network.h | 2 +- drivers/net/ethernet/mellanox/mlx4/en_rx.c | 5 ++-- .../ethernet/netronome/nfp/nfp_net_common.c | 4 +-- drivers/net/ethernet/qlogic/qlge/qlge_main.c | 3 +-- drivers/net/ethernet/sfc/falcon/rx.c | 2 +- drivers/net/ethernet/sfc/rx.c | 2 +- .../net/ethernet/synopsys/dwc-xlgmac-desc.c | 2 +- drivers/net/ethernet/ti/netcp_core.c | 2 +- drivers/net/virtio_net.c | 1 - .../staging/lustre/lustre/mdc/mdc_request.c | 2 +- fs/cachefiles/rdwr.c | 6 ++--- include/linux/gfp.h | 5 ---- include/linux/pagemap.h | 8 +----- include/linux/skbuff.h | 2 +- include/linux/slab.h | 3 --- include/trace/events/mmflags.h | 1 - kernel/power/snapshot.c | 4 +-- mm/filemap.c | 4 +-- mm/page_alloc.c | 26 +++++++------------ mm/percpu-vm.c | 2 +- net/core/skbuff.c | 4 +-- tools/perf/builtin-kmem.c | 1 - 25 files changed, 34 insertions(+), 64 deletions(-) diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c index d9ece9ac6f53..7e1e00d77ea0 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.c +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c @@ -517,7 +517,7 @@ static int ena_refill_rx_bufs(struct ena_ring *rx_ring, u32 num) rc = ena_alloc_rx_page(rx_ring, rx_info, - __GFP_COLD | GFP_ATOMIC | __GFP_COMP); + GFP_ATOMIC | __GFP_COMP); if (unlikely(rc < 0)) { netif_warn(rx_ring->adapter, rx_err, rx_ring->netdev, "failed to alloc buffer for rx queue %d\n", diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-desc.c b/drivers/net/ethernet/amd/xgbe/xgbe-desc.c index a5eaf174d914..533094233659 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-desc.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-desc.c @@ -295,7 +295,7 @@ again: order = alloc_order; /* Try to obtain pages, decreasing order if necessary */ - gfp = GFP_ATOMIC | __GFP_COLD | __GFP_COMP | __GFP_NOWARN; + gfp = GFP_ATOMIC | __GFP_COMP | __GFP_NOWARN; while (order >= 0) { pages = alloc_pages_node(node, gfp, order); if (pages) diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c index 784c3522aaa3..b81ff84d1555 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c @@ -309,8 +309,7 @@ int aq_ring_rx_fill(struct aq_ring_s *self) buff->flags = 0U; buff->len = AQ_CFG_RX_FRAME_MAX; - buff->page = alloc_pages(GFP_ATOMIC | __GFP_COLD | - __GFP_COMP, pages_order); + buff->page = alloc_pages(GFP_ATOMIC | __GFP_COMP, pages_order); if (!buff->page) { err = -ENOMEM; goto err_exit; diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_network.h b/drivers/net/ethernet/cavium/liquidio/octeon_network.h index 9e36319cead6..57853eead4b5 100644 --- a/drivers/net/ethernet/cavium/liquidio/octeon_network.h +++ b/drivers/net/ethernet/cavium/liquidio/octeon_network.h @@ -195,7 +195,7 @@ static inline void struct sk_buff *skb; struct octeon_skb_page_info *skb_pg_info; - page = alloc_page(GFP_ATOMIC | __GFP_COLD); + page = alloc_page(GFP_ATOMIC); if (unlikely(!page)) return NULL; diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c index c6d101351537..82841cb9b98a 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c @@ -193,7 +193,7 @@ static int mlx4_en_fill_rx_buffers(struct mlx4_en_priv *priv) if (mlx4_en_prepare_rx_desc(priv, ring, ring->actual_size, - GFP_KERNEL | __GFP_COLD)) { + GFP_KERNEL)) { if (ring->actual_size < MLX4_EN_MIN_RX_SIZE) { en_err(priv, "Failed to allocate enough rx buffers\n"); return -ENOMEM; @@ -556,8 +556,7 @@ static void mlx4_en_refill_rx_buffers(struct mlx4_en_priv *priv, do { if (mlx4_en_prepare_rx_desc(priv, ring, ring->prod & ring->size_mask, - GFP_ATOMIC | __GFP_COLD | - __GFP_MEMALLOC)) + GFP_ATOMIC | __GFP_MEMALLOC)) break; ring->prod++; } while (likely(--missing)); diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index bffa25d6dc29..a5ed330b88e8 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -1203,7 +1203,7 @@ static void *nfp_net_rx_alloc_one(struct nfp_net_dp *dp, dma_addr_t *dma_addr) } else { struct page *page; - page = alloc_page(GFP_KERNEL | __GFP_COLD); + page = alloc_page(GFP_KERNEL); frag = page ? page_address(page) : NULL; } if (!frag) { @@ -1230,7 +1230,7 @@ static void *nfp_net_napi_alloc_one(struct nfp_net_dp *dp, dma_addr_t *dma_addr) } else { struct page *page; - page = alloc_page(GFP_ATOMIC | __GFP_COLD); + page = alloc_page(GFP_ATOMIC); frag = page ? page_address(page) : NULL; } if (!frag) { diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/drivers/net/ethernet/qlogic/qlge/qlge_main.c index c693e5e8dada..af9dab53a0a6 100644 --- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c +++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c @@ -1092,8 +1092,7 @@ static int ql_get_next_chunk(struct ql_adapter *qdev, struct rx_ring *rx_ring, { if (!rx_ring->pg_chunk.page) { u64 map; - rx_ring->pg_chunk.page = alloc_pages(__GFP_COLD | __GFP_COMP | - GFP_ATOMIC, + rx_ring->pg_chunk.page = alloc_pages(__GFP_COMP | GFP_ATOMIC, qdev->lbq_buf_order); if (unlikely(!rx_ring->pg_chunk.page)) { netif_err(qdev, drv, qdev->ndev, diff --git a/drivers/net/ethernet/sfc/falcon/rx.c b/drivers/net/ethernet/sfc/falcon/rx.c index 6a8406dc0c2b..91097aea6c41 100644 --- a/drivers/net/ethernet/sfc/falcon/rx.c +++ b/drivers/net/ethernet/sfc/falcon/rx.c @@ -163,7 +163,7 @@ static int ef4_init_rx_buffers(struct ef4_rx_queue *rx_queue, bool atomic) do { page = ef4_reuse_page(rx_queue); if (page == NULL) { - page = alloc_pages(__GFP_COLD | __GFP_COMP | + page = alloc_pages(__GFP_COMP | (atomic ? GFP_ATOMIC : GFP_KERNEL), efx->rx_buffer_order); if (unlikely(page == NULL)) diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c index 42443f434569..0004c50d3c83 100644 --- a/drivers/net/ethernet/sfc/rx.c +++ b/drivers/net/ethernet/sfc/rx.c @@ -163,7 +163,7 @@ static int efx_init_rx_buffers(struct efx_rx_queue *rx_queue, bool atomic) do { page = efx_reuse_page(rx_queue); if (page == NULL) { - page = alloc_pages(__GFP_COLD | __GFP_COMP | + page = alloc_pages(__GFP_COMP | (atomic ? GFP_ATOMIC : GFP_KERNEL), efx->rx_buffer_order); if (unlikely(page == NULL)) diff --git a/drivers/net/ethernet/synopsys/dwc-xlgmac-desc.c b/drivers/net/ethernet/synopsys/dwc-xlgmac-desc.c index e9672b1f9968..031cf9c3435a 100644 --- a/drivers/net/ethernet/synopsys/dwc-xlgmac-desc.c +++ b/drivers/net/ethernet/synopsys/dwc-xlgmac-desc.c @@ -335,7 +335,7 @@ static int xlgmac_alloc_pages(struct xlgmac_pdata *pdata, dma_addr_t pages_dma; /* Try to obtain pages, decreasing order if necessary */ - gfp |= __GFP_COLD | __GFP_COMP | __GFP_NOWARN; + gfp |= __GFP_COMP | __GFP_NOWARN; while (order >= 0) { pages = alloc_pages(gfp, order); if (pages) diff --git a/drivers/net/ethernet/ti/netcp_core.c b/drivers/net/ethernet/ti/netcp_core.c index 437d36289786..50d2b76771b5 100644 --- a/drivers/net/ethernet/ti/netcp_core.c +++ b/drivers/net/ethernet/ti/netcp_core.c @@ -906,7 +906,7 @@ static int netcp_allocate_rx_buf(struct netcp_intf *netcp, int fdq) sw_data[0] = (u32)bufptr; } else { /* Allocate a secondary receive queue entry */ - page = alloc_page(GFP_ATOMIC | GFP_DMA | __GFP_COLD); + page = alloc_page(GFP_ATOMIC | GFP_DMA); if (unlikely(!page)) { dev_warn_ratelimited(netcp->ndev_dev, "Secondary page alloc failed\n"); goto fail; diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index bc40745bf772..9ca7ce7f6cd5 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -999,7 +999,6 @@ static bool try_fill_recv(struct virtnet_info *vi, struct receive_queue *rq, int err; bool oom; - gfp |= __GFP_COLD; do { if (vi->mergeable_rx_bufs) err = add_recvbuf_mergeable(vi, rq, gfp); diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 8c97acd79211..1a0ee7578d7f 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -1151,7 +1151,7 @@ static int mdc_read_page_remote(struct file *data, struct page *page0) } for (npages = 1; npages < max_pages; npages++) { - page = page_cache_alloc_cold(inode->i_mapping); + page = page_cache_alloc(inode->i_mapping); if (!page) break; page_pool[npages] = page; diff --git a/fs/cachefiles/rdwr.c b/fs/cachefiles/rdwr.c index c073a0f680fd..a3e279894c6d 100644 --- a/fs/cachefiles/rdwr.c +++ b/fs/cachefiles/rdwr.c @@ -263,8 +263,7 @@ static int cachefiles_read_backing_file_one(struct cachefiles_object *object, goto backing_page_already_present; if (!newpage) { - newpage = __page_cache_alloc(cachefiles_gfp | - __GFP_COLD); + newpage = __page_cache_alloc(cachefiles_gfp); if (!newpage) goto nomem_monitor; } @@ -500,8 +499,7 @@ static int cachefiles_read_backing_file(struct cachefiles_object *object, goto backing_page_already_present; if (!newpage) { - newpage = __page_cache_alloc(cachefiles_gfp | - __GFP_COLD); + newpage = __page_cache_alloc(cachefiles_gfp); if (!newpage) goto nomem; } diff --git a/include/linux/gfp.h b/include/linux/gfp.h index 2c6f13b23484..422a132a51d8 100644 --- a/include/linux/gfp.h +++ b/include/linux/gfp.h @@ -24,7 +24,6 @@ struct vm_area_struct; #define ___GFP_HIGH 0x20u #define ___GFP_IO 0x40u #define ___GFP_FS 0x80u -#define ___GFP_COLD 0x100u #define ___GFP_NOWARN 0x200u #define ___GFP_RETRY_MAYFAIL 0x400u #define ___GFP_NOFAIL 0x800u @@ -193,16 +192,12 @@ struct vm_area_struct; /* * Action modifiers * - * __GFP_COLD indicates that the caller does not expect to be used in the near - * future. Where possible, a cache-cold page will be returned. - * * __GFP_NOWARN suppresses allocation failure reports. * * __GFP_COMP address compound page metadata. * * __GFP_ZERO returns a zeroed page on success. */ -#define __GFP_COLD ((__force gfp_t)___GFP_COLD) #define __GFP_NOWARN ((__force gfp_t)___GFP_NOWARN) #define __GFP_COMP ((__force gfp_t)___GFP_COMP) #define __GFP_ZERO ((__force gfp_t)___GFP_ZERO) diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index af3a946d19be..6eb08a0dbe3b 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h @@ -232,15 +232,9 @@ static inline struct page *page_cache_alloc(struct address_space *x) return __page_cache_alloc(mapping_gfp_mask(x)); } -static inline struct page *page_cache_alloc_cold(struct address_space *x) -{ - return __page_cache_alloc(mapping_gfp_mask(x)|__GFP_COLD); -} - static inline gfp_t readahead_gfp_mask(struct address_space *x) { - return mapping_gfp_mask(x) | - __GFP_COLD | __GFP_NORETRY | __GFP_NOWARN; + return mapping_gfp_mask(x) | __GFP_NORETRY | __GFP_NOWARN; } typedef int filler_t(struct file *, struct page *); diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 9578eb274918..6f1699871a96 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -2722,7 +2722,7 @@ static inline struct page *__dev_alloc_pages(gfp_t gfp_mask, * 4. __GFP_MEMALLOC is ignored if __GFP_NOMEMALLOC is set due to * code in gfp_to_alloc_flags that should be enforcing this. */ - gfp_mask |= __GFP_COLD | __GFP_COMP | __GFP_MEMALLOC; + gfp_mask |= __GFP_COMP | __GFP_MEMALLOC; return alloc_pages_node(NUMA_NO_NODE, gfp_mask, order); } diff --git a/include/linux/slab.h b/include/linux/slab.h index a9376a897ae2..2376ce8966cd 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -498,9 +498,6 @@ static __always_inline void *kmalloc_large(size_t size, gfp_t flags) * Also it is possible to set different flags by OR'ing * in one or more of the following additional @flags: * - * %__GFP_COLD - Request cache-cold pages instead of - * trying to return cache-warm pages. - * * %__GFP_HIGH - This allocation has high priority and may use emergency pools. * * %__GFP_NOFAIL - Indicate that this allocation is in no way allowed to fail diff --git a/include/trace/events/mmflags.h b/include/trace/events/mmflags.h index 40b9cc3bfaf9..1a57a6fb2c86 100644 --- a/include/trace/events/mmflags.h +++ b/include/trace/events/mmflags.h @@ -32,7 +32,6 @@ {(unsigned long)__GFP_ATOMIC, "__GFP_ATOMIC"}, \ {(unsigned long)__GFP_IO, "__GFP_IO"}, \ {(unsigned long)__GFP_FS, "__GFP_FS"}, \ - {(unsigned long)__GFP_COLD, "__GFP_COLD"}, \ {(unsigned long)__GFP_NOWARN, "__GFP_NOWARN"}, \ {(unsigned long)__GFP_RETRY_MAYFAIL, "__GFP_RETRY_MAYFAIL"}, \ {(unsigned long)__GFP_NOFAIL, "__GFP_NOFAIL"}, \ diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c index d4dbe4a6d78f..06f2efd8742f 100644 --- a/kernel/power/snapshot.c +++ b/kernel/power/snapshot.c @@ -1924,7 +1924,7 @@ static int enough_free_mem(unsigned int nr_pages, unsigned int nr_highmem) */ static inline int get_highmem_buffer(int safe_needed) { - buffer = get_image_page(GFP_ATOMIC | __GFP_COLD, safe_needed); + buffer = get_image_page(GFP_ATOMIC, safe_needed); return buffer ? 0 : -ENOMEM; } @@ -1985,7 +1985,7 @@ static int swsusp_alloc(struct memory_bitmap *copy_bm, while (nr_pages-- > 0) { struct page *page; - page = alloc_image_page(GFP_ATOMIC | __GFP_COLD); + page = alloc_image_page(GFP_ATOMIC); if (!page) goto err_out; memory_bm_set_bit(copy_bm, page_to_pfn(page)); diff --git a/mm/filemap.c b/mm/filemap.c index e2ee462c8891..6128cdf0c798 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -2223,7 +2223,7 @@ no_cached_page: * Ok, it wasn't cached, so we need to create a new * page.. */ - page = page_cache_alloc_cold(mapping); + page = page_cache_alloc(mapping); if (!page) { error = -ENOMEM; goto out; @@ -2795,7 +2795,7 @@ static struct page *do_read_cache_page(struct address_space *mapping, repeat: page = find_get_page(mapping, index); if (!page) { - page = __page_cache_alloc(gfp | __GFP_COLD); + page = __page_cache_alloc(gfp); if (!page) return ERR_PTR(-ENOMEM); err = add_to_page_cache_lru(page, mapping, index, gfp); diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 18e2e8a0ad49..0717332cc43a 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -2412,7 +2412,7 @@ static inline struct page *__rmqueue_cma(struct zone *zone, unsigned int order) */ static int rmqueue_bulk(struct zone *zone, unsigned int order, unsigned long count, struct list_head *list, - int migratetype, bool cold) + int migratetype) { int i, alloced = 0; @@ -2445,10 +2445,7 @@ static int rmqueue_bulk(struct zone *zone, unsigned int order, * merge IO requests if the physical pages are ordered * properly. */ - if (likely(!cold)) - list_add(&page->lru, list); - else - list_add_tail(&page->lru, list); + list_add(&page->lru, list); list = &page->lru; alloced++; if (is_migrate_cma(get_pcppage_migratetype(page))) @@ -2474,14 +2471,14 @@ static int rmqueue_bulk(struct zone *zone, unsigned int order, */ static struct list_head *get_populated_pcp_list(struct zone *zone, unsigned int order, struct per_cpu_pages *pcp, - int migratetype, int cold) + int migratetype) { struct list_head *list = &pcp->lists[migratetype]; if (list_empty(list)) { pcp->count += rmqueue_bulk(zone, order, pcp->batch, list, - migratetype, cold); + migratetype); if (list_empty(list)) list = NULL; @@ -2875,7 +2872,7 @@ static inline void zone_statistics(struct zone *preferred_zone, struct zone *z) /* Remove page from the per-cpu list, caller must protect the list */ static struct page *__rmqueue_pcplist(struct zone *zone, int migratetype, - bool cold, struct per_cpu_pages *pcp, + struct per_cpu_pages *pcp, gfp_t gfp_flags) { struct page *page = NULL; @@ -2886,7 +2883,7 @@ static struct page *__rmqueue_pcplist(struct zone *zone, int migratetype, if (migratetype == MIGRATE_MOVABLE && gfp_flags & __GFP_CMA) { list = get_populated_pcp_list(zone, 0, pcp, - get_cma_migrate_type(), cold); + get_cma_migrate_type()); } if (list == NULL) { @@ -2895,18 +2892,14 @@ static struct page *__rmqueue_pcplist(struct zone *zone, int migratetype, * free CMA pages. */ list = get_populated_pcp_list(zone, 0, pcp, - migratetype, cold); + migratetype); if (unlikely(list == NULL) || unlikely(list_empty(list))) return NULL; } - if (cold) - page = list_last_entry(list, struct page, lru); - else - page = list_first_entry(list, struct page, lru); - + page = list_first_entry(list, struct page, lru); list_del(&page->lru); pcp->count--; } while (check_new_pcp(page)); @@ -2920,13 +2913,12 @@ static struct page *rmqueue_pcplist(struct zone *preferred_zone, gfp_t gfp_flags, int migratetype) { struct per_cpu_pages *pcp; - bool cold = ((gfp_flags & __GFP_COLD) != 0); struct page *page; unsigned long flags; local_irq_save(flags); pcp = &this_cpu_ptr(zone->pageset)->pcp; - page = __rmqueue_pcplist(zone, migratetype, cold, pcp, + page = __rmqueue_pcplist(zone, migratetype, pcp, gfp_flags); if (page) { __count_zid_vm_events(PGALLOC, page_zonenum(page), 1 << order); diff --git a/mm/percpu-vm.c b/mm/percpu-vm.c index f48ff9fc86fe..0af71eb2fff0 100644 --- a/mm/percpu-vm.c +++ b/mm/percpu-vm.c @@ -86,7 +86,7 @@ static int pcpu_alloc_pages(struct pcpu_chunk *chunk, unsigned int cpu, tcpu; int i; - gfp |= GFP_KERNEL | __GFP_HIGHMEM | __GFP_COLD; + gfp |= GFP_KERNEL | __GFP_HIGHMEM; for_each_possible_cpu(cpu) { for (i = page_start; i < page_end; i++) { diff --git a/net/core/skbuff.c b/net/core/skbuff.c index eb54fbb09cc5..50f27c2d3066 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -361,7 +361,7 @@ void *netdev_alloc_frag(unsigned int fragsz) { fragsz = SKB_DATA_ALIGN(fragsz); - return __netdev_alloc_frag(fragsz, GFP_ATOMIC | __GFP_COLD); + return __netdev_alloc_frag(fragsz, GFP_ATOMIC); } EXPORT_SYMBOL(netdev_alloc_frag); @@ -376,7 +376,7 @@ void *napi_alloc_frag(unsigned int fragsz) { fragsz = SKB_DATA_ALIGN(fragsz); - return __napi_alloc_frag(fragsz, GFP_ATOMIC | __GFP_COLD); + return __napi_alloc_frag(fragsz, GFP_ATOMIC); } EXPORT_SYMBOL(napi_alloc_frag); diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index ce786f363476..ae63bdf9051b 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c @@ -641,7 +641,6 @@ static const struct { { "__GFP_ATOMIC", "_A" }, { "__GFP_IO", "I" }, { "__GFP_FS", "F" }, - { "__GFP_COLD", "CO" }, { "__GFP_NOWARN", "NWR" }, { "__GFP_RETRY_MAYFAIL", "R" }, { "__GFP_NOFAIL", "NF" }, From 02662cf487e652d0ef4e2240d6abb4eb2eaf8637 Mon Sep 17 00:00:00 2001 From: UtsavBalar1231 Date: Mon, 17 Aug 2020 13:16:34 +0530 Subject: [PATCH 588/592] base: firmware_class: Fix suspicious concatenation warnings ../drivers/base/firmware_class.c:385:27: warning: suspicious concatenation of string literals in an array initialization; did you mean to separate the elements with a comma? [-Wstring-concatenation] "/lib/firmware/updates/" UTS_RELEASE, ^ , ./include/generated/utsrelease.h:1:21: note: expanded from macro 'UTS_RELEASE' ^ ../drivers/base/firmware_class.c:385:2: note: place parentheses around the string literal to silence warning "/lib/firmware/updates/" UTS_RELEASE, ^ ../drivers/base/firmware_class.c:387:19: warning: suspicious concatenation of string literals in an array initialization; did you mean to separate the elements with a comma? [-Wstring-concatenation] "/lib/firmware/" UTS_RELEASE, ^ , ./include/generated/utsrelease.h:1:21: note: expanded from macro 'UTS_RELEASE' ^ ../drivers/base/firmware_class.c:387:2: note: place parentheses around the string literal to silence warning "/lib/firmware/" UTS_RELEASE, Signed-off-by: UtsavBalar1231 --- drivers/base/firmware_class.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 7d1cb5e59338..3f795dea954b 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -382,9 +382,9 @@ static void fw_free_buf(struct firmware_buf *buf) static char fw_path_para[256]; static const char * const fw_path[] = { fw_path_para, - "/lib/firmware/updates/" UTS_RELEASE, + "/lib/firmware/updates/", UTS_RELEASE, "/lib/firmware/updates", - "/lib/firmware/" UTS_RELEASE, + "/lib/firmware/", UTS_RELEASE, "/lib/firmware" }; From 2ff1ac40e7914962599a8c19e6134ef3d8858f3f Mon Sep 17 00:00:00 2001 From: UtsavBalar1231 Date: Mon, 17 Aug 2020 18:59:57 +0530 Subject: [PATCH 589/592] Revert "fs: exec: Introduce is_zygote_pid()" This reverts commit af81b4dbde29eff9998628bff7da233b33fb89f0. --- fs/exec.c | 18 ------------------ include/linux/binfmts.h | 1 - 2 files changed, 19 deletions(-) diff --git a/fs/exec.c b/fs/exec.c index 8dd583d0ef22..2bd49fbdf38b 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -77,17 +77,6 @@ int suid_dumpable = 0; static LIST_HEAD(formats); static DEFINE_RWLOCK(binfmt_lock); -#define ZYGOTE32_BIN "/system/bin/app_process32" -#define ZYGOTE64_BIN "/system/bin/app_process64" -static atomic_t zygote32_pid; -static atomic_t zygote64_pid; - -bool is_zygote_pid(pid_t pid) -{ - return atomic_read(&zygote32_pid) == pid || - atomic_read(&zygote64_pid) == pid; -} - void __register_binfmt(struct linux_binfmt * fmt, int insert) { BUG_ON(!fmt); @@ -1810,13 +1799,6 @@ static int do_execveat_common(int fd, struct filename *filename, if (retval < 0) goto out; - if (capable(CAP_SYS_ADMIN)) { - if (unlikely(!strcmp(filename->name, ZYGOTE32_BIN))) - atomic_set(&zygote32_pid, current->pid); - else if (unlikely(!strcmp(filename->name, ZYGOTE64_BIN))) - atomic_set(&zygote64_pid, current->pid); - } - /* execve succeeded */ current->fs->in_exec = 0; current->in_execve = 0; diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h index a1c50c633a77..ef6f37c7ed39 100644 --- a/include/linux/binfmts.h +++ b/include/linux/binfmts.h @@ -139,7 +139,6 @@ extern int prepare_bprm_creds(struct linux_binprm *bprm); extern void install_exec_creds(struct linux_binprm *bprm); extern void set_binfmt(struct linux_binfmt *new); extern ssize_t read_code(struct file *, unsigned long, loff_t, size_t); -extern bool is_zygote_pid(pid_t pid); extern int do_execve(struct filename *, const char __user * const __user *, From ab25cbf8fb092b53b12d07e9b3cb9f8c59d3409a Mon Sep 17 00:00:00 2001 From: Sultan Alsawaf Date: Sun, 3 Mar 2019 14:00:56 -0800 Subject: [PATCH 590/592] kernel: Boost to the max for when zygote forks In order to boost during the period from when a new app is forked to the time that it is added to the top-app cpuset (which is a signal to subsequently boost again), boost for a short amount of time when zygote forks. Not all processes forked from zygote are top apps, hence the decoupled boosting setup. Signed-off-by: Sultan Alsawaf Signed-off-by: celtare21 Signed-off-by: UtsavBalar1231 --- kernel/fork.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/kernel/fork.c b/kernel/fork.c index 17a5cc8e7880..e4e47a9a8be6 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -95,6 +95,7 @@ #include #include #include +#include #include #include @@ -2206,6 +2207,10 @@ long _do_fork(unsigned long clone_flags, int trace = 0; long nr; + /* Boost CPU to the max for 3000 ms when userspace launches an app */ + if (task_is_zygote(current)) + cpu_input_boost_kick_max(3000); + /* * Determine whether and which event to report to ptracer. When * called from kernel_thread or CLONE_UNTRACED is explicitly From 1237497eba2f83fa6e9d2c65214ad3d4e55c81df Mon Sep 17 00:00:00 2001 From: Sultan Alsawaf Date: Fri, 19 Apr 2019 12:44:52 -0700 Subject: [PATCH 591/592] kernel: Boost whenever a zygote-forked process becomes a top app Boost the CPU to the max for 1000 ms whenever the top app changes, which improves app launch speeds and addresses jitter when switching between apps. A check to make sure that the top-app's parent is zygote ensures that a user-facing app is indeed what's added to the top app task group, since app processes are forked from zygote. Signed-off-by: Sultan Alsawaf Signed-off-by: celtare21 Signed-off-by: UtsavBalar1231 --- fs/exec.c | 17 +++++++++++++++++ include/linux/binfmts.h | 1 + kernel/cgroup/cgroup-v1.c | 7 +++++++ 3 files changed, 25 insertions(+) diff --git a/fs/exec.c b/fs/exec.c index 2bd49fbdf38b..3fb5e4bd523e 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -77,6 +77,16 @@ int suid_dumpable = 0; static LIST_HEAD(formats); static DEFINE_RWLOCK(binfmt_lock); +#define ZYGOTE32_BIN "/system/bin/app_process32" +#define ZYGOTE64_BIN "/system/bin/app_process64" +static struct signal_struct *zygote32_sig; +static struct signal_struct *zygote64_sig; + +bool task_is_zygote(struct task_struct *p) +{ + return p->signal == zygote32_sig || p->signal == zygote64_sig; +} + void __register_binfmt(struct linux_binfmt * fmt, int insert) { BUG_ON(!fmt); @@ -1799,6 +1809,13 @@ static int do_execveat_common(int fd, struct filename *filename, if (retval < 0) goto out; + if (is_global_init(current->parent)) { + if (unlikely(!strcmp(filename->name, ZYGOTE32_BIN))) + zygote32_sig = current->signal; + else if (unlikely(!strcmp(filename->name, ZYGOTE64_BIN))) + zygote64_sig = current->signal; + } + /* execve succeeded */ current->fs->in_exec = 0; current->in_execve = 0; diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h index ef6f37c7ed39..4e7a46907b6d 100644 --- a/include/linux/binfmts.h +++ b/include/linux/binfmts.h @@ -139,6 +139,7 @@ extern int prepare_bprm_creds(struct linux_binprm *bprm); extern void install_exec_creds(struct linux_binprm *bprm); extern void set_binfmt(struct linux_binfmt *new); extern ssize_t read_code(struct file *, unsigned long, loff_t, size_t); +extern bool task_is_zygote(struct task_struct *p); extern int do_execve(struct filename *, const char __user * const __user *, diff --git a/kernel/cgroup/cgroup-v1.c b/kernel/cgroup/cgroup-v1.c index 7f53d00f19ae..6a3e34f07b36 100644 --- a/kernel/cgroup/cgroup-v1.c +++ b/kernel/cgroup/cgroup-v1.c @@ -13,6 +13,8 @@ #include #include #include +#include +#include #include @@ -551,6 +553,11 @@ static ssize_t __cgroup1_procs_write(struct kernfs_open_file *of, ret = cgroup_attach_task(cgrp, task, threadgroup); + /* This covers boosting for app launches and app transitions */ + if (!ret && !threadgroup && !strcmp(of->kn->parent->name, "top-app") && + task_is_zygote(task->parent)) + cpu_input_boost_kick_max(1000); + out_finish: cgroup_procs_write_finish(task); out_unlock: From de70e7d21df7869ca788cd0e1e9ee954f258ce76 Mon Sep 17 00:00:00 2001 From: UtsavBalar1231 Date: Mon, 17 Aug 2020 18:57:45 +0530 Subject: [PATCH 592/592] ARM64: configs: raphael: Regenerate and sync Signed-off-by: UtsavBalar1231 --- arch/arm64/configs/raphael_defconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm64/configs/raphael_defconfig b/arch/arm64/configs/raphael_defconfig index 26a65ea2193d..ab290b2f27c9 100644 --- a/arch/arm64/configs/raphael_defconfig +++ b/arch/arm64/configs/raphael_defconfig @@ -3892,7 +3892,6 @@ CONFIG_ION=y # CONFIG_ION_CARVEOUT_HEAP is not set # CONFIG_ION_CHUNK_HEAP is not set # CONFIG_ION_CMA_HEAP is not set -# CONFIG_ION_FORCE_DMA_SYNC is not set # CONFIG_ION_DEFER_FREE_NO_SCHED_IDLE is not set CONFIG_ALLOC_BUFFERS_IN_4K_CHUNKS=y # CONFIG_STAGING_BOARD is not set @@ -4238,6 +4237,7 @@ CONFIG_QCOM_AOP_DDRSS_COMMANDS=y # CONFIG_MSM_BGCOM is not set # CONFIG_MSM_PIL_SSR_BG is not set CONFIG_QCOM_SOC_INFO=y +# CONFIG_RENAME_BLOCK_DEVICE is not set # CONFIG_WCNSS_CORE is not set # CONFIG_SUNXI_SRAM is not set # CONFIG_SOC_TI is not set @@ -5094,6 +5094,7 @@ CONFIG_SECURITY_SELINUX_DEVELOP=y # CONFIG_SECURITY_SELINUX_AVC_STATS is not set CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=0 CONFIG_SECURITY_SELINUX_SIDTAB_HASH_BITS=9 +CONFIG_SECURITY_SELINUX_SID2STR_CACHE_SIZE=256 # CONFIG_SECURITY_SMACK is not set # CONFIG_SECURITY_TOMOYO is not set # CONFIG_SECURITY_APPARMOR is not set