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

Commit 266b8e2f authored by Konstantin Dorfman's avatar Konstantin Dorfman
Browse files

sdhci: disable sg list fixing for ADMA alignment



Some SDHCi controller implementations did not require alignment
for ADMA buffers. When SDHCI_QUIRK2_ADMA_SKIP_DATA_ALIGNMENT defined,
the logic that fixes scatter gather list buffers is skipped.

CRs-fixed: 719302
Change-Id: I822b394a0ae4f9b8a132c13831c0cdf78684cb36
Signed-off-by: default avatarKonstantin Dorfman <kdorfman@codeaurora.org>
parent 1def2dee
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -3183,6 +3183,7 @@ static int sdhci_msm_probe(struct platform_device *pdev)
	}

	host->quirks2 |= SDHCI_QUIRK2_IGN_DATA_END_BIT_ERROR;
	host->quirks2 |= SDHCI_QUIRK2_ADMA_SKIP_DATA_ALIGNMENT;

	/* Setup PWRCTL irq */
	msm_host->pwr_irq = platform_get_irq_byname(pdev, "pwr_irq");
+38 −34
Original line number Diff line number Diff line
@@ -629,23 +629,25 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
		addr = sg_dma_address(sg);
		len = sg_dma_len(sg);

		if (!(host->quirks2 & SDHCI_QUIRK2_ADMA_SKIP_DATA_ALIGNMENT)) {
			/*
		 * The SDHCI specification states that ADMA addresses must be
		 * 32-bit aligned for 32-bit ADMA or 64-bit aligned for 64-bit
		 * ADMA. If they aren't, then we use a bounce buffer for the
		 * (up to three for 32-bit and up to seven for 64-bit) bytes
		 * that screw up the alignment.
		 *
			 * The SDHCI specification states that ADMA addresses
			 * must be 32-bit aligned for 32-bit ADMA or 64-bit
			 * aligned for 64-bit ADMA. If they aren't, then we use
			 * a bounce buffer for the (up to three for 32-bit and
			 * up to seven for 64-bit) bytes that screw up the
			 * alignment.
			 */
		offset = (host->align_bytes - (addr & (host->align_bytes - 1)))
			offset = (host->align_bytes
				- (addr & (host->align_bytes - 1)))
				& (host->align_bytes - 1);
			if (offset) {
				if (data->flags & MMC_DATA_WRITE) {
					buffer = sdhci_kmap_atomic(sg, &flags);
					/*
				 * This check is intended here to verify if the
				 * page offset plus alignment bytes is indeed
				 * within the same page.
					 * This check is intended here to verify
					 * if the page offset plus alignment
					 * bytes is indeed within the same page.
					 */
				WARN_ON(((long)buffer & (PAGE_SIZE - 1)) >
					(PAGE_SIZE - (host->align_bytes - 1)));
@@ -667,6 +669,7 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
				addr += offset;
				len -= offset;
			}
		}

		BUG_ON(len > 65536);

@@ -710,7 +713,8 @@ fail:
static void sdhci_adma_table_post(struct sdhci_host *host,
	struct mmc_data *data)
{
	int direction;
	int direction = (data->flags & MMC_DATA_WRITE)
				     ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
	struct scatterlist *sg;
	int i, size;
	u8 *align;
@@ -721,8 +725,9 @@ static void sdhci_adma_table_post(struct sdhci_host *host,

	trace_mmc_adma_table_post(command, data->sg_len);

	if (data->flags & MMC_DATA_READ) {
		direction = DMA_FROM_DEVICE;
	if (!(host->quirks2 & SDHCI_QUIRK2_ADMA_SKIP_DATA_ALIGNMENT)
			&& (data->flags & MMC_DATA_READ)) {

		/* Do a quick scan of the SG list for any unaligned mappings */
		for_each_sg(data->sg, sg, host->sg_count, i) {
			if (sg_dma_address(sg) & (host->align_bytes - 1)) {
@@ -730,11 +735,10 @@ static void sdhci_adma_table_post(struct sdhci_host *host,
				break;
			}
		}
	} else {
		direction = DMA_TO_DEVICE;
	}

	if (has_unaligned) {
	if (!(host->quirks2 & SDHCI_QUIRK2_ADMA_SKIP_DATA_ALIGNMENT)
	     && has_unaligned) {
		dma_sync_sg_for_cpu(mmc_dev(host->mmc), data->sg,
			data->sg_len, direction);

+7 −0
Original line number Diff line number Diff line
@@ -167,6 +167,13 @@ struct sdhci_host {
 * 1-bit mode of SDIO.
 */
#define SDHCI_QUIRK2_IGN_DATA_END_BIT_ERROR             (1<<9)

/*
 * Some SDHC controllers do not require data buffers alignment, skip
 * the bounce buffer logic when preparing data
 */
#define SDHCI_QUIRK2_ADMA_SKIP_DATA_ALIGNMENT             (1<<13)

	int irq;		/* Device IRQ */
	void __iomem *ioaddr;	/* Mapped address */