From owner-svn-src-all@freebsd.org Mon Nov 18 18:40:36 2019 Return-Path: Delivered-To: svn-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 9478E1C687B; Mon, 18 Nov 2019 18:40:36 +0000 (UTC) (envelope-from kevans@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 47GySh3VLCz4Ndy; Mon, 18 Nov 2019 18:40:36 +0000 (UTC) (envelope-from kevans@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 5B6C42E0CA; Mon, 18 Nov 2019 18:40:36 +0000 (UTC) (envelope-from kevans@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id xAIIeaDB050947; Mon, 18 Nov 2019 18:40:36 GMT (envelope-from kevans@FreeBSD.org) Received: (from kevans@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id xAIIeaTe050946; Mon, 18 Nov 2019 18:40:36 GMT (envelope-from kevans@FreeBSD.org) Message-Id: <201911181840.xAIIeaTe050946@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: kevans set sender to kevans@FreeBSD.org using -f From: Kyle Evans Date: Mon, 18 Nov 2019 18:40:36 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r354823 - head/sys/arm/broadcom/bcm2835 X-SVN-Group: head X-SVN-Commit-Author: kevans X-SVN-Commit-Paths: head/sys/arm/broadcom/bcm2835 X-SVN-Commit-Revision: 354823 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 18 Nov 2019 18:40:36 -0000 Author: kevans Date: Mon Nov 18 18:40:35 2019 New Revision: 354823 URL: https://svnweb.freebsd.org/changeset/base/354823 Log: bcm2835_sdhci: push DATA_END handling out of DMA interrupt path This simplifies the DMA interrupt handler quite a bit. The sdhci framework will call platform_finish_transfer() if it's received SDHCI_INT_DATA_END, so we can take care of any final cleanup there and simply not worry about the possibility of it ending in the DMA interrupt path. Modified: head/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c Modified: head/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c ============================================================================== --- head/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c Mon Nov 18 18:34:23 2019 (r354822) +++ head/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c Mon Nov 18 18:40:35 2019 (r354823) @@ -167,6 +167,8 @@ bcm_sdhci_dmacb(void *arg, bus_dma_segment_t *segs, in struct bcm_sdhci_softc *sc = arg; int i; + /* Sanity check: we can only ever have one mapping at a time. */ + KASSERT(sc->dmamap_seg_count == 0, ("leaked DMA segment")); sc->dmamap_status = err; sc->dmamap_seg_count = nseg; @@ -546,8 +548,8 @@ bcm_sdhci_start_dma_seg(struct bcm_sdhci_softc *sc) */ if (idx == 0) { bus_dmamap_sync(sc->sc_dma_tag, sc->sc_dma_map, sync_op); - slot->intmask &= ~(SDHCI_INT_DATA_AVAIL | - SDHCI_INT_SPACE_AVAIL | SDHCI_INT_DATA_END); + slot->intmask &= ~(SDHCI_INT_DATA_AVAIL | + SDHCI_INT_SPACE_AVAIL); bcm_sdhci_write_4(sc->sc_dev, &sc->sc_slot, SDHCI_SIGNAL_ENABLE, slot->intmask); } @@ -572,8 +574,6 @@ bcm_sdhci_dma_intr(int ch, void *arg) if (slot->curcmd == NULL) { mtx_unlock(&slot->mtx); - device_printf(sc->sc_dev, - "command aborted in the middle of DMA\n"); return; } @@ -595,12 +595,15 @@ bcm_sdhci_dma_intr(int ch, void *arg) sync_op = BUS_DMASYNC_POSTWRITE; mask = SDHCI_INT_SPACE_AVAIL; } - bus_dmamap_sync(sc->sc_dma_tag, sc->sc_dma_map, sync_op); - bus_dmamap_unload(sc->sc_dma_tag, sc->sc_dma_map); - sc->dmamap_seg_count = 0; - sc->dmamap_seg_index = 0; + if (sc->dmamap_seg_count != 0) { + bus_dmamap_sync(sc->sc_dma_tag, sc->sc_dma_map, sync_op); + bus_dmamap_unload(sc->sc_dma_tag, sc->sc_dma_map); + sc->dmamap_seg_count = 0; + sc->dmamap_seg_index = 0; + } + left = min(BCM_SDHCI_BUFFER_SIZE, slot->curcmd->data->len - slot->offset); @@ -612,57 +615,40 @@ bcm_sdhci_dma_intr(int ch, void *arg) */ if (left < BCM_SDHCI_BUFFER_SIZE) { /* Re-enable data interrupts. */ - slot->intmask |= SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | - SDHCI_INT_DATA_END; + slot->intmask |= SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL; bcm_sdhci_write_4(slot->bus, slot, SDHCI_SIGNAL_ENABLE, slot->intmask); mtx_unlock(&slot->mtx); return; } - /* DATA END? */ reg = bcm_sdhci_read_4(slot->bus, slot, SDHCI_INT_STATUS); - if (reg & SDHCI_INT_DATA_END) { - /* ACK for all outstanding interrupts */ - bcm_sdhci_write_4(slot->bus, slot, SDHCI_INT_STATUS, reg); + /* already available? */ + if (reg & mask) { - /* enable INT */ - slot->intmask |= SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL - | SDHCI_INT_DATA_END; - bcm_sdhci_write_4(slot->bus, slot, SDHCI_SIGNAL_ENABLE, - slot->intmask); + /* ACK for DATA_AVAIL or SPACE_AVAIL */ + bcm_sdhci_write_4(slot->bus, slot, + SDHCI_INT_STATUS, mask); - /* finish this data */ - sdhci_finish_data(slot); - } - else { - /* already available? */ - if (reg & mask) { - - /* ACK for DATA_AVAIL or SPACE_AVAIL */ - bcm_sdhci_write_4(slot->bus, slot, - SDHCI_INT_STATUS, mask); - - /* continue next DMA transfer */ - if (bus_dmamap_load(sc->sc_dma_tag, sc->sc_dma_map, - (uint8_t *)slot->curcmd->data->data + - slot->offset, left, bcm_sdhci_dmacb, sc, - BUS_DMA_NOWAIT) != 0 || sc->dmamap_status != 0) { - slot->curcmd->error = MMC_ERR_NO_MEMORY; - sdhci_finish_data(slot); - } else { - bcm_sdhci_start_dma_seg(sc); - } + /* continue next DMA transfer */ + if (bus_dmamap_load(sc->sc_dma_tag, sc->sc_dma_map, + (uint8_t *)slot->curcmd->data->data + + slot->offset, left, bcm_sdhci_dmacb, sc, + BUS_DMA_NOWAIT) != 0 || sc->dmamap_status != 0) { + slot->curcmd->error = MMC_ERR_NO_MEMORY; + sdhci_finish_data(slot); } else { - /* wait for next data by INT */ - - /* enable INT */ - slot->intmask |= SDHCI_INT_DATA_AVAIL | - SDHCI_INT_SPACE_AVAIL | SDHCI_INT_DATA_END; - bcm_sdhci_write_4(slot->bus, slot, SDHCI_SIGNAL_ENABLE, - slot->intmask); + bcm_sdhci_start_dma_seg(sc); } + } else { + /* wait for next data by INT */ + + /* enable INT */ + slot->intmask |= SDHCI_INT_DATA_AVAIL | + SDHCI_INT_SPACE_AVAIL; + bcm_sdhci_write_4(slot->bus, slot, SDHCI_SIGNAL_ENABLE, + slot->intmask); } mtx_unlock(&slot->mtx); @@ -674,6 +660,7 @@ bcm_sdhci_read_dma(device_t dev, struct sdhci_slot *sl struct bcm_sdhci_softc *sc = device_get_softc(slot->bus); size_t left; + /* XXX TODO: Not many-segment safe */ if (sc->dmamap_seg_count != 0) { device_printf(sc->sc_dev, "DMA in use\n"); return; @@ -703,6 +690,7 @@ bcm_sdhci_write_dma(device_t dev, struct sdhci_slot *s struct bcm_sdhci_softc *sc = device_get_softc(slot->bus); size_t left; + /* XXX TODO: Not many-segment safe */ if (sc->dmamap_seg_count != 0) { device_printf(sc->sc_dev, "DMA in use\n"); return; @@ -764,7 +752,30 @@ bcm_sdhci_start_transfer(device_t dev, struct sdhci_sl static void bcm_sdhci_finish_transfer(device_t dev, struct sdhci_slot *slot) { + struct bcm_sdhci_softc *sc = device_get_softc(slot->bus); + /* Clean up */ + if (sc->dmamap_seg_count != 0) { + if (slot->curcmd->data->flags & MMC_DATA_READ) + bus_dmamap_sync(sc->sc_dma_tag, sc->sc_dma_map, + BUS_DMASYNC_POSTREAD); + else + bus_dmamap_sync(sc->sc_dma_tag, sc->sc_dma_map, + BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(sc->sc_dma_tag, sc->sc_dma_map); + + sc->dmamap_seg_count = 0; + sc->dmamap_seg_index = 0; + + slot->intmask |= SDHCI_INT_DATA_AVAIL | + SDHCI_INT_SPACE_AVAIL; + bcm_sdhci_write_4(slot->bus, slot, SDHCI_SIGNAL_ENABLE, + slot->intmask); + } else { + KASSERT((slot->intmask & SDHCI_INT_DATA_AVAIL) != 0 && + (slot->intmask & SDHCI_INT_SPACE_AVAIL) != 0, + ("%s: interrupt mask not restored", __func__)); + } sdhci_finish_data(slot); }