From patchwork Sat Oct 16 21:19:36 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Frysinger X-Patchwork-Id: 259291 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id o9GLKBOC005024 for ; Sat, 16 Oct 2010 21:20:11 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754228Ab0JPVUK (ORCPT ); Sat, 16 Oct 2010 17:20:10 -0400 Received: from smtp.gentoo.org ([140.211.166.183]:47325 "EHLO smtp.gentoo.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754164Ab0JPVUJ (ORCPT ); Sat, 16 Oct 2010 17:20:09 -0400 Received: from localhost.localdomain (localhost [127.0.0.1]) by smtp.gentoo.org (Postfix) with ESMTP id 6F2EC1B416F; Sat, 16 Oct 2010 21:19:56 +0000 (UTC) From: Mike Frysinger To: linux-mmc@vger.kernel.org, Adrian Hunter , Andrew Morton Cc: uclinux-dist-devel@blackfin.uclinux.org, linux-kernel@vger.kernel.org, David Brownell , Grant Likely , Anton Vorontsov , Ernst Schwab , Sonic Zhang , Chris Ball Subject: [PATCH] MMC:mmc_spi: Recover from CRC error for SD read/write operation over SPI. Date: Sat, 16 Oct 2010 17:19:36 -0400 Message-Id: <1287263976-9578-1-git-send-email-vapier@gentoo.org> X-Mailer: git-send-email 1.7.3.1 In-Reply-To: <20100827203639.GT23079@void.printf.net> References: <20100827203639.GT23079@void.printf.net> Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Sat, 16 Oct 2010 21:20:11 +0000 (UTC) diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c index 62a3582..fbd673e 100644 --- a/drivers/mmc/host/mmc_spi.c +++ b/drivers/mmc/host/mmc_spi.c @@ -1055,6 +1055,8 @@ static void mmc_spi_request(struct mmc_host *mmc, struct mmc_request *mrq) { struct mmc_spi_host *host = mmc_priv(mmc); int status = -EINVAL; + int crc_retry = 5; + struct mmc_command stop; #ifdef DEBUG /* MMC core and layered drivers *MUST* issue SPI-aware commands */ @@ -1087,10 +1089,30 @@ static void mmc_spi_request(struct mmc_host *mmc, struct mmc_request *mrq) /* request exclusive bus access */ spi_bus_lock(host->spi->master); + crc_recover: /* issue command; then optionally data and stop */ status = mmc_spi_command_send(host, mrq, mrq->cmd, mrq->data != NULL); if (status == 0 && mrq->data) { mmc_spi_data_do(host, mrq->cmd, mrq->data, mrq->data->blksz); + + /* + * SPI bus is not reliable when doing large data transfer. + * If occasional crc error is reported by SD device when do + * data read/write over SPI, it can be recovered by doing + * last SD command again. The retry count is set to 5 to + * ensure the driver pass any stress test. + */ + if (mrq->data->error == -EILSEQ && crc_retry) { + stop.opcode = MMC_STOP_TRANSMISSION; + stop.arg = 0; + stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; + + status = mmc_spi_command_send(host, mrq, &stop, 0); + crc_retry--; + mrq->data->error = 0; + goto crc_recover; + } + if (mrq->stop) status = mmc_spi_command_send(host, mrq, mrq->stop, 0); else