+++ /dev/null
-From 0020c35a0ab004ee65d5cac87a0e77c318bfedd5 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-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 <namjae.jeon@samsung.com>
-
-[ Upstream commit 1e49a94cf707204b66a3fb242f2814712c941f52 ]
-
-This adds the implementation of bitmap operations for exfat.
-
-Signed-off-by: Namjae Jeon <namjae.jeon@samsung.com>
-Signed-off-by: Sungjong Seo <sj1557.seo@samsung.com>
-Reviewed-by: Pali Rohár <pali.rohar@gmail.com>
-Reviewed-by: Christoph Hellwig <hch@lst.de>
-Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-Stable-dep-of: daf60d6cca26 ("exfat: use kvmalloc_array/kvfree instead of kmalloc_array/kfree")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- 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 <linux/blkdev.h>
-+#include <linux/slab.h>
-+#include <linux/buffer_head.h>
-+
-+#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
-
+++ /dev/null
-From 08e0003605d52d1c70788d8ca2a531cd4aff5a3f Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 5 Jul 2023 15:15:15 +0800
-Subject: exfat: use kvmalloc_array/kvfree instead of kmalloc_array/kfree
-
-From: gaoming <gaoming20@hihonor.com>
-
-[ 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 <gaoming20@hihonor.com>
-Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- 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
-
--- /dev/null
+From 2c6c9c049510163090b979ea5f92a68ae8d93c45 Mon Sep 17 00:00:00 2001
+From: Jiaxun Yang <jiaxun.yang@flygoat.com>
+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 <jiaxun.yang@flygoat.com>
+
+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 <jiaxun.yang@flygoat.com>
+Reviewed-by: Serge Semin <fancer.lancer@gmail.com>
+Tested-by: Serge Semin <fancer.lancer@gmail.com>
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Link: https://lore.kernel.org/r/20230424103156.66753-2-jiaxun.yang@flygoat.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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)
Stable-dep-of: 71150ac12558 ("mmc: bcm2835: fix deferred probing")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
- 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) {
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;
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) {
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);
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) {
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) {
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) {
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);
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);
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
-
+++ /dev/null
-From c343ea70c67bf61df8e1046119d24453efc8475c Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Thu, 23 Aug 2018 13:44:18 +0900
-Subject: mmc: uniphier-sd: add UniPhier SD/eMMC controller driver
-
-From: Masahiro Yamada <yamada.masahiro@socionext.com>
-
-[ 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 <yamada.masahiro@socionext.com>
-Acked-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
-Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
-Stable-dep-of: 71150ac12558 ("mmc: bcm2835: fix deferred probing")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- 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 <yamada.masahiro@socionext.com>
-+
-+#include <linux/bitfield.h>
-+#include <linux/bitops.h>
-+#include <linux/clk.h>
-+#include <linux/delay.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/mfd/tmio.h>
-+#include <linux/mmc/host.h>
-+#include <linux/module.h>
-+#include <linux/of.h>
-+#include <linux/of_device.h>
-+#include <linux/pinctrl/consumer.h>
-+#include <linux/platform_device.h>
-+#include <linux/reset.h>
-+
-+#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 <yamada.masahiro@socionext.com>");
-+MODULE_DESCRIPTION("UniPhier SD/eMMC host controller driver");
-+MODULE_LICENSE("GPL v2");
---
-2.40.1
-
--- /dev/null
+From 6613bc2301ba291a1c5a90e1dc24cf3edf223c03 Mon Sep 17 00:00:00 2001
+From: Shradha Todi <shradha.t@samsung.com>
+Date: Wed, 24 Mar 2021 15:46:09 +0530
+Subject: PCI: endpoint: Fix NULL pointer dereference for ->get_features()
+
+From: Shradha Todi <shradha.t@samsung.com>
+
+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 <dash.sriram@gmail.com>
+Signed-off-by: Shradha Todi <shradha.t@samsung.com>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Reviewed-by: Pankaj Dubey <pankaj.dubey@samsung.com>
+Reviewed-by: Kishon Vijay Abraham I <kishon@ti.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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;
+
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
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
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