diff mbox

[RFC] mmc: core: Remove CONFIG_MMC_BLOCK_BOUNCE option.

Message ID cc8694f6-4955-51d3-6342-107cfbb50ed2@cavium.com (mailing list archive)
State New, archived
Headers show

Commit Message

Steven J. Hill May 19, 2017, 7:30 a.m. UTC
Remove MMC bounce buffer config option and associated code. This
is proposed in addition to Linus' changes to remove the config
option. I have tested this on our Octeon hardware platforms.

Signed-off-by: Steven J. Hill <Steven.Hill@cavium.com>
---
 arch/arm/configs/colibri_pxa300_defconfig |   1 -
 arch/arm/configs/davinci_all_defconfig    |   1 -
 arch/arm/configs/lpc32xx_defconfig        |   1 -
 arch/arm/configs/nhk8815_defconfig        |   1 -
 arch/arm/configs/sama5_defconfig          |   1 -
 arch/arm/configs/u300_defconfig           |   1 -
 arch/arm/configs/zeus_defconfig           |   1 -
 arch/blackfin/configs/CM-BF533_defconfig  |   1 -
 arch/blackfin/configs/CM-BF537E_defconfig |   1 -
 arch/mips/configs/cavium_octeon_defconfig |   1 -
 arch/mips/configs/qi_lb60_defconfig       |   1 -
 drivers/mmc/core/Kconfig                  |  18 -----
 drivers/mmc/core/queue.c                  | 109 +++---------------------------
 drivers/mmc/host/davinci_mmc.c            |   6 +-
 include/linux/mmc/card.h                  |   1 -
 15 files changed, 9 insertions(+), 136 deletions(-)

Comments

Linus Walleij May 23, 2017, 9:05 a.m. UTC | #1
On Fri, May 19, 2017 at 9:30 AM, Steven J. Hill <Steven.Hill@cavium.com> wrote:

> Remove MMC bounce buffer config option and associated code. This
> is proposed in addition to Linus' changes to remove the config
> option. I have tested this on our Octeon hardware platforms.
>
> Signed-off-by: Steven J. Hill <Steven.Hill@cavium.com>

This would have to be rebased as Ulf merged my patch making this
a per-host runtime config option. (The Kconfig is gone for example.)

Bounce buffers were added by Pierre Ossman for kernel 2.6.23 in
commit 98ccf14909ba02a41c5925b0b2c92aeeef23d3b9
"mmc: bounce requests for simple hosts"

Quote:

    Some hosts cannot do scatter/gather in hardware. Since not doing sg
    is such a big performance hit, we (optionally) bounce the requests
    to a simple linear buffer that we hand over to the driver.

    Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>

So this runs the risk on reducing performance on simple MMC/SD
controllers. Notice: simple, not old.

We need to know if people are deploying simple controllers still
and if this is something that really affects their performance.

That said: this was put in place because the kernel was sending
SG lists that the host DMA could not manage.

Nowadays we have two mechanisms:

- DMA engine and DMA-API that help out in managing bounce
  buffers when used. This means this only is useful for hardware
  that does autonomous DMA, without any separate DMA engine.

- CMA that can actually allocate a big chunk of memory: I think
  this original code is restricted to a 64KB segment because
  kmalloc() will only guarantee contigous physical memory up to
  64-128KiB or so. Now we could actually allocate a big badass
  CMA buffer if that improves the performance, and that would be
  a per-host setting.

It would be good to hear from people seeing benefits from bounce
buffers about this. What hardware is there that acually sees a
significant improvement with bounce buffers?

Pierre, what host were you developing this for? Maybe I can try
to get the same and test it.

Yours,
Linus Walleij
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Arnd Bergmann May 23, 2017, 10:08 a.m. UTC | #2
On Tue, May 23, 2017 at 11:05 AM, Linus Walleij
<linus.walleij@linaro.org> wrote:
> On Fri, May 19, 2017 at 9:30 AM, Steven J. Hill <Steven.Hill@cavium.com> wrote:
>
>> Remove MMC bounce buffer config option and associated code. This
>> is proposed in addition to Linus' changes to remove the config
>> option. I have tested this on our Octeon hardware platforms.
>>
>> Signed-off-by: Steven J. Hill <Steven.Hill@cavium.com>
>
> This would have to be rebased as Ulf merged my patch making this
> a per-host runtime config option. (The Kconfig is gone for example.)
>
> Bounce buffers were added by Pierre Ossman for kernel 2.6.23 in
> commit 98ccf14909ba02a41c5925b0b2c92aeeef23d3b9
> "mmc: bounce requests for simple hosts"
>
> Quote:
>
>     Some hosts cannot do scatter/gather in hardware. Since not doing sg
>     is such a big performance hit, we (optionally) bounce the requests
>     to a simple linear buffer that we hand over to the driver.
>
>     Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
>
> So this runs the risk on reducing performance on simple MMC/SD
> controllers. Notice: simple, not old.

Right, we definitely need to have something that allows us
to send larger commands to the device for scattered requests.

It wouldn't hurt to reconsider whether the current method is
the most efficient way of doing this, but that doesn't seem to
be a priority to me. If the MMC bounce buffers get in the way
of the blk-mq conversion, we could try to come up with a
different implementation as part of that conversion.

> We need to know if people are deploying simple controllers still
> and if this is something that really affects their performance.
>
> That said: this was put in place because the kernel was sending
> SG lists that the host DMA could not manage.
>
> Nowadays we have two mechanisms:
>
> - DMA engine and DMA-API that help out in managing bounce
>   buffers when used. This means this only is useful for hardware
>   that does autonomous DMA, without any separate DMA engine.

I think the bounce buffers in the DMA-API (swiotlb) should be
kept separate since it has a completely different purpose of
bouncing pages within the dma mask, rather than linearizing
a sglist.

If I read this right, we used to use blk-bounce for highmem
pages and mmc-bounce for lowmem until 2ff1fa679115 ("mmc_block:
bounce buffer highmem support") in 2008, now we don't
use blk-bounce at all if mmc-bounce is in use.

> - CMA that can actually allocate a big chunk of memory: I think
>   this original code is restricted to a 64KB segment because
>   kmalloc() will only guarantee contigous physical memory up to
>   64-128KiB or so. Now we could actually allocate a big badass
>   CMA buffer if that improves the performance, and that would be
>   a per-host setting.
>
> It would be good to hear from people seeing benefits from bounce
> buffers about this. What hardware is there that acually sees a
> significant improvement with bounce buffers?

The mmc-bounce code is active on hosts that have 'max_segs=1'
(the default unless they override it). These one set it to '1'
explicitly:

drivers/mmc/host/au1xmmc.c:     mmc->max_segs = AU1XMMC_DESCRIPTOR_COUNT;
drivers/mmc/host/bfin_sdh.c:    mmc->max_segs = 1; /* only BF51x */
drivers/mmc/host/sdhci.c:               mmc->max_segs = 1; /* with
SDHCI_USE_SDMA */
drivers/mmc/host/ushc.c:        mmc->max_segs      = 1;
drivers/mmc/host/via-sdmmc.c:   mmc->max_segs = 1;

These have max_segs=1 but ask for bounce buffers to be
disabled, which will severely limit their performance:

drivers/mmc/host/cavium.c:              mmc->max_segs = 1; /*
cavium,octeon-6130-mmc */
drivers/mmc/host/pxamci.c: mmc->max_segs = NR_SG;

These ones don't seem to set it at all, defaulting to '1':
drivers/mmc/host/cb710-mmc.c
drivers/mmc/host/moxart-mmc.c
drivers/mmc/host/sdricoh_cs.c
drivers/mmc/host/toshsd.c

       Arnd
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Pierre Ossman May 23, 2017, 6:24 p.m. UTC | #3
On 23/05/17 11:05, Linus Walleij wrote:
> 
> Pierre, what host were you developing this for? Maybe I can try
> to get the same and test it.
> 

I think the work primarily was done with the Texas Instruments SDHCI 
host that HP used in their laptops. Ricoh controllers were also popular, 
but they had some proprietary mode that you had to get them out of.

If I recall correctly, all early SDHCI controllers needed this feature. 
I think scatter/gather was a later addition to the spec.

I take it updates to the SD specification hasn't fixed this performance 
issue?

Regards
diff mbox

Patch

diff --git a/arch/arm/configs/colibri_pxa300_defconfig b/arch/arm/configs/colibri_pxa300_defconfig
index be02fe2..10c940c 100644
--- a/arch/arm/configs/colibri_pxa300_defconfig
+++ b/arch/arm/configs/colibri_pxa300_defconfig
@@ -51,7 +51,6 @@  CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
 CONFIG_USB_MON=y
 CONFIG_USB_STORAGE=y
 CONFIG_MMC=y
-# CONFIG_MMC_BLOCK_BOUNCE is not set
 CONFIG_MMC_PXA=y
 CONFIG_EXT3_FS=y
 CONFIG_INOTIFY=y
diff --git a/arch/arm/configs/davinci_all_defconfig b/arch/arm/configs/davinci_all_defconfig
index 67db829..8a8f086 100644
--- a/arch/arm/configs/davinci_all_defconfig
+++ b/arch/arm/configs/davinci_all_defconfig
@@ -188,7 +188,6 @@  CONFIG_USB_G_SERIAL=m
 CONFIG_USB_G_PRINTER=m
 CONFIG_USB_CDC_COMPOSITE=m
 CONFIG_MMC=y
-# CONFIG_MMC_BLOCK_BOUNCE is not set
 CONFIG_MMC_DAVINCI=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=m
diff --git a/arch/arm/configs/lpc32xx_defconfig b/arch/arm/configs/lpc32xx_defconfig
index 6ba430d..655edfd 100644
--- a/arch/arm/configs/lpc32xx_defconfig
+++ b/arch/arm/configs/lpc32xx_defconfig
@@ -146,7 +146,6 @@  CONFIG_USB_LPC32XX=y
 CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_MMC=y
-# CONFIG_MMC_BLOCK_BOUNCE is not set
 CONFIG_MMC_ARMMMCI=y
 CONFIG_MMC_SPI=y
 CONFIG_NEW_LEDS=y
diff --git a/arch/arm/configs/nhk8815_defconfig b/arch/arm/configs/nhk8815_defconfig
index 7d2ad30..e113d4a 100644
--- a/arch/arm/configs/nhk8815_defconfig
+++ b/arch/arm/configs/nhk8815_defconfig
@@ -95,7 +95,6 @@  CONFIG_GPIO_STMPE=y
 CONFIG_MFD_STMPE=y
 CONFIG_REGULATOR=y
 CONFIG_MMC=y
-# CONFIG_MMC_BLOCK_BOUNCE is not set
 CONFIG_MMC_ARMMMCI=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
diff --git a/arch/arm/configs/sama5_defconfig b/arch/arm/configs/sama5_defconfig
index 777c9e9..c330071 100644
--- a/arch/arm/configs/sama5_defconfig
+++ b/arch/arm/configs/sama5_defconfig
@@ -180,7 +180,6 @@  CONFIG_USB_GADGET=y
 CONFIG_USB_ATMEL_USBA=y
 CONFIG_USB_G_SERIAL=y
 CONFIG_MMC=y
-# CONFIG_MMC_BLOCK_BOUNCE is not set
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_PLTFM=y
 CONFIG_MMC_SDHCI_OF_AT91=y
diff --git a/arch/arm/configs/u300_defconfig b/arch/arm/configs/u300_defconfig
index aaa95ab..d6eb9fe 100644
--- a/arch/arm/configs/u300_defconfig
+++ b/arch/arm/configs/u300_defconfig
@@ -50,7 +50,6 @@  CONFIG_BACKLIGHT_CLASS_DEVICE=y
 # CONFIG_USB_SUPPORT is not set
 CONFIG_MMC=y
 CONFIG_MMC_UNSAFE_RESUME=y
-# CONFIG_MMC_BLOCK_BOUNCE is not set
 CONFIG_MMC_ARMMMCI=y
 CONFIG_RTC_CLASS=y
 # CONFIG_RTC_HCTOSYS is not set
diff --git a/arch/arm/configs/zeus_defconfig b/arch/arm/configs/zeus_defconfig
index cd11da8..a126f7b 100644
--- a/arch/arm/configs/zeus_defconfig
+++ b/arch/arm/configs/zeus_defconfig
@@ -146,7 +146,6 @@  CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_G_PRINTER=m
 CONFIG_MMC=y
-# CONFIG_MMC_BLOCK_BOUNCE is not set
 CONFIG_MMC_PXA=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=m
diff --git a/arch/blackfin/configs/CM-BF533_defconfig b/arch/blackfin/configs/CM-BF533_defconfig
index 9a5716d..7a40109 100644
--- a/arch/blackfin/configs/CM-BF533_defconfig
+++ b/arch/blackfin/configs/CM-BF533_defconfig
@@ -59,7 +59,6 @@  CONFIG_SPI_BFIN5XX=y
 # CONFIG_HWMON is not set
 # CONFIG_USB_SUPPORT is not set
 CONFIG_MMC=y
-# CONFIG_MMC_BLOCK_BOUNCE is not set
 CONFIG_MMC_SPI=m
 # CONFIG_DNOTIFY is not set
 CONFIG_VFAT_FS=y
diff --git a/arch/blackfin/configs/CM-BF537E_defconfig b/arch/blackfin/configs/CM-BF537E_defconfig
index 6845928..b47ced8 100644
--- a/arch/blackfin/configs/CM-BF537E_defconfig
+++ b/arch/blackfin/configs/CM-BF537E_defconfig
@@ -83,7 +83,6 @@  CONFIG_GPIO_SYSFS=y
 CONFIG_USB_GADGET=m
 CONFIG_USB_ETH=m
 CONFIG_MMC=y
-# CONFIG_MMC_BLOCK_BOUNCE is not set
 CONFIG_MMC_SPI=m
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
diff --git a/arch/mips/configs/cavium_octeon_defconfig b/arch/mips/configs/cavium_octeon_defconfig
index d4fda41..7f337cf 100644
--- a/arch/mips/configs/cavium_octeon_defconfig
+++ b/arch/mips/configs/cavium_octeon_defconfig
@@ -130,7 +130,6 @@  CONFIG_USB_OHCI_HCD_PLATFORM=m
 CONFIG_MMC=y
 # CONFIG_PWRSEQ_EMMC is not set
 # CONFIG_PWRSEQ_SIMPLE is not set
-# CONFIG_MMC_BLOCK_BOUNCE is not set
 CONFIG_MMC_CAVIUM_OCTEON=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_DS1307=y
diff --git a/arch/mips/configs/qi_lb60_defconfig b/arch/mips/configs/qi_lb60_defconfig
index d7bb8cc..df067bc 100644
--- a/arch/mips/configs/qi_lb60_defconfig
+++ b/arch/mips/configs/qi_lb60_defconfig
@@ -110,7 +110,6 @@  CONFIG_USB_ETH=y
 # CONFIG_USB_ETH_RNDIS is not set
 CONFIG_MMC=y
 CONFIG_MMC_UNSAFE_RESUME=y
-# CONFIG_MMC_BLOCK_BOUNCE is not set
 CONFIG_MMC_JZ4740=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_JZ4740=y
diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig
index fc1ecda..42e8906 100644
--- a/drivers/mmc/core/Kconfig
+++ b/drivers/mmc/core/Kconfig
@@ -61,24 +61,6 @@  config MMC_BLOCK_MINORS

 	  If unsure, say 8 here.

-config MMC_BLOCK_BOUNCE
-	bool "Use bounce buffer for simple hosts"
-	depends on MMC_BLOCK
-	default y
-	help
-	  SD/MMC is a high latency protocol where it is crucial to
-	  send large requests in order to get high performance. Many
-	  controllers, however, are restricted to continuous memory
-	  (i.e. they can't do scatter-gather), something the kernel
-	  rarely can provide.
-
-	  Say Y here to help these restricted hosts by bouncing
-	  requests back and forth from a large buffer. You will get
-	  a big performance gain at the cost of up to 64 KiB of
-	  physical memory.
-
-	  If unsure, say Y here.
-
 config SDIO_UART
 	tristate "SDIO UART/GPS class support"
 	depends on TTY
diff --git a/drivers/mmc/core/queue.c b/drivers/mmc/core/queue.c
index 5c37b6b..0dcf31d 100644
--- a/drivers/mmc/core/queue.c
+++ b/drivers/mmc/core/queue.c
@@ -23,8 +23,6 @@ 
 #include "core.h"
 #include "card.h"

-#define MMC_QUEUE_BOUNCESZ	65536
-
 /*
  * Prepare a MMC request. This just filters out odd stuff.
  */
@@ -219,73 +217,6 @@  static struct mmc_queue_req *mmc_queue_alloc_mqrqs(int qdepth)
 	return mqrq;
 }

-#ifdef CONFIG_MMC_BLOCK_BOUNCE
-static int mmc_queue_alloc_bounce_bufs(struct mmc_queue_req *mqrq, int qdepth,
-				       unsigned int bouncesz)
-{
-	int i;
-
-	for (i = 0; i < qdepth; i++) {
-		mqrq[i].bounce_buf = kmalloc(bouncesz, GFP_KERNEL);
-		if (!mqrq[i].bounce_buf)
-			return -ENOMEM;
-
-		mqrq[i].sg = mmc_alloc_sg(1);
-		if (!mqrq[i].sg)
-			return -ENOMEM;
-
-		mqrq[i].bounce_sg = mmc_alloc_sg(bouncesz / 512);
-		if (!mqrq[i].bounce_sg)
-			return -ENOMEM;
-	}
-
-	return 0;
-}
-
-static bool mmc_queue_alloc_bounce(struct mmc_queue_req *mqrq, int qdepth,
-				   unsigned int bouncesz)
-{
-	int ret;
-
-	ret = mmc_queue_alloc_bounce_bufs(mqrq, qdepth, bouncesz);
-	if (ret)
-		mmc_queue_reqs_free_bufs(mqrq, qdepth);
-
-	return !ret;
-}
-
-static unsigned int mmc_queue_calc_bouncesz(struct mmc_host *host)
-{
-	unsigned int bouncesz = MMC_QUEUE_BOUNCESZ;
-
-	if (host->max_segs != 1)
-		return 0;
-
-	if (bouncesz > host->max_req_size)
-		bouncesz = host->max_req_size;
-	if (bouncesz > host->max_seg_size)
-		bouncesz = host->max_seg_size;
-	if (bouncesz > host->max_blk_count * 512)
-		bouncesz = host->max_blk_count * 512;
-
-	if (bouncesz <= 512)
-		return 0;
-
-	return bouncesz;
-}
-#else
-static inline bool mmc_queue_alloc_bounce(struct mmc_queue_req *mqrq,
-					  int qdepth, unsigned int bouncesz)
-{
-	return false;
-}
-
-static unsigned int mmc_queue_calc_bouncesz(struct mmc_host *host)
-{
-	return 0;
-}
-#endif
-
 static int mmc_queue_alloc_sgs(struct mmc_queue_req *mqrq, int qdepth,
 			       int max_segs)
 {
@@ -312,7 +243,6 @@  static int __mmc_queue_alloc_shared_queue(struct mmc_card *card, int qdepth)
 {
 	struct mmc_host *host = card->host;
 	struct mmc_queue_req *mqrq;
-	unsigned int bouncesz;
 	int ret = 0;

 	if (card->mqrq)
@@ -325,26 +255,10 @@  static int __mmc_queue_alloc_shared_queue(struct mmc_card *card, int qdepth)
 	card->mqrq = mqrq;
 	card->qdepth = qdepth;

-	bouncesz = mmc_queue_calc_bouncesz(host);
-
-	if (bouncesz && !mmc_queue_alloc_bounce(mqrq, qdepth, bouncesz)) {
-		bouncesz = 0;
-		pr_warn("%s: unable to allocate bounce buffers\n",
-			mmc_card_name(card));
-	}
-
-	card->bouncesz = bouncesz;
-
-	if (!bouncesz) {
-		ret = mmc_queue_alloc_sgs(mqrq, qdepth, host->max_segs);
-		if (ret)
-			goto out_err;
-	}
-
-	return ret;
+	ret = mmc_queue_alloc_sgs(mqrq, qdepth, host->max_segs);
+	if (ret)
+		mmc_queue_free_shared_queue(card);

-out_err:
-	mmc_queue_free_shared_queue(card);
 	return ret;
 }

@@ -387,18 +301,11 @@  int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
 	if (mmc_can_erase(card))
 		mmc_queue_setup_discard(mq->queue, card);

-	if (card->bouncesz) {
-		blk_queue_bounce_limit(mq->queue, BLK_BOUNCE_ANY);
-		blk_queue_max_hw_sectors(mq->queue, card->bouncesz / 512);
-		blk_queue_max_segments(mq->queue, card->bouncesz / 512);
-		blk_queue_max_segment_size(mq->queue, card->bouncesz);
-	} else {
-		blk_queue_bounce_limit(mq->queue, limit);
-		blk_queue_max_hw_sectors(mq->queue,
-			min(host->max_blk_count, host->max_req_size / 512));
-		blk_queue_max_segments(mq->queue, host->max_segs);
-		blk_queue_max_segment_size(mq->queue, host->max_seg_size);
-	}
+	blk_queue_bounce_limit(mq->queue, limit);
+	blk_queue_max_hw_sectors(mq->queue,
+		min(host->max_blk_count, host->max_req_size / 512));
+	blk_queue_max_segments(mq->queue, host->max_segs);
+	blk_queue_max_segment_size(mq->queue, host->max_seg_size);

 	sema_init(&mq->thread_sem, 1);

diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c
index 621ce47..2c6d131 100644
--- a/drivers/mmc/host/davinci_mmc.c
+++ b/drivers/mmc/host/davinci_mmc.c
@@ -149,11 +149,7 @@ 

 /*
  * One scatterlist dma "segment" is at most MAX_CCNT rw_threshold units,
- * and we handle up to MAX_NR_SG segments.  MMC_BLOCK_BOUNCE kicks in only
- * for drivers with max_segs == 1, making the segments bigger (64KB)
- * than the page or two that's otherwise typical. nr_sg (passed from
- * platform data) == 16 gives at least the same throughput boost, using
- * EDMA transfer linkage instead of spending CPU time copying pages.
+ * and we handle up to MAX_NR_SG segments.
  */
 #define MAX_CCNT	((1 << 16) - 1)

diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index aad015e..23653c7 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -306,7 +306,6 @@  struct mmc_card {
 	unsigned int    nr_parts;

 	struct mmc_queue_req	*mqrq;		/* Shared queue structure */
-	unsigned int		bouncesz;	/* Bounce buffer size */
 	int			qdepth;		/* Shared queue depth */
 };