Date: Sun, 11 Jan 2015 21:25:04 +0000 (UTC) From: Ian Lepore <ian@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r277027 - head/sys/dev/sdhci Message-ID: <201501112125.t0BLP4mx057006@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201501112125.t0BLP4mx057006>