From 1806c60df00b3b4b040bf63a5ed59e8e1b20d598 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 27 Aug 2023 12:29:10 +0200 Subject: [PATCH] 4.19-stable patches added patches: irqchip-mips-gic-don-t-touch-vl_map-if-a-local-interrupt-is-not-routable.patch pci-endpoint-fix-null-pointer-dereference-for-get_features.patch --- queue-4.19/exfat-add-bitmap-operations.patch | 315 ------- ...oc_array-kvfree-instead-of-kmalloc_a.patch | 86 -- ...if-a-local-interrupt-is-not-routable.patch | 45 + ...dev_err-usage-after-platform_get_irq.patch | 76 +- ...add-uniphier-sd-emmc-controller-driv.patch | 812 ------------------ ...pointer-dereference-for-get_features.patch | 72 ++ queue-4.19/series | 5 +- 7 files changed, 138 insertions(+), 1273 deletions(-) delete mode 100644 queue-4.19/exfat-add-bitmap-operations.patch delete mode 100644 queue-4.19/exfat-use-kvmalloc_array-kvfree-instead-of-kmalloc_a.patch create mode 100644 queue-4.19/irqchip-mips-gic-don-t-touch-vl_map-if-a-local-interrupt-is-not-routable.patch delete mode 100644 queue-4.19/mmc-uniphier-sd-add-uniphier-sd-emmc-controller-driv.patch create mode 100644 queue-4.19/pci-endpoint-fix-null-pointer-dereference-for-get_features.patch diff --git a/queue-4.19/exfat-add-bitmap-operations.patch b/queue-4.19/exfat-add-bitmap-operations.patch deleted file mode 100644 index 9a36bc16bca..00000000000 --- a/queue-4.19/exfat-add-bitmap-operations.patch +++ /dev/null @@ -1,315 +0,0 @@ -From 0020c35a0ab004ee65d5cac87a0e77c318bfedd5 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Mon, 2 Mar 2020 15:21:38 +0900 -Subject: exfat: add bitmap operations -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -From: Namjae Jeon - -[ Upstream commit 1e49a94cf707204b66a3fb242f2814712c941f52 ] - -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 -Stable-dep-of: daf60d6cca26 ("exfat: use kvmalloc_array/kvfree instead of kmalloc_array/kfree") -Signed-off-by: Sasha Levin ---- - fs/exfat/balloc.c | 280 ++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 280 insertions(+) - create mode 100644 fs/exfat/balloc.c - -diff --git a/fs/exfat/balloc.c b/fs/exfat/balloc.c -new file mode 100644 -index 0000000000000..6a04cc02565a1 ---- /dev/null -+++ b/fs/exfat/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; -+} --- -2.40.1 - diff --git a/queue-4.19/exfat-use-kvmalloc_array-kvfree-instead-of-kmalloc_a.patch b/queue-4.19/exfat-use-kvmalloc_array-kvfree-instead-of-kmalloc_a.patch deleted file mode 100644 index b1564ffaec4..00000000000 --- a/queue-4.19/exfat-use-kvmalloc_array-kvfree-instead-of-kmalloc_a.patch +++ /dev/null @@ -1,86 +0,0 @@ -From 08e0003605d52d1c70788d8ca2a531cd4aff5a3f Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Wed, 5 Jul 2023 15:15:15 +0800 -Subject: exfat: use kvmalloc_array/kvfree instead of kmalloc_array/kfree - -From: gaoming - -[ Upstream commit daf60d6cca26e50d65dac374db92e58de745ad26 ] - -The call stack shown below is a scenario in the Linux 4.19 kernel. -Allocating memory failed where exfat fs use kmalloc_array due to -system memory fragmentation, while the u-disk was inserted without -recognition. -Devices such as u-disk using the exfat file system are pluggable and -may be insert into the system at any time. -However, long-term running systems cannot guarantee the continuity of -physical memory. Therefore, it's necessary to address this issue. - -Binder:2632_6: page allocation failure: order:4, - mode:0x6040c0(GFP_KERNEL|__GFP_COMP), nodemask=(null) -Call trace: -[242178.097582] dump_backtrace+0x0/0x4 -[242178.097589] dump_stack+0xf4/0x134 -[242178.097598] warn_alloc+0xd8/0x144 -[242178.097603] __alloc_pages_nodemask+0x1364/0x1384 -[242178.097608] kmalloc_order+0x2c/0x510 -[242178.097612] kmalloc_order_trace+0x40/0x16c -[242178.097618] __kmalloc+0x360/0x408 -[242178.097624] load_alloc_bitmap+0x160/0x284 -[242178.097628] exfat_fill_super+0xa3c/0xe7c -[242178.097635] mount_bdev+0x2e8/0x3a0 -[242178.097638] exfat_fs_mount+0x40/0x50 -[242178.097643] mount_fs+0x138/0x2e8 -[242178.097649] vfs_kern_mount+0x90/0x270 -[242178.097655] do_mount+0x798/0x173c -[242178.097659] ksys_mount+0x114/0x1ac -[242178.097665] __arm64_sys_mount+0x24/0x34 -[242178.097671] el0_svc_common+0xb8/0x1b8 -[242178.097676] el0_svc_handler+0x74/0x90 -[242178.097681] el0_svc+0x8/0x340 - -By analyzing the exfat code,we found that continuous physical memory -is not required here,so kvmalloc_array is used can solve this problem. - -Cc: stable@vger.kernel.org -Signed-off-by: gaoming -Signed-off-by: Namjae Jeon -Signed-off-by: Sasha Levin ---- - fs/exfat/balloc.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/fs/exfat/balloc.c b/fs/exfat/balloc.c -index 6a04cc02565a1..322aa78c50fb4 100644 ---- a/fs/exfat/balloc.c -+++ b/fs/exfat/balloc.c -@@ -70,7 +70,7 @@ static int exfat_allocate_bitmap(struct super_block *sb, - } - sbi->map_sectors = ((need_map_size - 1) >> - (sb->s_blocksize_bits)) + 1; -- sbi->vol_amap = kmalloc_array(sbi->map_sectors, -+ sbi->vol_amap = kvmalloc_array(sbi->map_sectors, - sizeof(struct buffer_head *), GFP_KERNEL); - if (!sbi->vol_amap) - return -ENOMEM; -@@ -85,7 +85,7 @@ static int exfat_allocate_bitmap(struct super_block *sb, - while (j < i) - brelse(sbi->vol_amap[j++]); - -- kfree(sbi->vol_amap); -+ kvfree(sbi->vol_amap); - sbi->vol_amap = NULL; - return -EIO; - } -@@ -142,7 +142,7 @@ void exfat_free_bitmap(struct exfat_sb_info *sbi) - for (i = 0; i < sbi->map_sectors; i++) - __brelse(sbi->vol_amap[i]); - -- kfree(sbi->vol_amap); -+ kvfree(sbi->vol_amap); - } - - /* --- -2.40.1 - diff --git a/queue-4.19/irqchip-mips-gic-don-t-touch-vl_map-if-a-local-interrupt-is-not-routable.patch b/queue-4.19/irqchip-mips-gic-don-t-touch-vl_map-if-a-local-interrupt-is-not-routable.patch new file mode 100644 index 00000000000..d348ee4444c --- /dev/null +++ b/queue-4.19/irqchip-mips-gic-don-t-touch-vl_map-if-a-local-interrupt-is-not-routable.patch @@ -0,0 +1,45 @@ +From 2c6c9c049510163090b979ea5f92a68ae8d93c45 Mon Sep 17 00:00:00 2001 +From: Jiaxun Yang +Date: Mon, 24 Apr 2023 11:31:55 +0100 +Subject: irqchip/mips-gic: Don't touch vl_map if a local interrupt is not routable + +From: Jiaxun Yang + +commit 2c6c9c049510163090b979ea5f92a68ae8d93c45 upstream. + +When a GIC local interrupt is not routable, it's vl_map will be used +to control some internal states for core (providing IPTI, IPPCI, IPFDC +input signal for core). Overriding it will interfere core's intetrupt +controller. + +Do not touch vl_map if a local interrupt is not routable, we are not +going to remap it. + +Before dd098a0e0319 (" irqchip/mips-gic: Get rid of the reliance on +irq_cpu_online()"), if a local interrupt is not routable, then it won't +be requested from GIC Local domain, and thus gic_all_vpes_irq_cpu_online +won't be called for that particular interrupt. + +Fixes: dd098a0e0319 (" irqchip/mips-gic: Get rid of the reliance on irq_cpu_online()") +Cc: stable@vger.kernel.org +Signed-off-by: Jiaxun Yang +Reviewed-by: Serge Semin +Tested-by: Serge Semin +Signed-off-by: Marc Zyngier +Link: https://lore.kernel.org/r/20230424103156.66753-2-jiaxun.yang@flygoat.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/irqchip/irq-mips-gic.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/irqchip/irq-mips-gic.c ++++ b/drivers/irqchip/irq-mips-gic.c +@@ -396,6 +396,8 @@ static void gic_all_vpes_irq_cpu_online( + unsigned int intr = local_intrs[i]; + struct gic_all_vpes_chip_data *cd; + ++ if (!gic_local_irq_is_routable(intr)) ++ continue; + cd = &gic_all_vpes_chip_data[intr]; + write_gic_vl_map(mips_gic_vx_map_reg(intr), cd->map); + if (cd->mask) diff --git a/queue-4.19/mmc-remove-dev_err-usage-after-platform_get_irq.patch b/queue-4.19/mmc-remove-dev_err-usage-after-platform_get_irq.patch index f271b31870c..2a6b708b5e7 100644 --- a/queue-4.19/mmc-remove-dev_err-usage-after-platform_get_irq.patch +++ b/queue-4.19/mmc-remove-dev_err-usage-after-platform_get_irq.patch @@ -50,23 +50,20 @@ Signed-off-by: Ulf Hansson Stable-dep-of: 71150ac12558 ("mmc: bcm2835: fix deferred probing") Signed-off-by: Sasha Levin --- - drivers/mmc/host/bcm2835.c | 1 - - drivers/mmc/host/jz4740_mmc.c | 1 - - drivers/mmc/host/meson-gx-mmc.c | 1 - - drivers/mmc/host/mxcmmc.c | 4 +--- - drivers/mmc/host/s3cmci.c | 1 - - drivers/mmc/host/sdhci-msm.c | 2 -- - drivers/mmc/host/sdhci-pltfm.c | 1 - - drivers/mmc/host/sdhci-s3c.c | 4 +--- - drivers/mmc/host/sdhci_f_sdh30.c | 4 +--- - drivers/mmc/host/uniphier-sd.c | 4 +--- - 10 files changed, 4 insertions(+), 19 deletions(-) + drivers/mmc/host/bcm2835.c | 1 - + drivers/mmc/host/jz4740_mmc.c | 1 - + drivers/mmc/host/meson-gx-mmc.c | 1 - + drivers/mmc/host/mxcmmc.c | 4 +--- + drivers/mmc/host/s3cmci.c | 1 - + drivers/mmc/host/sdhci-msm.c | 2 -- + drivers/mmc/host/sdhci-pltfm.c | 1 - + drivers/mmc/host/sdhci-s3c.c | 4 +--- + drivers/mmc/host/sdhci_f_sdh30.c | 4 +--- + 9 files changed, 3 insertions(+), 16 deletions(-) -diff --git a/drivers/mmc/host/bcm2835.c b/drivers/mmc/host/bcm2835.c -index 5301302fb5310..11026474dda47 100644 --- a/drivers/mmc/host/bcm2835.c +++ b/drivers/mmc/host/bcm2835.c -@@ -1418,7 +1418,6 @@ static int bcm2835_probe(struct platform_device *pdev) +@@ -1418,7 +1418,6 @@ static int bcm2835_probe(struct platform host->irq = platform_get_irq(pdev, 0); if (host->irq <= 0) { @@ -74,11 +71,9 @@ index 5301302fb5310..11026474dda47 100644 ret = -EINVAL; goto err; } -diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c -index 864338e308e2b..b8fb518c6db01 100644 --- a/drivers/mmc/host/jz4740_mmc.c +++ b/drivers/mmc/host/jz4740_mmc.c -@@ -1060,7 +1060,6 @@ static int jz4740_mmc_probe(struct platform_device* pdev) +@@ -1060,7 +1060,6 @@ static int jz4740_mmc_probe(struct platf host->irq = platform_get_irq(pdev, 0); if (host->irq < 0) { ret = host->irq; @@ -86,11 +81,9 @@ index 864338e308e2b..b8fb518c6db01 100644 goto err_free_host; } -diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c -index a3e5be81b4660..28f07d4100433 100644 --- a/drivers/mmc/host/meson-gx-mmc.c +++ b/drivers/mmc/host/meson-gx-mmc.c -@@ -1272,7 +1272,6 @@ static int meson_mmc_probe(struct platform_device *pdev) +@@ -1272,7 +1272,6 @@ static int meson_mmc_probe(struct platfo host->irq = platform_get_irq(pdev, 0); if (host->irq <= 0) { @@ -98,11 +91,9 @@ index a3e5be81b4660..28f07d4100433 100644 ret = -EINVAL; goto free_host; } -diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c -index 6215feb976e32..a0e8ac9124455 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c -@@ -1017,10 +1017,8 @@ static int mxcmci_probe(struct platform_device *pdev) +@@ -1017,10 +1017,8 @@ static int mxcmci_probe(struct platform_ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); irq = platform_get_irq(pdev, 0); @@ -114,11 +105,9 @@ index 6215feb976e32..a0e8ac9124455 100644 mmc = mmc_alloc_host(sizeof(*host), &pdev->dev); if (!mmc) -diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c -index f774936043129..ca2239ea6d96d 100644 --- a/drivers/mmc/host/s3cmci.c +++ b/drivers/mmc/host/s3cmci.c -@@ -1661,7 +1661,6 @@ static int s3cmci_probe(struct platform_device *pdev) +@@ -1661,7 +1661,6 @@ static int s3cmci_probe(struct platform_ host->irq = platform_get_irq(pdev, 0); if (host->irq <= 0) { @@ -126,11 +115,9 @@ index f774936043129..ca2239ea6d96d 100644 ret = -EINVAL; goto probe_iounmap; } -diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c -index 4970cd40813b2..feede31fab47d 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c -@@ -1914,8 +1914,6 @@ static int sdhci_msm_probe(struct platform_device *pdev) +@@ -1914,8 +1914,6 @@ static int sdhci_msm_probe(struct platfo /* Setup IRQ for handling power/voltage tasks with PMIC */ msm_host->pwr_irq = platform_get_irq_byname(pdev, "pwr_irq"); if (msm_host->pwr_irq < 0) { @@ -139,11 +126,9 @@ index 4970cd40813b2..feede31fab47d 100644 ret = msm_host->pwr_irq; goto clk_disable; } -diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c -index 02bea6159d792..ac380c54bd170 100644 --- a/drivers/mmc/host/sdhci-pltfm.c +++ b/drivers/mmc/host/sdhci-pltfm.c -@@ -131,7 +131,6 @@ struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev, +@@ -131,7 +131,6 @@ struct sdhci_host *sdhci_pltfm_init(stru irq = platform_get_irq(pdev, 0); if (irq < 0) { @@ -151,11 +136,9 @@ index 02bea6159d792..ac380c54bd170 100644 ret = irq; goto err; } -diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c -index 9ef89d00970e1..936d88a33a675 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c -@@ -493,10 +493,8 @@ static int sdhci_s3c_probe(struct platform_device *pdev) +@@ -493,10 +493,8 @@ static int sdhci_s3c_probe(struct platfo } irq = platform_get_irq(pdev, 0); @@ -167,11 +150,9 @@ index 9ef89d00970e1..936d88a33a675 100644 host = sdhci_alloc_host(dev, sizeof(struct sdhci_s3c)); if (IS_ERR(host)) { -diff --git a/drivers/mmc/host/sdhci_f_sdh30.c b/drivers/mmc/host/sdhci_f_sdh30.c -index ca9e05440da1d..ee8160d6015ea 100644 --- a/drivers/mmc/host/sdhci_f_sdh30.c +++ b/drivers/mmc/host/sdhci_f_sdh30.c -@@ -122,10 +122,8 @@ static int sdhci_f_sdh30_probe(struct platform_device *pdev) +@@ -122,10 +122,8 @@ static int sdhci_f_sdh30_probe(struct pl u32 reg = 0; irq = platform_get_irq(pdev, 0); @@ -183,22 +164,3 @@ index ca9e05440da1d..ee8160d6015ea 100644 host = sdhci_alloc_host(dev, sizeof(struct f_sdhost_priv)); if (IS_ERR(host)) -diff --git a/drivers/mmc/host/uniphier-sd.c b/drivers/mmc/host/uniphier-sd.c -index 10e7b30c792a2..2e57bbb0883f8 100644 ---- a/drivers/mmc/host/uniphier-sd.c -+++ b/drivers/mmc/host/uniphier-sd.c -@@ -552,10 +552,8 @@ static int uniphier_sd_probe(struct platform_device *pdev) - int irq, ret; - - irq = platform_get_irq(pdev, 0); -- if (irq < 0) { -- dev_err(dev, "failed to get IRQ number"); -+ if (irq < 0) - return irq; -- } - - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (!priv) --- -2.40.1 - diff --git a/queue-4.19/mmc-uniphier-sd-add-uniphier-sd-emmc-controller-driv.patch b/queue-4.19/mmc-uniphier-sd-add-uniphier-sd-emmc-controller-driv.patch deleted file mode 100644 index 3d9db650935..00000000000 --- a/queue-4.19/mmc-uniphier-sd-add-uniphier-sd-emmc-controller-driv.patch +++ /dev/null @@ -1,812 +0,0 @@ -From c343ea70c67bf61df8e1046119d24453efc8475c Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Thu, 23 Aug 2018 13:44:18 +0900 -Subject: mmc: uniphier-sd: add UniPhier SD/eMMC controller driver - -From: Masahiro Yamada - -[ Upstream commit 3fd784f745dd1747863775a99ec749619ee6759c ] - -Here is another TMIO MMC variant found in Socionext UniPhier SoCs. - -As commit b6147490e6aa ("mmc: tmio: split core functionality, DMA and -MFD glue") said, these MMC controllers use the IP from Panasonic. - -However, the MMC controller in the TMIO (Toshiba Mobile IO) MFD chip -was the first upstreamed user of this IP. The common driver code -for this IP is now called 'tmio-mmc-core' in Linux although it is a -historical misnomer. - -Anyway, this driver select's MMC_TMIO_CORE to borrow the common code -from tmio-mmc-core.c - -Older UniPhier SoCs (LD4, Pro4, sLD8) support the external DMA engine -like renesas_sdhi_sys_dmac.c. The difference is UniPhier SoCs use a -single DMA channel whereas Renesas chips request separate channels for -RX and TX. - -Newer UniPhier SoCs (Pro5 and later) support the internal DMA engine -like renesas_sdhi_internal_dmac.c The register map is almost the same, -so I guess Renesas and Socionext use the same internal DMA hardware. -The main difference is, the register offsets are doubled for Renesas. - - Renesas Socionext - SDHI UniPhier - DM_CM_DTRAN_MODE 0x820 0x410 - DM_CM_DTRAN_CTRL 0x828 0x414 - DM_CM_RST 0x830 0x418 - DM_CM_INFO1 0x840 0x420 - DM_CM_INFO1_MASK 0x848 0x424 - DM_CM_INFO2 0x850 0x428 - DM_CM_INFO2_MASK 0x858 0x42c - DM_DTRAN_ADDR 0x880 0x440 - DM_DTRAN_ADDREX --- 0x444 - -This comes from the difference of host->bus_shift; 2 for Renesas SoCs, -and 1 for UniPhier SoCs. Also, the datasheet for UniPhier SoCs defines -DM_DTRAN_ADDR and DM_DTRAN_ADDREX as two separate registers. - -It could be possible to factor out the DMA common code by introducing -some hooks to cope with platform quirks, but this patch does not touch -that for now. - -Signed-off-by: Masahiro Yamada -Acked-by: Wolfram Sang -Signed-off-by: Ulf Hansson -Stable-dep-of: 71150ac12558 ("mmc: bcm2835: fix deferred probing") -Signed-off-by: Sasha Levin ---- - MAINTAINERS | 1 + - drivers/mmc/host/Kconfig | 10 + - drivers/mmc/host/Makefile | 1 + - drivers/mmc/host/uniphier-sd.c | 693 +++++++++++++++++++++++++++++++++ - 4 files changed, 705 insertions(+) - create mode 100644 drivers/mmc/host/uniphier-sd.c - -diff --git a/MAINTAINERS b/MAINTAINERS -index 59003315a9597..1827d859491b5 100644 ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -2195,6 +2195,7 @@ F: drivers/clk/uniphier/ - F: drivers/gpio/gpio-uniphier.c - F: drivers/i2c/busses/i2c-uniphier* - F: drivers/irqchip/irq-uniphier-aidet.c -+F: drivers/mmc/host/uniphier-sd.c - F: drivers/pinctrl/uniphier/ - F: drivers/reset/reset-uniphier.c - F: drivers/tty/serial/8250/8250_uniphier.c -diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig -index 2c11944686cf9..f45dd8223526f 100644 ---- a/drivers/mmc/host/Kconfig -+++ b/drivers/mmc/host/Kconfig -@@ -630,6 +630,16 @@ config MMC_SDHI_INTERNAL_DMAC - using on-chip bus mastering. This supports the controllers - found in arm64 based SoCs. - -+config MMC_UNIPHIER -+ tristate "UniPhier SD/eMMC Host Controller support" -+ depends on ARCH_UNIPHIER || COMPILE_TEST -+ depends on OF -+ select MMC_TMIO_CORE -+ help -+ This provides support for the SD/eMMC controller found in -+ UniPhier SoCs. The eMMC variant of this controller is used -+ only for 32-bit SoCs. -+ - config MMC_CB710 - tristate "ENE CB710 MMC/SD Interface support" - depends on PCI -diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile -index ce8398e6f2c0e..a835d1a0546d2 100644 ---- a/drivers/mmc/host/Makefile -+++ b/drivers/mmc/host/Makefile -@@ -42,6 +42,7 @@ obj-$(CONFIG_MMC_TMIO_CORE) += tmio_mmc_core.o - obj-$(CONFIG_MMC_SDHI) += renesas_sdhi_core.o - obj-$(CONFIG_MMC_SDHI_SYS_DMAC) += renesas_sdhi_sys_dmac.o - obj-$(CONFIG_MMC_SDHI_INTERNAL_DMAC) += renesas_sdhi_internal_dmac.o -+obj-$(CONFIG_MMC_UNIPHIER) += uniphier-sd.o - obj-$(CONFIG_MMC_CB710) += cb710-mmc.o - obj-$(CONFIG_MMC_VIA_SDMMC) += via-sdmmc.o - octeon-mmc-objs := cavium.o cavium-octeon.o -diff --git a/drivers/mmc/host/uniphier-sd.c b/drivers/mmc/host/uniphier-sd.c -new file mode 100644 -index 0000000000000..10e7b30c792a2 ---- /dev/null -+++ b/drivers/mmc/host/uniphier-sd.c -@@ -0,0 +1,693 @@ -+// SPDX-License-Identifier: GPL-2.0 -+// -+// Copyright (C) 2017-2018 Socionext Inc. -+// Author: Masahiro Yamada -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "tmio_mmc.h" -+ -+#define UNIPHIER_SD_CLK_CTL_DIV1024 BIT(16) -+#define UNIPHIER_SD_CLK_CTL_DIV1 BIT(10) -+#define UNIPHIER_SD_CLKCTL_OFFEN BIT(9) // auto SDCLK stop -+#define UNIPHIER_SD_CC_EXT_MODE 0x1b0 -+#define UNIPHIER_SD_CC_EXT_MODE_DMA BIT(1) -+#define UNIPHIER_SD_HOST_MODE 0x1c8 -+#define UNIPHIER_SD_VOLT 0x1e4 -+#define UNIPHIER_SD_VOLT_MASK GENMASK(1, 0) -+#define UNIPHIER_SD_VOLT_OFF 0 -+#define UNIPHIER_SD_VOLT_330 1 // 3.3V signal -+#define UNIPHIER_SD_VOLT_180 2 // 1.8V signal -+#define UNIPHIER_SD_DMA_MODE 0x410 -+#define UNIPHIER_SD_DMA_MODE_DIR_MASK GENMASK(17, 16) -+#define UNIPHIER_SD_DMA_MODE_DIR_TO_DEV 0 -+#define UNIPHIER_SD_DMA_MODE_DIR_FROM_DEV 1 -+#define UNIPHIER_SD_DMA_MODE_WIDTH_MASK GENMASK(5, 4) -+#define UNIPHIER_SD_DMA_MODE_WIDTH_8 0 -+#define UNIPHIER_SD_DMA_MODE_WIDTH_16 1 -+#define UNIPHIER_SD_DMA_MODE_WIDTH_32 2 -+#define UNIPHIER_SD_DMA_MODE_WIDTH_64 3 -+#define UNIPHIER_SD_DMA_MODE_ADDR_INC BIT(0) // 1: inc, 0: fixed -+#define UNIPHIER_SD_DMA_CTL 0x414 -+#define UNIPHIER_SD_DMA_CTL_START BIT(0) // start DMA (auto cleared) -+#define UNIPHIER_SD_DMA_RST 0x418 -+#define UNIPHIER_SD_DMA_RST_CH1 BIT(9) -+#define UNIPHIER_SD_DMA_RST_CH0 BIT(8) -+#define UNIPHIER_SD_DMA_ADDR_L 0x440 -+#define UNIPHIER_SD_DMA_ADDR_H 0x444 -+ -+/* -+ * IP is extended to support various features: built-in DMA engine, -+ * 1/1024 divisor, etc. -+ */ -+#define UNIPHIER_SD_CAP_EXTENDED_IP BIT(0) -+/* RX channel of the built-in DMA controller is broken (Pro5) */ -+#define UNIPHIER_SD_CAP_BROKEN_DMA_RX BIT(1) -+ -+struct uniphier_sd_priv { -+ struct tmio_mmc_data tmio_data; -+ struct pinctrl *pinctrl; -+ struct pinctrl_state *pinstate_default; -+ struct pinctrl_state *pinstate_uhs; -+ struct clk *clk; -+ struct reset_control *rst; -+ struct reset_control *rst_br; -+ struct reset_control *rst_hw; -+ struct dma_chan *chan; -+ enum dma_data_direction dma_dir; -+ unsigned long clk_rate; -+ unsigned long caps; -+}; -+ -+static void *uniphier_sd_priv(struct tmio_mmc_host *host) -+{ -+ return container_of(host->pdata, struct uniphier_sd_priv, tmio_data); -+} -+ -+static void uniphier_sd_dma_endisable(struct tmio_mmc_host *host, int enable) -+{ -+ sd_ctrl_write16(host, CTL_DMA_ENABLE, DMA_ENABLE_DMASDRW); -+} -+ -+/* external DMA engine */ -+static void uniphier_sd_external_dma_issue(unsigned long arg) -+{ -+ struct tmio_mmc_host *host = (void *)arg; -+ struct uniphier_sd_priv *priv = uniphier_sd_priv(host); -+ -+ uniphier_sd_dma_endisable(host, 1); -+ dma_async_issue_pending(priv->chan); -+} -+ -+static void uniphier_sd_external_dma_callback(void *param, -+ const struct dmaengine_result *result) -+{ -+ struct tmio_mmc_host *host = param; -+ struct uniphier_sd_priv *priv = uniphier_sd_priv(host); -+ unsigned long flags; -+ -+ dma_unmap_sg(mmc_dev(host->mmc), host->sg_ptr, host->sg_len, -+ priv->dma_dir); -+ -+ spin_lock_irqsave(&host->lock, flags); -+ -+ if (result->result == DMA_TRANS_NOERROR) { -+ /* -+ * When the external DMA engine is enabled, strangely enough, -+ * the DATAEND flag can be asserted even if the DMA engine has -+ * not been kicked yet. Enable the TMIO_STAT_DATAEND irq only -+ * after we make sure the DMA engine finishes the transfer, -+ * hence, in this callback. -+ */ -+ tmio_mmc_enable_mmc_irqs(host, TMIO_STAT_DATAEND); -+ } else { -+ host->data->error = -ETIMEDOUT; -+ tmio_mmc_do_data_irq(host); -+ } -+ -+ spin_unlock_irqrestore(&host->lock, flags); -+} -+ -+static void uniphier_sd_external_dma_start(struct tmio_mmc_host *host, -+ struct mmc_data *data) -+{ -+ struct uniphier_sd_priv *priv = uniphier_sd_priv(host); -+ enum dma_transfer_direction dma_tx_dir; -+ struct dma_async_tx_descriptor *desc; -+ dma_cookie_t cookie; -+ int sg_len; -+ -+ if (!priv->chan) -+ goto force_pio; -+ -+ if (data->flags & MMC_DATA_READ) { -+ priv->dma_dir = DMA_FROM_DEVICE; -+ dma_tx_dir = DMA_DEV_TO_MEM; -+ } else { -+ priv->dma_dir = DMA_TO_DEVICE; -+ dma_tx_dir = DMA_MEM_TO_DEV; -+ } -+ -+ sg_len = dma_map_sg(mmc_dev(host->mmc), host->sg_ptr, host->sg_len, -+ priv->dma_dir); -+ if (sg_len == 0) -+ goto force_pio; -+ -+ desc = dmaengine_prep_slave_sg(priv->chan, host->sg_ptr, sg_len, -+ dma_tx_dir, DMA_CTRL_ACK); -+ if (!desc) -+ goto unmap_sg; -+ -+ desc->callback_result = uniphier_sd_external_dma_callback; -+ desc->callback_param = host; -+ -+ cookie = dmaengine_submit(desc); -+ if (cookie < 0) -+ goto unmap_sg; -+ -+ return; -+ -+unmap_sg: -+ dma_unmap_sg(mmc_dev(host->mmc), host->sg_ptr, host->sg_len, -+ priv->dma_dir); -+force_pio: -+ host->force_pio = true; -+ uniphier_sd_dma_endisable(host, 0); -+} -+ -+static void uniphier_sd_external_dma_enable(struct tmio_mmc_host *host, -+ bool enable) -+{ -+} -+ -+static void uniphier_sd_external_dma_request(struct tmio_mmc_host *host, -+ struct tmio_mmc_data *pdata) -+{ -+ struct uniphier_sd_priv *priv = uniphier_sd_priv(host); -+ struct dma_chan *chan; -+ -+ chan = dma_request_chan(mmc_dev(host->mmc), "rx-tx"); -+ if (IS_ERR(chan)) { -+ dev_warn(mmc_dev(host->mmc), -+ "failed to request DMA channel. falling back to PIO\n"); -+ return; /* just use PIO even for -EPROBE_DEFER */ -+ } -+ -+ /* this driver uses a single channel for both RX an TX */ -+ priv->chan = chan; -+ host->chan_rx = chan; -+ host->chan_tx = chan; -+ -+ tasklet_init(&host->dma_issue, uniphier_sd_external_dma_issue, -+ (unsigned long)host); -+} -+ -+static void uniphier_sd_external_dma_release(struct tmio_mmc_host *host) -+{ -+ struct uniphier_sd_priv *priv = uniphier_sd_priv(host); -+ -+ if (priv->chan) -+ dma_release_channel(priv->chan); -+} -+ -+static void uniphier_sd_external_dma_abort(struct tmio_mmc_host *host) -+{ -+ struct uniphier_sd_priv *priv = uniphier_sd_priv(host); -+ -+ uniphier_sd_dma_endisable(host, 0); -+ -+ if (priv->chan) -+ dmaengine_terminate_sync(priv->chan); -+} -+ -+static void uniphier_sd_external_dma_dataend(struct tmio_mmc_host *host) -+{ -+ uniphier_sd_dma_endisable(host, 0); -+ -+ tmio_mmc_do_data_irq(host); -+} -+ -+static const struct tmio_mmc_dma_ops uniphier_sd_external_dma_ops = { -+ .start = uniphier_sd_external_dma_start, -+ .enable = uniphier_sd_external_dma_enable, -+ .request = uniphier_sd_external_dma_request, -+ .release = uniphier_sd_external_dma_release, -+ .abort = uniphier_sd_external_dma_abort, -+ .dataend = uniphier_sd_external_dma_dataend, -+}; -+ -+static void uniphier_sd_internal_dma_issue(unsigned long arg) -+{ -+ struct tmio_mmc_host *host = (void *)arg; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&host->lock, flags); -+ tmio_mmc_enable_mmc_irqs(host, TMIO_STAT_DATAEND); -+ spin_unlock_irqrestore(&host->lock, flags); -+ -+ uniphier_sd_dma_endisable(host, 1); -+ writel(UNIPHIER_SD_DMA_CTL_START, host->ctl + UNIPHIER_SD_DMA_CTL); -+} -+ -+static void uniphier_sd_internal_dma_start(struct tmio_mmc_host *host, -+ struct mmc_data *data) -+{ -+ struct uniphier_sd_priv *priv = uniphier_sd_priv(host); -+ struct scatterlist *sg = host->sg_ptr; -+ dma_addr_t dma_addr; -+ unsigned int dma_mode_dir; -+ u32 dma_mode; -+ int sg_len; -+ -+ if (WARN_ON(host->sg_len != 1)) -+ goto force_pio; -+ -+ if (!IS_ALIGNED(sg->offset, 8)) -+ goto force_pio; -+ -+ if (data->flags & MMC_DATA_READ) { -+ priv->dma_dir = DMA_FROM_DEVICE; -+ dma_mode_dir = UNIPHIER_SD_DMA_MODE_DIR_FROM_DEV; -+ } else { -+ priv->dma_dir = DMA_TO_DEVICE; -+ dma_mode_dir = UNIPHIER_SD_DMA_MODE_DIR_TO_DEV; -+ } -+ -+ sg_len = dma_map_sg(mmc_dev(host->mmc), sg, 1, priv->dma_dir); -+ if (sg_len == 0) -+ goto force_pio; -+ -+ dma_mode = FIELD_PREP(UNIPHIER_SD_DMA_MODE_DIR_MASK, dma_mode_dir); -+ dma_mode |= FIELD_PREP(UNIPHIER_SD_DMA_MODE_WIDTH_MASK, -+ UNIPHIER_SD_DMA_MODE_WIDTH_64); -+ dma_mode |= UNIPHIER_SD_DMA_MODE_ADDR_INC; -+ -+ writel(dma_mode, host->ctl + UNIPHIER_SD_DMA_MODE); -+ -+ dma_addr = sg_dma_address(data->sg); -+ writel(lower_32_bits(dma_addr), host->ctl + UNIPHIER_SD_DMA_ADDR_L); -+ writel(upper_32_bits(dma_addr), host->ctl + UNIPHIER_SD_DMA_ADDR_H); -+ -+ return; -+force_pio: -+ host->force_pio = true; -+ uniphier_sd_dma_endisable(host, 0); -+} -+ -+static void uniphier_sd_internal_dma_enable(struct tmio_mmc_host *host, -+ bool enable) -+{ -+} -+ -+static void uniphier_sd_internal_dma_request(struct tmio_mmc_host *host, -+ struct tmio_mmc_data *pdata) -+{ -+ struct uniphier_sd_priv *priv = uniphier_sd_priv(host); -+ -+ /* -+ * Due to a hardware bug, Pro5 cannot use DMA for RX. -+ * We can still use DMA for TX, but PIO for RX. -+ */ -+ if (!(priv->caps & UNIPHIER_SD_CAP_BROKEN_DMA_RX)) -+ host->chan_rx = (void *)0xdeadbeaf; -+ -+ host->chan_tx = (void *)0xdeadbeaf; -+ -+ tasklet_init(&host->dma_issue, uniphier_sd_internal_dma_issue, -+ (unsigned long)host); -+} -+ -+static void uniphier_sd_internal_dma_release(struct tmio_mmc_host *host) -+{ -+ /* Each value is set to zero to assume "disabling" each DMA */ -+ host->chan_rx = NULL; -+ host->chan_tx = NULL; -+} -+ -+static void uniphier_sd_internal_dma_abort(struct tmio_mmc_host *host) -+{ -+ u32 tmp; -+ -+ uniphier_sd_dma_endisable(host, 0); -+ -+ tmp = readl(host->ctl + UNIPHIER_SD_DMA_RST); -+ tmp &= ~(UNIPHIER_SD_DMA_RST_CH1 | UNIPHIER_SD_DMA_RST_CH0); -+ writel(tmp, host->ctl + UNIPHIER_SD_DMA_RST); -+ -+ tmp |= UNIPHIER_SD_DMA_RST_CH1 | UNIPHIER_SD_DMA_RST_CH0; -+ writel(tmp, host->ctl + UNIPHIER_SD_DMA_RST); -+} -+ -+static void uniphier_sd_internal_dma_dataend(struct tmio_mmc_host *host) -+{ -+ struct uniphier_sd_priv *priv = uniphier_sd_priv(host); -+ -+ uniphier_sd_dma_endisable(host, 0); -+ dma_unmap_sg(mmc_dev(host->mmc), host->sg_ptr, 1, priv->dma_dir); -+ -+ tmio_mmc_do_data_irq(host); -+} -+ -+static const struct tmio_mmc_dma_ops uniphier_sd_internal_dma_ops = { -+ .start = uniphier_sd_internal_dma_start, -+ .enable = uniphier_sd_internal_dma_enable, -+ .request = uniphier_sd_internal_dma_request, -+ .release = uniphier_sd_internal_dma_release, -+ .abort = uniphier_sd_internal_dma_abort, -+ .dataend = uniphier_sd_internal_dma_dataend, -+}; -+ -+static int uniphier_sd_clk_enable(struct tmio_mmc_host *host) -+{ -+ struct uniphier_sd_priv *priv = uniphier_sd_priv(host); -+ struct mmc_host *mmc = host->mmc; -+ int ret; -+ -+ ret = clk_prepare_enable(priv->clk); -+ if (ret) -+ return ret; -+ -+ ret = clk_set_rate(priv->clk, ULONG_MAX); -+ if (ret) -+ goto disable_clk; -+ -+ priv->clk_rate = clk_get_rate(priv->clk); -+ -+ /* If max-frequency property is set, use it. */ -+ if (!mmc->f_max) -+ mmc->f_max = priv->clk_rate; -+ -+ /* -+ * 1/512 is the finest divisor in the original IP. Newer versions -+ * also supports 1/1024 divisor. (UniPhier-specific extension) -+ */ -+ if (priv->caps & UNIPHIER_SD_CAP_EXTENDED_IP) -+ mmc->f_min = priv->clk_rate / 1024; -+ else -+ mmc->f_min = priv->clk_rate / 512; -+ -+ ret = reset_control_deassert(priv->rst); -+ if (ret) -+ goto disable_clk; -+ -+ ret = reset_control_deassert(priv->rst_br); -+ if (ret) -+ goto assert_rst; -+ -+ return 0; -+ -+assert_rst: -+ reset_control_assert(priv->rst); -+disable_clk: -+ clk_disable_unprepare(priv->clk); -+ -+ return ret; -+} -+ -+static void uniphier_sd_clk_disable(struct tmio_mmc_host *host) -+{ -+ struct uniphier_sd_priv *priv = uniphier_sd_priv(host); -+ -+ reset_control_assert(priv->rst_br); -+ reset_control_assert(priv->rst); -+ clk_disable_unprepare(priv->clk); -+} -+ -+static void uniphier_sd_hw_reset(struct tmio_mmc_host *host) -+{ -+ struct uniphier_sd_priv *priv = uniphier_sd_priv(host); -+ -+ reset_control_assert(priv->rst_hw); -+ /* For eMMC, minimum is 1us but give it 9us for good measure */ -+ udelay(9); -+ reset_control_deassert(priv->rst_hw); -+ /* For eMMC, minimum is 200us but give it 300us for good measure */ -+ usleep_range(300, 1000); -+} -+ -+static void uniphier_sd_set_clock(struct tmio_mmc_host *host, -+ unsigned int clock) -+{ -+ struct uniphier_sd_priv *priv = uniphier_sd_priv(host); -+ unsigned long divisor; -+ u32 tmp; -+ -+ tmp = readl(host->ctl + (CTL_SD_CARD_CLK_CTL << 1)); -+ -+ /* stop the clock before changing its rate to avoid a glitch signal */ -+ tmp &= ~CLK_CTL_SCLKEN; -+ writel(tmp, host->ctl + (CTL_SD_CARD_CLK_CTL << 1)); -+ -+ if (clock == 0) -+ return; -+ -+ tmp &= ~UNIPHIER_SD_CLK_CTL_DIV1024; -+ tmp &= ~UNIPHIER_SD_CLK_CTL_DIV1; -+ tmp &= ~CLK_CTL_DIV_MASK; -+ -+ divisor = priv->clk_rate / clock; -+ -+ /* -+ * In the original IP, bit[7:0] represents the divisor. -+ * bit7 set: 1/512, ... bit0 set:1/4, all bits clear: 1/2 -+ * -+ * The IP does not define a way to achieve 1/1. For UniPhier variants, -+ * bit10 is used for 1/1. Newer versions of UniPhier variants use -+ * bit16 for 1/1024. -+ */ -+ if (divisor <= 1) -+ tmp |= UNIPHIER_SD_CLK_CTL_DIV1; -+ else if (priv->caps & UNIPHIER_SD_CAP_EXTENDED_IP && divisor > 512) -+ tmp |= UNIPHIER_SD_CLK_CTL_DIV1024; -+ else -+ tmp |= roundup_pow_of_two(divisor) >> 2; -+ -+ writel(tmp, host->ctl + (CTL_SD_CARD_CLK_CTL << 1)); -+ -+ tmp |= CLK_CTL_SCLKEN; -+ writel(tmp, host->ctl + (CTL_SD_CARD_CLK_CTL << 1)); -+} -+ -+static void uniphier_sd_host_init(struct tmio_mmc_host *host) -+{ -+ struct uniphier_sd_priv *priv = uniphier_sd_priv(host); -+ u32 val; -+ -+ /* -+ * Connected to 32bit AXI. -+ * This register holds settings for SoC-specific internal bus -+ * connection. What is worse, the register spec was changed, -+ * breaking the backward compatibility. Write an appropriate -+ * value depending on a flag associated with a compatible string. -+ */ -+ if (priv->caps & UNIPHIER_SD_CAP_EXTENDED_IP) -+ val = 0x00000101; -+ else -+ val = 0x00000000; -+ -+ writel(val, host->ctl + UNIPHIER_SD_HOST_MODE); -+ -+ val = 0; -+ /* -+ * If supported, the controller can automatically -+ * enable/disable the clock line to the card. -+ */ -+ if (priv->caps & UNIPHIER_SD_CAP_EXTENDED_IP) -+ val |= UNIPHIER_SD_CLKCTL_OFFEN; -+ -+ writel(val, host->ctl + (CTL_SD_CARD_CLK_CTL << 1)); -+} -+ -+static int uniphier_sd_start_signal_voltage_switch(struct mmc_host *mmc, -+ struct mmc_ios *ios) -+{ -+ struct tmio_mmc_host *host = mmc_priv(mmc); -+ struct uniphier_sd_priv *priv = uniphier_sd_priv(host); -+ struct pinctrl_state *pinstate; -+ u32 val, tmp; -+ -+ switch (ios->signal_voltage) { -+ case MMC_SIGNAL_VOLTAGE_330: -+ val = UNIPHIER_SD_VOLT_330; -+ pinstate = priv->pinstate_default; -+ break; -+ case MMC_SIGNAL_VOLTAGE_180: -+ val = UNIPHIER_SD_VOLT_180; -+ pinstate = priv->pinstate_uhs; -+ break; -+ default: -+ return -ENOTSUPP; -+ } -+ -+ tmp = readl(host->ctl + UNIPHIER_SD_VOLT); -+ tmp &= ~UNIPHIER_SD_VOLT_MASK; -+ tmp |= FIELD_PREP(UNIPHIER_SD_VOLT_MASK, val); -+ writel(tmp, host->ctl + UNIPHIER_SD_VOLT); -+ -+ pinctrl_select_state(priv->pinctrl, pinstate); -+ -+ return 0; -+} -+ -+static int uniphier_sd_uhs_init(struct tmio_mmc_host *host, -+ struct uniphier_sd_priv *priv) -+{ -+ priv->pinctrl = devm_pinctrl_get(mmc_dev(host->mmc)); -+ if (IS_ERR(priv->pinctrl)) -+ return PTR_ERR(priv->pinctrl); -+ -+ priv->pinstate_default = pinctrl_lookup_state(priv->pinctrl, -+ PINCTRL_STATE_DEFAULT); -+ if (IS_ERR(priv->pinstate_default)) -+ return PTR_ERR(priv->pinstate_default); -+ -+ priv->pinstate_uhs = pinctrl_lookup_state(priv->pinctrl, "uhs"); -+ if (IS_ERR(priv->pinstate_uhs)) -+ return PTR_ERR(priv->pinstate_uhs); -+ -+ host->ops.start_signal_voltage_switch = -+ uniphier_sd_start_signal_voltage_switch; -+ -+ return 0; -+} -+ -+static int uniphier_sd_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct uniphier_sd_priv *priv; -+ struct tmio_mmc_data *tmio_data; -+ struct tmio_mmc_host *host; -+ int irq, ret; -+ -+ irq = platform_get_irq(pdev, 0); -+ if (irq < 0) { -+ dev_err(dev, "failed to get IRQ number"); -+ return irq; -+ } -+ -+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ priv->caps = (unsigned long)of_device_get_match_data(dev); -+ -+ priv->clk = devm_clk_get(dev, NULL); -+ if (IS_ERR(priv->clk)) { -+ dev_err(dev, "failed to get clock\n"); -+ return PTR_ERR(priv->clk); -+ } -+ -+ priv->rst = devm_reset_control_get_shared(dev, "host"); -+ if (IS_ERR(priv->rst)) { -+ dev_err(dev, "failed to get host reset\n"); -+ return PTR_ERR(priv->rst); -+ } -+ -+ /* old version has one more reset */ -+ if (!(priv->caps & UNIPHIER_SD_CAP_EXTENDED_IP)) { -+ priv->rst_br = devm_reset_control_get_shared(dev, "bridge"); -+ if (IS_ERR(priv->rst_br)) { -+ dev_err(dev, "failed to get bridge reset\n"); -+ return PTR_ERR(priv->rst_br); -+ } -+ } -+ -+ tmio_data = &priv->tmio_data; -+ tmio_data->flags |= TMIO_MMC_32BIT_DATA_PORT; -+ -+ host = tmio_mmc_host_alloc(pdev, tmio_data); -+ if (IS_ERR(host)) -+ return PTR_ERR(host); -+ -+ if (host->mmc->caps & MMC_CAP_HW_RESET) { -+ priv->rst_hw = devm_reset_control_get_exclusive(dev, "hw"); -+ if (IS_ERR(priv->rst_hw)) { -+ dev_err(dev, "failed to get hw reset\n"); -+ ret = PTR_ERR(priv->rst_hw); -+ goto free_host; -+ } -+ host->hw_reset = uniphier_sd_hw_reset; -+ } -+ -+ if (host->mmc->caps & MMC_CAP_UHS) { -+ ret = uniphier_sd_uhs_init(host, priv); -+ if (ret) { -+ dev_warn(dev, -+ "failed to setup UHS (error %d). Disabling UHS.", -+ ret); -+ host->mmc->caps &= ~MMC_CAP_UHS; -+ } -+ } -+ -+ ret = devm_request_irq(dev, irq, tmio_mmc_irq, IRQF_SHARED, -+ dev_name(dev), host); -+ if (ret) -+ goto free_host; -+ -+ if (priv->caps & UNIPHIER_SD_CAP_EXTENDED_IP) -+ host->dma_ops = &uniphier_sd_internal_dma_ops; -+ else -+ host->dma_ops = &uniphier_sd_external_dma_ops; -+ -+ host->bus_shift = 1; -+ host->clk_enable = uniphier_sd_clk_enable; -+ host->clk_disable = uniphier_sd_clk_disable; -+ host->set_clock = uniphier_sd_set_clock; -+ -+ ret = uniphier_sd_clk_enable(host); -+ if (ret) -+ goto free_host; -+ -+ uniphier_sd_host_init(host); -+ -+ tmio_data->ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34; -+ if (host->mmc->caps & MMC_CAP_UHS) -+ tmio_data->ocr_mask |= MMC_VDD_165_195; -+ -+ tmio_data->max_segs = 1; -+ tmio_data->max_blk_count = U16_MAX; -+ -+ ret = tmio_mmc_host_probe(host); -+ if (ret) -+ goto free_host; -+ -+ return 0; -+ -+free_host: -+ tmio_mmc_host_free(host); -+ -+ return ret; -+} -+ -+static int uniphier_sd_remove(struct platform_device *pdev) -+{ -+ struct tmio_mmc_host *host = platform_get_drvdata(pdev); -+ -+ tmio_mmc_host_remove(host); -+ uniphier_sd_clk_disable(host); -+ -+ return 0; -+} -+ -+static const struct of_device_id uniphier_sd_match[] = { -+ { -+ .compatible = "socionext,uniphier-sd-v2.91", -+ }, -+ { -+ .compatible = "socionext,uniphier-sd-v3.1", -+ .data = (void *)(UNIPHIER_SD_CAP_EXTENDED_IP | -+ UNIPHIER_SD_CAP_BROKEN_DMA_RX), -+ }, -+ { -+ .compatible = "socionext,uniphier-sd-v3.1.1", -+ .data = (void *)UNIPHIER_SD_CAP_EXTENDED_IP, -+ }, -+ { /* sentinel */ } -+}; -+MODULE_DEVICE_TABLE(of, uniphier_sd_match); -+ -+static struct platform_driver uniphier_sd_driver = { -+ .probe = uniphier_sd_probe, -+ .remove = uniphier_sd_remove, -+ .driver = { -+ .name = "uniphier-sd", -+ .of_match_table = uniphier_sd_match, -+ }, -+}; -+module_platform_driver(uniphier_sd_driver); -+ -+MODULE_AUTHOR("Masahiro Yamada "); -+MODULE_DESCRIPTION("UniPhier SD/eMMC host controller driver"); -+MODULE_LICENSE("GPL v2"); --- -2.40.1 - diff --git a/queue-4.19/pci-endpoint-fix-null-pointer-dereference-for-get_features.patch b/queue-4.19/pci-endpoint-fix-null-pointer-dereference-for-get_features.patch new file mode 100644 index 00000000000..c39c4dc080d --- /dev/null +++ b/queue-4.19/pci-endpoint-fix-null-pointer-dereference-for-get_features.patch @@ -0,0 +1,72 @@ +From 6613bc2301ba291a1c5a90e1dc24cf3edf223c03 Mon Sep 17 00:00:00 2001 +From: Shradha Todi +Date: Wed, 24 Mar 2021 15:46:09 +0530 +Subject: PCI: endpoint: Fix NULL pointer dereference for ->get_features() + +From: Shradha Todi + +commit 6613bc2301ba291a1c5a90e1dc24cf3edf223c03 upstream. + +get_features ops of pci_epc_ops may return NULL, causing NULL pointer +dereference in pci_epf_test_alloc_space function. Let us add a check for +pci_epc_feature pointer in pci_epf_test_bind before we access it to avoid +any such NULL pointer dereference and return -ENOTSUPP in case +pci_epc_feature is not found. + +When the patch is not applied and EPC features is not implemented in the +platform driver, we see the following dump due to kernel NULL pointer +dereference. + +Call trace: + pci_epf_test_bind+0xf4/0x388 + pci_epf_bind+0x3c/0x80 + pci_epc_epf_link+0xa8/0xcc + configfs_symlink+0x1a4/0x48c + vfs_symlink+0x104/0x184 + do_symlinkat+0x80/0xd4 + __arm64_sys_symlinkat+0x1c/0x24 + el0_svc_common.constprop.3+0xb8/0x170 + el0_svc_handler+0x70/0x88 + el0_svc+0x8/0x640 +Code: d2800581 b9403ab9 f9404ebb 8b394f60 (f9400400) +---[ end trace a438e3c5a24f9df0 ]--- + +Link: https://lore.kernel.org/r/20210324101609.79278-1-shradha.t@samsung.com +Fixes: 2c04c5b8eef79 ("PCI: pci-epf-test: Use pci_epc_get_features() to get EPC features") +Signed-off-by: Sriram Dash +Signed-off-by: Shradha Todi +Signed-off-by: Lorenzo Pieralisi +Reviewed-by: Pankaj Dubey +Reviewed-by: Kishon Vijay Abraham I +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/endpoint/functions/pci-epf-test.c | 16 ++++++++++------ + 1 file changed, 10 insertions(+), 6 deletions(-) + +--- a/drivers/pci/endpoint/functions/pci-epf-test.c ++++ b/drivers/pci/endpoint/functions/pci-epf-test.c +@@ -496,14 +496,18 @@ static int pci_epf_test_bind(struct pci_ + return -EINVAL; + + epc_features = pci_epc_get_features(epc, epf->func_no); +- if (epc_features) { +- linkup_notifier = epc_features->linkup_notifier; +- msix_capable = epc_features->msix_capable; +- msi_capable = epc_features->msi_capable; +- test_reg_bar = pci_epc_get_first_free_bar(epc_features); +- pci_epf_configure_bar(epf, epc_features); ++ if (!epc_features) { ++ dev_err(&epf->dev, "epc_features not implemented\n"); ++ return -EOPNOTSUPP; + } + ++ linkup_notifier = epc_features->linkup_notifier; ++ core_init_notifier = epc_features->core_init_notifier; ++ test_reg_bar = pci_epc_get_first_free_bar(epc_features); ++ if (test_reg_bar < 0) ++ return -EINVAL; ++ pci_epf_configure_bar(epf, epc_features); ++ + epf_test->test_reg_bar = test_reg_bar; + epf_test->epc_features = epc_features; + diff --git a/queue-4.19/series b/queue-4.19/series index db3630e39ea..5587ccf9468 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -37,7 +37,6 @@ mmc-meson-gx-remove-useless-lock.patch mmc-meson-gx-remove-redundant-mmc_request_done-call-.patch mmc-tmio-replace-tmio_mmc_clk_stop-calls-with-tmio_m.patch mmc-tmio-move-tmio_mmc_set_clock-to-platform-hook.patch -mmc-uniphier-sd-add-uniphier-sd-emmc-controller-driv.patch mmc-remove-dev_err-usage-after-platform_get_irq.patch mmc-bcm2835-fix-deferred-probing.patch mmc-sunxi-fix-deferred-probing.patch @@ -103,8 +102,6 @@ powerpc-remove-leftover-code-of-old-gcc-version-chec.patch powerpc-fail-build-if-using-recordmcount-with-binuti.patch dm-integrity-increase-recalc_sectors-to-improve-reca.patch dm-integrity-reduce-vmalloc-space-footprint-on-32-bi.patch -exfat-add-bitmap-operations.patch -exfat-use-kvmalloc_array-kvfree-instead-of-kmalloc_a.patch regmap-account-for-register-length-in-smbus-i-o-limi.patch drm-amd-display-do-not-wait-for-mpc-idle-if-tg-is-di.patch drm-amd-display-check-tg-is-non-null-before-checking.patch @@ -132,3 +129,5 @@ mmc-block-fix-in_flight-value-error.patch sched-rt-pick_next_rt_entity-check-list_entry.patch netfilter-nf_queue-fix-socket-leak.patch rtnetlink-reject-negative-ifindexes-in-rtm_newlink.patch +irqchip-mips-gic-don-t-touch-vl_map-if-a-local-interrupt-is-not-routable.patch +pci-endpoint-fix-null-pointer-dereference-for-get_features.patch -- 2.47.3