summaryrefslogtreecommitdiff
path: root/drivers/mmc
diff options
context:
space:
mode:
authorMarek Vasut <marek.vasut@gmail.com>2020-04-04 12:45:05 +0200
committerPeng Fan <peng.fan@nxp.com>2020-04-22 20:41:56 +0800
commit145429aac05b399c3543ebb86799f4ed753328c4 (patch)
tree961a177256e8227f7d71d29a0804c0e2bac3a92a /drivers/mmc
parentd2661d8e9f9e83cb15ab981cb42e84c51bd85c2d (diff)
mmc: Add option to adjust b_max before long read
Add getter function which permits adjusting the maximum number of blocks that could be read in a single sustained read transfer based on the location of the source/target buffer and length, before such transfer starts. This is mainly useful on systems which have various DMA restrictions for different memory locations, e.g. DMA limited to 32bit addresses, and where a bounce buffer is used to work around such restrictions. Since the U-Boot bounce buffer is mallocated, it's size is limited by the malloc area size, and the read transfer to such a buffer must also be limited. However, as not all areas are limited equally, the b_max should be adjusted accordinly as needed to avoid degrading performance unnecessarily. Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com> Cc: Daniel Schwierzeck <daniel.schwierzeck@gmail.com> Cc: Masahiro Yamada <yamada.masahiro@socionext.com> Cc: Peng Fan <peng.fan@nxp.com> Cc: Simon Glass <sjg@chromium.org> Cc: Tom Rini <trini@konsulko.com>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/mmc-uclass.c16
-rw-r--r--drivers/mmc/mmc.c16
2 files changed, 30 insertions, 2 deletions
diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c
index c75892a72c..cb26d841be 100644
--- a/drivers/mmc/mmc-uclass.c
+++ b/drivers/mmc/mmc-uclass.c
@@ -13,6 +13,22 @@
#include <linux/compat.h>
#include "mmc_private.h"
+int dm_mmc_get_b_max(struct udevice *dev, void *dst, lbaint_t blkcnt)
+{
+ struct dm_mmc_ops *ops = mmc_get_ops(dev);
+ struct mmc *mmc = mmc_get_mmc_dev(dev);
+
+ if (ops->get_b_max)
+ return ops->get_b_max(dev, dst, blkcnt);
+ else
+ return mmc->cfg->b_max;
+}
+
+int mmc_get_b_max(struct mmc *mmc, void *dst, lbaint_t blkcnt)
+{
+ return dm_mmc_get_b_max(mmc->dev, dst, blkcnt);
+}
+
int dm_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
struct mmc_data *data)
{
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index fc3123c3c3..523c055967 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -409,6 +409,16 @@ static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start,
return blkcnt;
}
+#if !CONFIG_IS_ENABLED(DM_MMC)
+static int mmc_get_b_max(struct mmc *mmc, void *dst, lbaint_t blkcnt)
+{
+ if (mmc->cfg->ops->get_b_max)
+ return mmc->cfg->ops->get_b_max(mmc, dst, blkcnt);
+ else
+ return mmc->cfg->b_max;
+}
+#endif
+
#if CONFIG_IS_ENABLED(BLK)
ulong mmc_bread(struct udevice *dev, lbaint_t start, lbaint_t blkcnt, void *dst)
#else
@@ -422,6 +432,7 @@ ulong mmc_bread(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt,
int dev_num = block_dev->devnum;
int err;
lbaint_t cur, blocks_todo = blkcnt;
+ uint b_max;
if (blkcnt == 0)
return 0;
@@ -451,9 +462,10 @@ ulong mmc_bread(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt,
return 0;
}
+ b_max = mmc_get_b_max(mmc, dst, blkcnt);
+
do {
- cur = (blocks_todo > mmc->cfg->b_max) ?
- mmc->cfg->b_max : blocks_todo;
+ cur = (blocks_todo > b_max) ? b_max : blocks_todo;
if (mmc_read_blocks(mmc, dst, start, cur) != cur) {
pr_debug("%s: Failed to read blocks\n", __func__);
return 0;