From owner-svn-src-head@FreeBSD.ORG Sun Jan 11 21:25:05 2015 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 025BF5E1; Sun, 11 Jan 2015 21:25:05 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id C9B792B5; Sun, 11 Jan 2015 21:25:04 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id t0BLP4v8057008; Sun, 11 Jan 2015 21:25:04 GMT (envelope-from ian@FreeBSD.org) Received: (from ian@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id t0BLP4mx057006; Sun, 11 Jan 2015 21:25:04 GMT (envelope-from ian@FreeBSD.org) Message-Id: <201501112125.t0BLP4mx057006@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: ian set sender to ian@FreeBSD.org using -f From: Ian Lepore Date: Sun, 11 Jan 2015 21:25:04 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r277027 - head/sys/dev/sdhci X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 11 Jan 2015 21:25:05 -0000 Author: ian Date: Sun Jan 11 21:25:03 2015 New Revision: 277027 URL: https://svnweb.freebsd.org/changeset/base/277027 Log: Handle the possibility that SDHCI_PLATFORM_START_TRANSFER() can fail, by moving the handling of curcmd->error != 0 to the end of the interrupt handler. Also make sdhci_finish_data() idempotent by moving the setting of slot->data_done = 1 down past the point where the busdma buffer is unmapped. This allows for the possibility that the finish routine can get called from multiple places when handling errors. Modified: head/sys/dev/sdhci/sdhci.c Modified: head/sys/dev/sdhci/sdhci.c ============================================================================== --- head/sys/dev/sdhci/sdhci.c Sun Jan 11 20:55:16 2015 (r277026) +++ head/sys/dev/sdhci/sdhci.c Sun Jan 11 21:25:03 2015 (r277027) @@ -984,7 +984,6 @@ sdhci_finish_data(struct sdhci_slot *slo { struct mmc_data *data = slot->curcmd->data; - slot->data_done = 1; /* Interrupt aggregation: Restore command interrupt. * Auxiliary restore point for the case when data interrupt * happened first. */ @@ -993,7 +992,7 @@ sdhci_finish_data(struct sdhci_slot *slo slot->intmask |= SDHCI_INT_RESPONSE); } /* Unload rest of data from DMA buffer. */ - if (slot->flags & SDHCI_USE_DMA) { + if (!slot->data_done && (slot->flags & SDHCI_USE_DMA)) { if (data->flags & MMC_DATA_READ) { size_t left = data->len - slot->offset; bus_dmamap_sync(slot->dmatag, slot->dmamap, @@ -1004,6 +1003,7 @@ sdhci_finish_data(struct sdhci_slot *slo bus_dmamap_sync(slot->dmatag, slot->dmamap, BUS_DMASYNC_POSTWRITE); } + slot->data_done = 1; /* If there was error - reset the host. */ if (slot->curcmd->error) { sdhci_reset(slot, SDHCI_RESET_CMD); @@ -1171,12 +1171,7 @@ sdhci_data_irq(struct sdhci_slot *slot, } if (slot->curcmd->error) { /* No need to continue after any error. */ - if (slot->flags & PLATFORM_DATA_STARTED) { - slot->flags &= ~PLATFORM_DATA_STARTED; - SDHCI_PLATFORM_FINISH_TRANSFER(slot->bus, slot); - } else - sdhci_finish_data(slot); - return; + goto done; } /* Handle PIO interrupt. */ @@ -1233,6 +1228,15 @@ sdhci_data_irq(struct sdhci_slot *slot, } else sdhci_finish_data(slot); } +done: + if (slot->curcmd != NULL && slot->curcmd->error != 0) { + if (slot->flags & PLATFORM_DATA_STARTED) { + slot->flags &= ~PLATFORM_DATA_STARTED; + SDHCI_PLATFORM_FINISH_TRANSFER(slot->bus, slot); + } else + sdhci_finish_data(slot); + return; + } } static void