From patchwork Mon Aug 31 16:25:49 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexey Brodkin X-Patchwork-Id: 512546 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133]) by ozlabs.org (Postfix) with ESMTP id 309FA1401F0 for ; Tue, 1 Sep 2015 02:26:05 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by hemlock.osuosl.org (Postfix) with ESMTP id 743FC95D41; Mon, 31 Aug 2015 16:26:04 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from hemlock.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 3e92crzMAAE6; Mon, 31 Aug 2015 16:25:59 +0000 (UTC) Received: from ash.osuosl.org (ash.osuosl.org [140.211.166.34]) by hemlock.osuosl.org (Postfix) with ESMTP id 2F86095D19; Mon, 31 Aug 2015 16:25:59 +0000 (UTC) X-Original-To: buildroot@lists.busybox.net Delivered-To: buildroot@osuosl.org Received: from whitealder.osuosl.org (smtp1.osuosl.org [140.211.166.138]) by ash.osuosl.org (Postfix) with ESMTP id 508221C2781 for ; Mon, 31 Aug 2015 16:25:56 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by whitealder.osuosl.org (Postfix) with ESMTP id CE1BC8D560 for ; Mon, 31 Aug 2015 16:25:56 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from whitealder.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id iLORUZAxrQEo for ; Mon, 31 Aug 2015 16:25:55 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from smtprelay.synopsys.com (us01smtprelay-2.synopsys.com [198.182.60.111]) by whitealder.osuosl.org (Postfix) with ESMTPS id A5D018D45D for ; Mon, 31 Aug 2015 16:25:55 +0000 (UTC) Received: from dc8secmta2.synopsys.com (dc8secmta2.synopsys.com [10.13.218.202]) by smtprelay.synopsys.com (Postfix) with ESMTP id 6120910C019E; Mon, 31 Aug 2015 09:25:54 -0700 (PDT) Received: from dc8secmta2.internal.synopsys.com (dc8secmta2.internal.synopsys.com [127.0.0.1]) by dc8secmta2.internal.synopsys.com (Service) with ESMTP id 5E08CA4114; Mon, 31 Aug 2015 09:25:54 -0700 (PDT) Received: from mailhost.synopsys.com (mailhost3.synopsys.com [10.12.238.238]) by dc8secmta2.internal.synopsys.com (Service) with ESMTP id 22EB3A4102; Mon, 31 Aug 2015 09:25:54 -0700 (PDT) Received: from mailhost.synopsys.com (localhost [127.0.0.1]) by mailhost.synopsys.com (Postfix) with ESMTP id 07C449E3; Mon, 31 Aug 2015 09:25:54 -0700 (PDT) Received: from abrodkin-e7440l.internal.synopsys.com (unknown [10.225.15.67]) by mailhost.synopsys.com (Postfix) with ESMTP id 411BF9DB; Mon, 31 Aug 2015 09:25:51 -0700 (PDT) From: Alexey Brodkin To: buildroot@busybox.net Date: Mon, 31 Aug 2015 19:25:49 +0300 Message-Id: <1441038349-14606-1-git-send-email-abrodkin@synopsys.com> X-Mailer: git-send-email 2.4.3 Cc: Thomas Petazzoni , Alexey Brodkin Subject: [Buildroot] [PATCH] arc: axs10x - bump Linux kernel to 4.2 release X-BeenThere: buildroot@busybox.net X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: Discussion and development of buildroot List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: buildroot-bounces@busybox.net Sender: "buildroot" Linux kernel 4.2 was finally released, so bumping from 4.2-rc5 to final release. Also adding 1 back-ported patch that makes SD/MMC cards usable on AXS boards. This patch will be a part of 4.3 (already in linux-next) and hopefully will make its way in 4.2.1. Once that patch appears in 4.2.x it must be removed from here. Cc: Peter Korsgaard Cc: Thomas Petazzoni Signed-off-by: Alexey Brodkin --- Hopefully this is not too late for v2015.08 Buildroot release. 4.2 hasjust released and I had to test build on real HW. Sorry for that last moment patch. ...handle-data-blocks-than-4kB-if-IDMAC-is-u.patch | 198 +++++++++++++++++++++ configs/snps_axs101_defconfig | 3 +- configs/snps_axs103_defconfig | 3 +- 3 files changed, 202 insertions(+), 2 deletions(-) create mode 100644 board/synopsys/axs10x/patches/linux/0001-mmc-dw_mmc-handle-data-blocks-than-4kB-if-IDMAC-is-u.patch diff --git a/board/synopsys/axs10x/patches/linux/0001-mmc-dw_mmc-handle-data-blocks-than-4kB-if-IDMAC-is-u.patch b/board/synopsys/axs10x/patches/linux/0001-mmc-dw_mmc-handle-data-blocks-than-4kB-if-IDMAC-is-u.patch new file mode 100644 index 0000000..93986b0 --- /dev/null +++ b/board/synopsys/axs10x/patches/linux/0001-mmc-dw_mmc-handle-data-blocks-than-4kB-if-IDMAC-is-u.patch @@ -0,0 +1,198 @@ +From 969872e334937bd0956887a925f20f7a446af5f6 Mon Sep 17 00:00:00 2001 +From: Alexey Brodkin +Date: Thu, 25 Jun 2015 11:25:07 +0300 +Subject: [PATCH] mmc: dw_mmc: handle data blocks > than 4kB if IDMAC is used + +As per DW MobileStorage databook "each descriptor can transfer up to 4kB +of data in chained mode", moreover buffer size that is put in "des1" is +limited to 13 bits, i.e. for example on attempt to +IDMAC_SET_BUFFER1_SIZE(desc, 8192) size value that's effectively written +will be 0. + +On the platform with 8kB PAGE_SIZE I see dw_mmc gets data blocks in +SG-list of 8kB size and that leads to unpredictable behavior of the +SD/MMC controller. + +In particular on write to FAT partition of SD-card the controller will +stuck in the middle of DMA transaction. + +Solution to the problem is simple - we need to pass large (> 4kB) data +buffers to the controller via multiple descriptors. And that's what +that change does. + +What's interesting I did try original driver on same platform but +configured with 4kB PAGE_SIZE and may confirm that data blocks passed +in SG-list to dw_mmc never exeed 4kB limit - that explains why nobody +ever faced a problem I did. + +Signed-off-by: Alexey Brodkin +Cc: Seungwon Jeon +Cc: Jaehoon Chung +Cc: Ulf Hansson +Cc: arc-linux-dev@synopsys.com +Cc: linux-kernel@vger.kernel.org +Signed-off-by: Jaehoon Chung +--- + drivers/mmc/host/dw_mmc.c | 109 ++++++++++++++++++++++++++++++---------------- + 1 file changed, 71 insertions(+), 38 deletions(-) + +diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c +index 40e9d8e..e41fb74 100644 +--- a/drivers/mmc/host/dw_mmc.c ++++ b/drivers/mmc/host/dw_mmc.c +@@ -99,6 +99,9 @@ struct idmac_desc { + + __le32 des3; /* buffer 2 physical address */ + }; ++ ++/* Each descriptor can transfer up to 4KB of data in chained mode */ ++#define DW_MCI_DESC_DATA_LENGTH 0x1000 + #endif /* CONFIG_MMC_DW_IDMAC */ + + static bool dw_mci_reset(struct dw_mci *host); +@@ -462,66 +465,96 @@ static void dw_mci_idmac_complete_dma(struct dw_mci *host) + static void dw_mci_translate_sglist(struct dw_mci *host, struct mmc_data *data, + unsigned int sg_len) + { ++ unsigned int desc_len; + int i; + if (host->dma_64bit_address == 1) { +- struct idmac_desc_64addr *desc = host->sg_cpu; ++ struct idmac_desc_64addr *desc_first, *desc_last, *desc; ++ ++ desc_first = desc_last = desc = host->sg_cpu; + +- for (i = 0; i < sg_len; i++, desc++) { ++ for (i = 0; i < sg_len; i++) { + unsigned int length = sg_dma_len(&data->sg[i]); + u64 mem_addr = sg_dma_address(&data->sg[i]); + +- /* +- * Set the OWN bit and disable interrupts for this +- * descriptor +- */ +- desc->des0 = IDMAC_DES0_OWN | IDMAC_DES0_DIC | +- IDMAC_DES0_CH; +- /* Buffer length */ +- IDMAC_64ADDR_SET_BUFFER1_SIZE(desc, length); +- +- /* Physical address to DMA to/from */ +- desc->des4 = mem_addr & 0xffffffff; +- desc->des5 = mem_addr >> 32; ++ for ( ; length ; desc++) { ++ desc_len = (length <= DW_MCI_DESC_DATA_LENGTH) ? ++ length : DW_MCI_DESC_DATA_LENGTH; ++ ++ length -= desc_len; ++ ++ /* ++ * Set the OWN bit and disable interrupts ++ * for this descriptor ++ */ ++ desc->des0 = IDMAC_DES0_OWN | IDMAC_DES0_DIC | ++ IDMAC_DES0_CH; ++ ++ /* Buffer length */ ++ IDMAC_64ADDR_SET_BUFFER1_SIZE(desc, desc_len); ++ ++ /* Physical address to DMA to/from */ ++ desc->des4 = mem_addr & 0xffffffff; ++ desc->des5 = mem_addr >> 32; ++ ++ /* Update physical address for the next desc */ ++ mem_addr += desc_len; ++ ++ /* Save pointer to the last descriptor */ ++ desc_last = desc; ++ } + } + + /* Set first descriptor */ +- desc = host->sg_cpu; +- desc->des0 |= IDMAC_DES0_FD; ++ desc_first->des0 |= IDMAC_DES0_FD; + + /* Set last descriptor */ +- desc = host->sg_cpu + (i - 1) * +- sizeof(struct idmac_desc_64addr); +- desc->des0 &= ~(IDMAC_DES0_CH | IDMAC_DES0_DIC); +- desc->des0 |= IDMAC_DES0_LD; ++ desc_last->des0 &= ~(IDMAC_DES0_CH | IDMAC_DES0_DIC); ++ desc_last->des0 |= IDMAC_DES0_LD; + + } else { +- struct idmac_desc *desc = host->sg_cpu; ++ struct idmac_desc *desc_first, *desc_last, *desc; ++ ++ desc_first = desc_last = desc = host->sg_cpu; + +- for (i = 0; i < sg_len; i++, desc++) { ++ for (i = 0; i < sg_len; i++) { + unsigned int length = sg_dma_len(&data->sg[i]); + u32 mem_addr = sg_dma_address(&data->sg[i]); + +- /* +- * Set the OWN bit and disable interrupts for this +- * descriptor +- */ +- desc->des0 = cpu_to_le32(IDMAC_DES0_OWN | +- IDMAC_DES0_DIC | IDMAC_DES0_CH); +- /* Buffer length */ +- IDMAC_SET_BUFFER1_SIZE(desc, length); ++ for ( ; length ; desc++) { ++ desc_len = (length <= DW_MCI_DESC_DATA_LENGTH) ? ++ length : DW_MCI_DESC_DATA_LENGTH; ++ ++ length -= desc_len; ++ ++ /* ++ * Set the OWN bit and disable interrupts ++ * for this descriptor ++ */ ++ desc->des0 = cpu_to_le32(IDMAC_DES0_OWN | ++ IDMAC_DES0_DIC | ++ IDMAC_DES0_CH); ++ ++ /* Buffer length */ ++ IDMAC_SET_BUFFER1_SIZE(desc, desc_len); + +- /* Physical address to DMA to/from */ +- desc->des2 = cpu_to_le32(mem_addr); ++ /* Physical address to DMA to/from */ ++ desc->des2 = cpu_to_le32(mem_addr); ++ ++ /* Update physical address for the next desc */ ++ mem_addr += desc_len; ++ ++ /* Save pointer to the last descriptor */ ++ desc_last = desc; ++ } + } + + /* Set first descriptor */ +- desc = host->sg_cpu; +- desc->des0 |= cpu_to_le32(IDMAC_DES0_FD); ++ desc_first->des0 |= cpu_to_le32(IDMAC_DES0_FD); + + /* Set last descriptor */ +- desc = host->sg_cpu + (i - 1) * sizeof(struct idmac_desc); +- desc->des0 &= cpu_to_le32(~(IDMAC_DES0_CH | IDMAC_DES0_DIC)); +- desc->des0 |= cpu_to_le32(IDMAC_DES0_LD); ++ desc_last->des0 &= cpu_to_le32(~(IDMAC_DES0_CH | ++ IDMAC_DES0_DIC)); ++ desc_last->des0 |= cpu_to_le32(IDMAC_DES0_LD); + } + + wmb(); +@@ -2394,7 +2427,7 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) + #ifdef CONFIG_MMC_DW_IDMAC + mmc->max_segs = host->ring_size; + mmc->max_blk_size = 65536; +- mmc->max_seg_size = 0x1000; ++ mmc->max_seg_size = DW_MCI_DESC_DATA_LENGTH; + mmc->max_req_size = mmc->max_seg_size * host->ring_size; + mmc->max_blk_count = mmc->max_req_size / 512; + #else +-- +2.4.3 + diff --git a/configs/snps_axs101_defconfig b/configs/snps_axs101_defconfig index 1f1acac..ef6540b 100644 --- a/configs/snps_axs101_defconfig +++ b/configs/snps_axs101_defconfig @@ -16,7 +16,8 @@ BR2_PACKAGE_HOST_LINUX_HEADERS_CUSTOM_4_1=y # Kernel BR2_LINUX_KERNEL=y BR2_LINUX_KERNEL_CUSTOM_VERSION=y -BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="4.2-rc5" +BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="4.2" +BR2_LINUX_KERNEL_PATCH="board/synopsys/axs10x/patches/linux" BR2_LINUX_KERNEL_DEFCONFIG="axs101" # Bootloader diff --git a/configs/snps_axs103_defconfig b/configs/snps_axs103_defconfig index 4efdfd1..65f7544 100644 --- a/configs/snps_axs103_defconfig +++ b/configs/snps_axs103_defconfig @@ -17,7 +17,8 @@ BR2_PACKAGE_HOST_LINUX_HEADERS_CUSTOM_4_1=y # Kernel BR2_LINUX_KERNEL=y BR2_LINUX_KERNEL_CUSTOM_VERSION=y -BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="4.2-rc5" +BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="4.2" +BR2_LINUX_KERNEL_PATCH="board/synopsys/axs10x/patches/linux" BR2_LINUX_KERNEL_DEFCONFIG="axs103_smp" # Bootloader