Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0df55ea5 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc: (78 commits)
  mmc: MAINTAINERS: add myself as a tmio-mmc maintainer
  mmc: print debug messages for runtime PM actions
  mmc: fix runtime PM with -ENOSYS suspend case
  mmc: at91_mci: move register header from include/ to drivers/
  mmc: mxs-mmc: fix clock rate setting
  mmc: tmio: fix a deadlock
  mmc: tmio: fix a recently introduced bug in DMA code
  mmc: sh_mmcif: maximize power saving
  mmc: tmio: maximize power saving
  mmc: tmio: fix recursive spinlock, don't schedule with interrupts disabled
  mmc: Added quirks for Ricoh 1180:e823 lower base clock frequency
  mmc: omap_hsmmc: fix oops in omap_hsmmc_dma_cb()
  mmc: omap_hsmmc: refactor duplicated code
  mmc: omap_hsmmc: fix a few bugs when setting the clock divisor
  mmc: omap_hsmmc: introduce start_clock and re-use stop_clock
  mmc: omap_hsmmc: split duplicate code to calc_divisor() function
  mmc: omap_hsmmc: move hardcoded frequency constants to defines
  mmc: omap_hsmmc: correct debug report error status mnemonics
  mmc: block: fixed NULL pointer dereference
  mmc: documentation of mmc non-blocking request usage and design.
  ...
parents c1f792a5 d1057c40
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -4,3 +4,5 @@ mmc-dev-attrs.txt
        - info on SD and MMC device attributes
mmc-dev-parts.txt
        - info on SD and MMC device partitions
mmc-async-req.txt
        - info on mmc asynchronous requests
+87 −0
Original line number Diff line number Diff line
Rationale
=========

How significant is the cache maintenance overhead?
It depends. Fast eMMC and multiple cache levels with speculative cache
pre-fetch makes the cache overhead relatively significant. If the DMA
preparations for the next request are done in parallel with the current
transfer, the DMA preparation overhead would not affect the MMC performance.
The intention of non-blocking (asynchronous) MMC requests is to minimize the
time between when an MMC request ends and another MMC request begins.
Using mmc_wait_for_req(), the MMC controller is idle while dma_map_sg and
dma_unmap_sg are processing. Using non-blocking MMC requests makes it
possible to prepare the caches for next job in parallel with an active
MMC request.

MMC block driver
================

The mmc_blk_issue_rw_rq() in the MMC block driver is made non-blocking.
The increase in throughput is proportional to the time it takes to
prepare (major part of preparations are dma_map_sg() and dma_unmap_sg())
a request and how fast the memory is. The faster the MMC/SD is the
more significant the prepare request time becomes. Roughly the expected
performance gain is 5% for large writes and 10% on large reads on a L2 cache
platform. In power save mode, when clocks run on a lower frequency, the DMA
preparation may cost even more. As long as these slower preparations are run
in parallel with the transfer performance won't be affected.

Details on measurements from IOZone and mmc_test
================================================

https://wiki.linaro.org/WorkingGroups/Kernel/Specs/StoragePerfMMC-async-req

MMC core API extension
======================

There is one new public function mmc_start_req().
It starts a new MMC command request for a host. The function isn't
truly non-blocking. If there is an ongoing async request it waits
for completion of that request and starts the new one and returns. It
doesn't wait for the new request to complete. If there is no ongoing
request it starts the new request and returns immediately.

MMC host extensions
===================

There are two optional members in the mmc_host_ops -- pre_req() and
post_req() -- that the host driver may implement in order to move work
to before and after the actual mmc_host_ops.request() function is called.
In the DMA case pre_req() may do dma_map_sg() and prepare the DMA
descriptor, and post_req() runs the dma_unmap_sg().

Optimize for the first request
==============================

The first request in a series of requests can't be prepared in parallel
with the previous transfer, since there is no previous request.
The argument is_first_req in pre_req() indicates that there is no previous
request. The host driver may optimize for this scenario to minimize
the performance loss. A way to optimize for this is to split the current
request in two chunks, prepare the first chunk and start the request,
and finally prepare the second chunk and start the transfer.

Pseudocode to handle is_first_req scenario with minimal prepare overhead:

if (is_first_req && req->size > threshold)
   /* start MMC transfer for the complete transfer size */
   mmc_start_command(MMC_CMD_TRANSFER_FULL_SIZE);

   /*
    * Begin to prepare DMA while cmd is being processed by MMC.
    * The first chunk of the request should take the same time
    * to prepare as the "MMC process command time".
    * If prepare time exceeds MMC cmd time
    * the transfer is delayed, guesstimate max 4k as first chunk size.
    */
    prepare_1st_chunk_for_dma(req);
    /* flush pending desc to the DMAC (dmaengine.h) */
    dma_issue_pending(req->dma_desc);

    prepare_2nd_chunk_for_dma(req);
    /*
     * The second issue_pending should be called before MMC runs out
     * of the first chunk. If the MMC runs out of the first data chunk
     * before this call, the transfer is delayed.
     */
    dma_issue_pending(req->dma_desc);
+7 −3
Original line number Diff line number Diff line
@@ -4585,9 +4585,8 @@ S: Maintained
F:	drivers/mmc/host/omap.c

OMAP HS MMC SUPPORT
M:	Madhusudhan Chikkature <madhu.cr@ti.com>
L:	linux-omap@vger.kernel.org
S:	Maintained
S:	Orphan
F:	drivers/mmc/host/omap_hsmmc.c

OMAP RANDOM NUMBER GENERATOR SUPPORT
@@ -6243,9 +6242,14 @@ F: drivers/char/toshiba.c
F:	include/linux/toshiba.h

TMIO MMC DRIVER
M:	Guennadi Liakhovetski <g.liakhovetski@gmx.de>
M:	Ian Molton <ian@mnementh.co.uk>
L:	linux-mmc@vger.kernel.org
S:	Maintained
F:	drivers/mmc/host/tmio_mmc.*
F:	drivers/mmc/host/tmio_mmc*
F:	drivers/mmc/host/sh_mobile_sdhi.c
F:	include/linux/mmc/tmio.h
F:	include/linux/mmc/sh_mobile_sdhi.h

TMPFS (SHMEM FILESYSTEM)
M:	Hugh Dickins <hughd@google.com>
+8 −1
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@ CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
# CONFIG_BLK_DEV_BSG is not set
CONFIG_ARCH_MMP=y
CONFIG_MACH_BROWNSTONE=y
CONFIG_MACH_FLINT=y
CONFIG_MACH_MARVELL_JASPER=y
CONFIG_HIGH_RES_TIMERS=y
@@ -63,10 +64,16 @@ CONFIG_BACKLIGHT_MAX8925=y
# CONFIG_USB_SUPPORT is not set
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_MAX8925=y
CONFIG_MMC=y
# CONFIG_DNOTIFY is not set
CONFIG_INOTIFY=y
CONFIG_TMPFS=y
CONFIG_TMPFS_POSIX_ACL=y
CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y
CONFIG_EXT4_FS=y
CONFIG_MSDOS_FS=y
CONFIG_FAT_DEFAULT_CODEPAGE=437
CONFIG_JFFS2_FS=y
CONFIG_CRAMFS=y
CONFIG_NFS_FS=y
@@ -81,7 +88,7 @@ CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_PREEMPT is not set
CONFIG_DEBUG_INFO=y
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_DYNAMIC_DEBUG=y
# CONFIG_DYNAMIC_DEBUG is not set
CONFIG_DEBUG_USER=y
CONFIG_DEBUG_ERRORS=y
# CONFIG_CRYPTO_ANSI_CPRNG is not set
+9 −1
Original line number Diff line number Diff line
@@ -177,9 +177,16 @@ static struct i2c_board_info brownstone_twsi1_info[] = {
};

static struct sdhci_pxa_platdata mmp2_sdh_platdata_mmc0 = {
	.max_speed	= 25000000,
	.clk_delay_cycles = 0x1f,
};

static struct sdhci_pxa_platdata mmp2_sdh_platdata_mmc2 = {
	.clk_delay_cycles = 0x1f,
	.flags = PXA_FLAG_CARD_PERMANENT
		| PXA_FLAG_SD_8_BIT_CAPABLE_SLOT,
};


static void __init brownstone_init(void)
{
	mfp_config(ARRAY_AND_SIZE(brownstone_pin_config));
@@ -189,6 +196,7 @@ static void __init brownstone_init(void)
	mmp2_add_uart(3);
	mmp2_add_twsi(1, NULL, ARRAY_AND_SIZE(brownstone_twsi1_info));
	mmp2_add_sdhost(0, &mmp2_sdh_platdata_mmc0); /* SD/MMC */
	mmp2_add_sdhost(2, &mmp2_sdh_platdata_mmc2); /* eMMC */

	/* enable 5v regulator */
	platform_device_register(&brownstone_v_5vp_device);
Loading