From owner-svn-src-all@freebsd.org Sun Dec 30 23:08:10 2018 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id D06A61438A81; Sun, 30 Dec 2018 23:08:09 +0000 (UTC) (envelope-from marius@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 77F7D71C72; Sun, 30 Dec 2018 23:08:09 +0000 (UTC) (envelope-from marius@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 6A78F1D35; Sun, 30 Dec 2018 23:08:09 +0000 (UTC) (envelope-from marius@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id wBUN89gw084358; Sun, 30 Dec 2018 23:08:09 GMT (envelope-from marius@FreeBSD.org) Received: (from marius@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id wBUN87oG084339; Sun, 30 Dec 2018 23:08:07 GMT (envelope-from marius@FreeBSD.org) Message-Id: <201812302308.wBUN87oG084339@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: marius set sender to marius@FreeBSD.org using -f From: Marius Strobl Date: Sun, 30 Dec 2018 23:08:07 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r342634 - in head/sys: arm/broadcom/bcm2835 arm/nvidia arm/ti dev/sdhci X-SVN-Group: head X-SVN-Commit-Author: marius X-SVN-Commit-Paths: in head/sys: arm/broadcom/bcm2835 arm/nvidia arm/ti dev/sdhci X-SVN-Commit-Revision: 342634 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Rspamd-Queue-Id: 77F7D71C72 X-Spamd-Bar: -- Authentication-Results: mx1.freebsd.org X-Spamd-Result: default: False [-2.96 / 15.00]; local_wl_from(0.00)[FreeBSD.org]; NEURAL_HAM_MEDIUM(-1.00)[-0.999,0]; NEURAL_HAM_LONG(-1.00)[-0.998,0]; NEURAL_HAM_SHORT(-0.96)[-0.964,0]; ASN(0.00)[asn:11403, ipnet:2610:1c1:1::/48, country:US] 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: Sun, 30 Dec 2018 23:08:10 -0000 Author: marius Date: Sun Dec 30 23:08:06 2018 New Revision: 342634 URL: https://svnweb.freebsd.org/changeset/base/342634 Log: o Don't allocate resources for SDMA in sdhci(4) if the controller or the front-end doesn't support SDMA or the latter implements a platform- specific transfer method instead. While at it, factor out allocation and freeing of SDMA resources to sdhci_dma_{alloc,free}() in order to keep the code more readable when adding support for ADMA variants. o Base the size of the SDMA bounce buffer on MAXPHYS up to the maximum of 512 KiB instead of using a fixed 4-KiB-buffer. With the default MAXPHYS of 128 KiB and depending on the controller and medium, this reduces the number of SDHCI interrupts by a factor of ~16 to ~32 on sequential reads while an increase of throughput of up to ~84 % was seen. Front-ends for broken controllers that only support an SDMA buffer boundary of a specific size may set SDHCI_QUIRK_BROKEN_SDMA_BOUNDARY and supply a size via struct sdhci_slot. According to Linux, only Qualcomm MSM-type SDHCI controllers are affected by this, though. Requested by: Shreyank Amartya (unconditional bump to 512 KiB) o Introduce a SDHCI_DEPEND macro for specifying the dependency of the front-end modules on the sdhci(4) one and bump the module version of sdhci(4) to 2 via an also newly introduced SDHCI_VERSION in order to ensure that all components are in sync WRT struct sdhci_slot. o In sdhci(4): - Make pointers const were applicable, - replace a few device_printf(9) calls with slot_printf() for consistency, and - sync some local functions with their prototypes WRT static. Modified: head/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c head/sys/arm/broadcom/bcm2835/bcm2835_sdhost.c head/sys/arm/nvidia/tegra_sdhci.c head/sys/arm/ti/ti_sdhci.c head/sys/dev/sdhci/fsl_sdhci.c head/sys/dev/sdhci/sdhci.c head/sys/dev/sdhci/sdhci.h head/sys/dev/sdhci/sdhci_acpi.c head/sys/dev/sdhci/sdhci_fdt.c head/sys/dev/sdhci/sdhci_pci.c head/sys/dev/sdhci/sdhci_xenon.c Modified: head/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c ============================================================================== --- head/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c Sun Dec 30 23:04:02 2018 (r342633) +++ head/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c Sun Dec 30 23:08:06 2018 (r342634) @@ -683,7 +683,7 @@ static driver_t bcm_sdhci_driver = { DRIVER_MODULE(sdhci_bcm, simplebus, bcm_sdhci_driver, bcm_sdhci_devclass, NULL, NULL); -MODULE_DEPEND(sdhci_bcm, sdhci, 1, 1, 1); +SDHCI_DEPEND(sdhci_bcm); #ifndef MMCCAM MMC_DECLARE_BRIDGE(sdhci_bcm); #endif Modified: head/sys/arm/broadcom/bcm2835/bcm2835_sdhost.c ============================================================================== --- head/sys/arm/broadcom/bcm2835/bcm2835_sdhost.c Sun Dec 30 23:04:02 2018 (r342633) +++ head/sys/arm/broadcom/bcm2835/bcm2835_sdhost.c Sun Dec 30 23:08:06 2018 (r342634) @@ -1287,7 +1287,7 @@ static driver_t bcm_sdhost_driver = { DRIVER_MODULE(sdhost_bcm, simplebus, bcm_sdhost_driver, bcm_sdhost_devclass, NULL, NULL); -MODULE_DEPEND(sdhost_bcm, sdhci, 1, 1, 1); +SDHCI_DEPEND(sdhost_bcm); #ifndef MMCCAM MMC_DECLARE_BRIDGE(sdhost_bcm); #endif Modified: head/sys/arm/nvidia/tegra_sdhci.c ============================================================================== --- head/sys/arm/nvidia/tegra_sdhci.c Sun Dec 30 23:04:02 2018 (r342633) +++ head/sys/arm/nvidia/tegra_sdhci.c Sun Dec 30 23:08:06 2018 (r342634) @@ -465,7 +465,7 @@ static DEFINE_CLASS_0(sdhci, tegra_sdhci_driver, tegra sizeof(struct tegra_sdhci_softc)); DRIVER_MODULE(sdhci_tegra, simplebus, tegra_sdhci_driver, tegra_sdhci_devclass, NULL, NULL); -MODULE_DEPEND(sdhci_tegra, sdhci, 1, 1, 1); +SDHCI_DEPEND(sdhci_tegra); #ifndef MMCCAM MMC_DECLARE_BRIDGE(sdhci); #endif Modified: head/sys/arm/ti/ti_sdhci.c ============================================================================== --- head/sys/arm/ti/ti_sdhci.c Sun Dec 30 23:04:02 2018 (r342633) +++ head/sys/arm/ti/ti_sdhci.c Sun Dec 30 23:08:06 2018 (r342634) @@ -755,7 +755,7 @@ static driver_t ti_sdhci_driver = { DRIVER_MODULE(sdhci_ti, simplebus, ti_sdhci_driver, ti_sdhci_devclass, NULL, NULL); -MODULE_DEPEND(sdhci_ti, sdhci, 1, 1, 1); +SDHCI_DEPEND(sdhci_ti); #ifndef MMCCAM MMC_DECLARE_BRIDGE(sdhci_ti); Modified: head/sys/dev/sdhci/fsl_sdhci.c ============================================================================== --- head/sys/dev/sdhci/fsl_sdhci.c Sun Dec 30 23:04:02 2018 (r342633) +++ head/sys/dev/sdhci/fsl_sdhci.c Sun Dec 30 23:08:06 2018 (r342634) @@ -1005,7 +1005,7 @@ static driver_t fsl_sdhci_driver = { DRIVER_MODULE(sdhci_fsl, simplebus, fsl_sdhci_driver, fsl_sdhci_devclass, NULL, NULL); -MODULE_DEPEND(sdhci_fsl, sdhci, 1, 1, 1); +SDHCI_DEPEND(sdhci_fsl); #ifndef MMCCAM MMC_DECLARE_BRIDGE(sdhci_fsl); Modified: head/sys/dev/sdhci/sdhci.c ============================================================================== --- head/sys/dev/sdhci/sdhci.c Sun Dec 30 23:04:02 2018 (r342633) +++ head/sys/dev/sdhci/sdhci.c Sun Dec 30 23:08:06 2018 (r342634) @@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -108,19 +109,20 @@ static void sdhci_retune(void *arg); static void sdhci_set_clock(struct sdhci_slot *slot, uint32_t clock); static void sdhci_set_power(struct sdhci_slot *slot, u_char power); static void sdhci_set_transfer_mode(struct sdhci_slot *slot, - struct mmc_data *data); + const struct mmc_data *data); static void sdhci_start(struct sdhci_slot *slot); static void sdhci_timeout(void *arg); static void sdhci_start_command(struct sdhci_slot *slot, struct mmc_command *cmd); -static void sdhci_start_data(struct sdhci_slot *slot, struct mmc_data *data); +static void sdhci_start_data(struct sdhci_slot *slot, + const struct mmc_data *data); static void sdhci_write_block_pio(struct sdhci_slot *slot); static void sdhci_transfer_pio(struct sdhci_slot *slot); #ifdef MMCCAM /* CAM-related */ static void sdhci_cam_action(struct cam_sim *sim, union ccb *ccb); -static int sdhci_cam_get_possible_host_clock(struct sdhci_slot *slot, +static int sdhci_cam_get_possible_host_clock(const struct sdhci_slot *slot, int proposed_clock); static void sdhci_cam_handle_mmcio(struct cam_sim *sim, union ccb *ccb); static void sdhci_cam_poll(struct cam_sim *sim); @@ -130,12 +132,14 @@ static int sdhci_cam_update_ios(struct sdhci_slot *slo #endif /* helper routines */ +static int sdhci_dma_alloc(struct sdhci_slot *slot); +static void sdhci_dma_free(struct sdhci_slot *slot); static void sdhci_dumpregs(struct sdhci_slot *slot); static void sdhci_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs, int error); -static int slot_printf(struct sdhci_slot *slot, const char * fmt, ...) +static int slot_printf(const struct sdhci_slot *slot, const char * fmt, ...) __printflike(2, 3); -static uint32_t sdhci_tuning_intmask(struct sdhci_slot *slot); +static uint32_t sdhci_tuning_intmask(const struct sdhci_slot *slot); #define SDHCI_LOCK(_slot) mtx_lock(&(_slot)->mtx) #define SDHCI_UNLOCK(_slot) mtx_unlock(&(_slot)->mtx) @@ -179,7 +183,7 @@ sdhci_getaddr(void *arg, bus_dma_segment_t *segs, int } static int -slot_printf(struct sdhci_slot *slot, const char * fmt, ...) +slot_printf(const struct sdhci_slot *slot, const char * fmt, ...) { va_list ap; int retval; @@ -290,7 +294,7 @@ sdhci_reset(struct sdhci_slot *slot, uint8_t mask) } static uint32_t -sdhci_tuning_intmask(struct sdhci_slot *slot) +sdhci_tuning_intmask(const struct sdhci_slot *slot) { uint32_t intmask; @@ -737,55 +741,94 @@ sdhci_card_poll(void *arg) sdhci_card_poll, slot); } -int -sdhci_init_slot(device_t dev, struct sdhci_slot *slot, int num) +static int +sdhci_dma_alloc(struct sdhci_slot *slot) { - kobjop_desc_t kobj_desc; - kobj_method_t *kobj_method; - uint32_t caps, caps2, freq, host_caps; int err; - SDHCI_LOCK_INIT(slot); + if (!(slot->quirks & SDHCI_QUIRK_BROKEN_SDMA_BOUNDARY)) { + if (MAXPHYS <= 1024 * 4) + slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_4K; + else if (MAXPHYS <= 1024 * 8) + slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_8K; + else if (MAXPHYS <= 1024 * 16) + slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_16K; + else if (MAXPHYS <= 1024 * 32) + slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_32K; + else if (MAXPHYS <= 1024 * 64) + slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_64K; + else if (MAXPHYS <= 1024 * 128) + slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_128K; + else if (MAXPHYS <= 1024 * 256) + slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_256K; + else + slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_512K; + } + slot->sdma_bbufsz = SDHCI_SDMA_BNDRY_TO_BBUFSZ(slot->sdma_boundary); - slot->num = num; - slot->bus = dev; - - /* Allocate DMA tag. */ - err = bus_dma_tag_create(bus_get_dma_tag(dev), - DMA_BLOCK_SIZE, 0, BUS_SPACE_MAXADDR_32BIT, - BUS_SPACE_MAXADDR, NULL, NULL, - DMA_BLOCK_SIZE, 1, DMA_BLOCK_SIZE, - BUS_DMA_ALLOCNOW, NULL, NULL, - &slot->dmatag); + /* + * Allocate the DMA tag for an SDMA bounce buffer. + * Note that the SDHCI specification doesn't state any alignment + * constraint for the SDMA system address. However, controllers + * typically ignore the SDMA boundary bits in SDHCI_DMA_ADDRESS when + * forming the actual address of data, requiring the SDMA buffer to + * be aligned to the SDMA boundary. + */ + err = bus_dma_tag_create(bus_get_dma_tag(slot->bus), slot->sdma_bbufsz, + 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, + slot->sdma_bbufsz, 1, slot->sdma_bbufsz, BUS_DMA_ALLOCNOW, + NULL, NULL, &slot->dmatag); if (err != 0) { - device_printf(dev, "Can't create DMA tag\n"); - SDHCI_LOCK_DESTROY(slot); + slot_printf(slot, "Can't create DMA tag for SDMA\n"); return (err); } - /* Allocate DMA memory. */ + /* Allocate DMA memory for the SDMA bounce buffer. */ err = bus_dmamem_alloc(slot->dmatag, (void **)&slot->dmamem, BUS_DMA_NOWAIT, &slot->dmamap); if (err != 0) { - device_printf(dev, "Can't alloc DMA memory\n"); + slot_printf(slot, "Can't alloc DMA memory for SDMA\n"); bus_dma_tag_destroy(slot->dmatag); - SDHCI_LOCK_DESTROY(slot); return (err); } - /* Map the memory. */ + /* Map the memory of the SDMA bounce buffer. */ err = bus_dmamap_load(slot->dmatag, slot->dmamap, - (void *)slot->dmamem, DMA_BLOCK_SIZE, - sdhci_getaddr, &slot->paddr, 0); + (void *)slot->dmamem, slot->sdma_bbufsz, sdhci_getaddr, + &slot->paddr, 0); if (err != 0 || slot->paddr == 0) { - device_printf(dev, "Can't load DMA memory\n"); + slot_printf(slot, "Can't load DMA memory for SDMA\n"); bus_dmamem_free(slot->dmatag, slot->dmamem, slot->dmamap); bus_dma_tag_destroy(slot->dmatag); - SDHCI_LOCK_DESTROY(slot); if (err) return (err); else return (EFAULT); } + return (0); +} + +static void +sdhci_dma_free(struct sdhci_slot *slot) +{ + + bus_dmamap_unload(slot->dmatag, slot->dmamap); + bus_dmamem_free(slot->dmatag, slot->dmamem, slot->dmamap); + bus_dma_tag_destroy(slot->dmatag); +} + +int +sdhci_init_slot(device_t dev, struct sdhci_slot *slot, int num) +{ + kobjop_desc_t kobj_desc; + kobj_method_t *kobj_method; + uint32_t caps, caps2, freq, host_caps; + int err; + + SDHCI_LOCK_INIT(slot); + + slot->num = num; + slot->bus = dev; + slot->version = (RD2(slot, SDHCI_HOST_VERSION) >> SDHCI_SPEC_VER_SHIFT) & SDHCI_SPEC_VER_MASK; if (slot->quirks & SDHCI_QUIRK_MISSING_CAPS) { @@ -801,12 +844,8 @@ sdhci_init_slot(device_t dev, struct sdhci_slot *slot, if (slot->version >= SDHCI_SPEC_300) { if ((caps & SDHCI_SLOTTYPE_MASK) != SDHCI_SLOTTYPE_REMOVABLE && (caps & SDHCI_SLOTTYPE_MASK) != SDHCI_SLOTTYPE_EMBEDDED) { - device_printf(dev, + slot_printf(slot, "Driver doesn't support shared bus slots\n"); - bus_dmamap_unload(slot->dmatag, slot->dmamap); - bus_dmamem_free(slot->dmatag, slot->dmamem, - slot->dmamap); - bus_dma_tag_destroy(slot->dmatag); SDHCI_LOCK_DESTROY(slot); return (ENXIO); } else if ((caps & SDHCI_SLOTTYPE_MASK) == @@ -830,7 +869,7 @@ sdhci_init_slot(device_t dev, struct sdhci_slot *slot, */ if (slot->max_clk == 0) { slot->max_clk = SDHCI_DEFAULT_MAX_FREQ * 1000000; - device_printf(dev, "Hardware doesn't specify base clock " + slot_printf(slot, "Hardware doesn't specify base clock " "frequency, using %dMHz as default.\n", SDHCI_DEFAULT_MAX_FREQ); } @@ -851,7 +890,7 @@ sdhci_init_slot(device_t dev, struct sdhci_slot *slot, * max timeout, but still mention it. */ if (slot->timeout_clk == 0) { - device_printf(dev, "Hardware doesn't specify timeout clock " + slot_printf(slot, "Hardware doesn't specify timeout clock " "frequency, setting BROKEN_TIMEOUT quirk.\n"); slot->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; } @@ -867,7 +906,7 @@ sdhci_init_slot(device_t dev, struct sdhci_slot *slot, if ((caps & SDHCI_CAN_VDD_180) && (slot->opt & SDHCI_SLOT_EMBEDDED)) slot->host.host_ocr |= MMC_OCR_LOW_VOLTAGE; if (slot->host.host_ocr == 0) { - device_printf(dev, "Hardware doesn't report any " + slot_printf(slot, "Hardware doesn't report any " "support voltages.\n"); } @@ -953,7 +992,7 @@ no_tuning: slot->retune_count = (caps2 & SDHCI_RETUNE_CNT_MASK) >> SDHCI_RETUNE_CNT_SHIFT; if (slot->retune_count > 0xb) { - device_printf(dev, "Unknown re-tuning count " + slot_printf(slot, "Unknown re-tuning count " "%x, using 1 sec\n", slot->retune_count); slot->retune_count = 1; } else if (slot->retune_count != 0) @@ -1012,6 +1051,19 @@ no_tuning: if (slot->opt & SDHCI_PLATFORM_TRANSFER) slot->opt &= ~SDHCI_HAVE_DMA; + if (slot->opt & SDHCI_HAVE_DMA) { + err = sdhci_dma_alloc(slot); + if (err != 0) { + if (slot->opt & SDHCI_TUNING_SUPPORTED) { + free(slot->tune_req, M_DEVBUF); + free(slot->tune_cmd, M_DEVBUF); + free(slot->tune_data, M_DEVBUF); + } + SDHCI_LOCK_DESTROY(slot); + return (err); + } + } + if (bootverbose || sdhci_debug) { slot_printf(slot, "%uMHz%s %s VDD:%s%s%s VCCQ: 3.3V%s%s DRV: B%s%s%s %s %s\n", @@ -1109,9 +1161,8 @@ sdhci_cleanup_slot(struct sdhci_slot *slot) SDHCI_LOCK(slot); sdhci_reset(slot, SDHCI_RESET_ALL); SDHCI_UNLOCK(slot); - bus_dmamap_unload(slot->dmatag, slot->dmamap); - bus_dmamem_free(slot->dmatag, slot->dmamem, slot->dmamap); - bus_dma_tag_destroy(slot->dmatag); + if (slot->opt & SDHCI_HAVE_DMA) + sdhci_dma_free(slot); if (slot->opt & SDHCI_TUNING_SUPPORTED) { free(slot->tune_req, M_DEVBUF); free(slot->tune_cmd, M_DEVBUF); @@ -1175,7 +1226,7 @@ sdhci_generic_get_card_present(device_t brdev __unused void sdhci_generic_set_uhs_timing(device_t brdev __unused, struct sdhci_slot *slot) { - struct mmc_ios *ios; + const struct mmc_ios *ios; uint16_t hostctrl2; if (slot->version < SDHCI_SPEC_300) @@ -1308,7 +1359,7 @@ int sdhci_generic_tune(device_t brdev __unused, device_t reqdev, bool hs400) { struct sdhci_slot *slot = device_get_ivars(reqdev); - struct mmc_ios *ios = &slot->host.ios; + const struct mmc_ios *ios = &slot->host.ios; struct mmc_command *tune_cmd; struct mmc_data *tune_data; uint32_t opcode; @@ -1564,7 +1615,7 @@ sdhci_timeout(void *arg) } static void -sdhci_set_transfer_mode(struct sdhci_slot *slot, struct mmc_data *data) +sdhci_set_transfer_mode(struct sdhci_slot *slot, const struct mmc_data *data) { uint16_t mode; @@ -1766,9 +1817,9 @@ sdhci_finish_command(struct sdhci_slot *slot) } static void -sdhci_start_data(struct sdhci_slot *slot, struct mmc_data *data) +sdhci_start_data(struct sdhci_slot *slot, const struct mmc_data *data) { - uint32_t target_timeout, current_timeout; + uint32_t blkcnt, blksz, current_timeout, sdma_bbufsz, target_timeout; uint8_t div; if (data == NULL && (slot->curcmd->flags & MMC_RSP_BUSY) == 0) { @@ -1804,7 +1855,7 @@ sdhci_start_data(struct sdhci_slot *slot, struct mmc_d /* Use DMA if possible. */ if ((slot->opt & SDHCI_HAVE_DMA)) slot->flags |= SDHCI_USE_DMA; - /* If data is small, broken DMA may return zeroes instead of data, */ + /* If data is small, broken DMA may return zeroes instead of data. */ if ((slot->quirks & SDHCI_QUIRK_BROKEN_TIMINGS) && (data->len <= 512)) slot->flags &= ~SDHCI_USE_DMA; @@ -1814,20 +1865,22 @@ sdhci_start_data(struct sdhci_slot *slot, struct mmc_d slot->flags &= ~SDHCI_USE_DMA; /* Load DMA buffer. */ if (slot->flags & SDHCI_USE_DMA) { + sdma_bbufsz = slot->sdma_bbufsz; if (data->flags & MMC_DATA_READ) bus_dmamap_sync(slot->dmatag, slot->dmamap, BUS_DMASYNC_PREREAD); else { - memcpy(slot->dmamem, data->data, - (data->len < DMA_BLOCK_SIZE) ? - data->len : DMA_BLOCK_SIZE); + memcpy(slot->dmamem, data->data, ulmin(data->len, + sdma_bbufsz)); bus_dmamap_sync(slot->dmatag, slot->dmamap, BUS_DMASYNC_PREWRITE); } WR4(slot, SDHCI_DMA_ADDRESS, slot->paddr); - /* Interrupt aggregation: Mask border interrupt - * for the last page and unmask else. */ - if (data->len == DMA_BLOCK_SIZE) + /* + * Interrupt aggregation: Mask border interrupt for the last + * bounce buffer and unmask otherwise. + */ + if (data->len == sdma_bbufsz) slot->intmask &= ~SDHCI_INT_DMA_END; else slot->intmask |= SDHCI_INT_DMA_END; @@ -1835,16 +1888,15 @@ sdhci_start_data(struct sdhci_slot *slot, struct mmc_d } /* Current data offset for both PIO and DMA. */ slot->offset = 0; - /* Set block size and request IRQ on 4K border. */ - WR2(slot, SDHCI_BLOCK_SIZE, SDHCI_MAKE_BLKSZ(DMA_BOUNDARY, - (data->len < 512) ? data->len : 512)); + /* Set block size and request border interrupts on the SDMA boundary. */ + blksz = SDHCI_MAKE_BLKSZ(slot->sdma_boundary, ulmin(data->len, 512)); + WR2(slot, SDHCI_BLOCK_SIZE, blksz); /* Set block count. */ - WR2(slot, SDHCI_BLOCK_COUNT, (data->len + 511) / 512); - + blkcnt = howmany(data->len, 512); + WR2(slot, SDHCI_BLOCK_COUNT, blkcnt); if (__predict_false(sdhci_debug > 1)) - slot_printf(slot, "Block size: %02x, count %lu\n", - (unsigned int)SDHCI_MAKE_BLKSZ(DMA_BOUNDARY, (data->len < 512) ? data->len : 512), - (unsigned long)(data->len + 511) / 512); + slot_printf(slot, "Blk size: 0x%08x | Blk cnt: 0x%08x\n", + blksz, blkcnt); } void @@ -1868,7 +1920,7 @@ sdhci_finish_data(struct sdhci_slot *slot) bus_dmamap_sync(slot->dmatag, slot->dmamap, BUS_DMASYNC_POSTREAD); memcpy((u_char*)data->data + slot->offset, slot->dmamem, - (left < DMA_BLOCK_SIZE) ? left : DMA_BLOCK_SIZE); + ulmin(left, slot->sdma_bbufsz)); } else bus_dmamap_sync(slot->dmatag, slot->dmamap, BUS_DMASYNC_POSTWRITE); @@ -1892,15 +1944,14 @@ sdhci_finish_data(struct sdhci_slot *slot) static void sdhci_start(struct sdhci_slot *slot) { - union ccb *ccb; + union ccb *ccb; + struct ccb_mmcio *mmcio; ccb = slot->ccb; if (ccb == NULL) return; - struct ccb_mmcio *mmcio; mmcio = &ccb->mmcio; - if (!(slot->flags & CMD_STARTED)) { slot->flags |= CMD_STARTED; sdhci_start_command(slot, &mmcio->cmd); @@ -1932,7 +1983,7 @@ sdhci_start(struct sdhci_slot *slot) static void sdhci_start(struct sdhci_slot *slot) { - struct mmc_request *req; + const struct mmc_request *req; req = slot->req; if (req == NULL) @@ -2061,6 +2112,7 @@ sdhci_data_irq(struct sdhci_slot *slot, uint32_t intma { struct mmc_data *data; size_t left; + uint32_t sdma_bbufsz; if (!slot->curcmd) { slot_printf(slot, "Got data interrupt 0x%08x, but " @@ -2115,6 +2167,7 @@ sdhci_data_irq(struct sdhci_slot *slot, uint32_t intma /* Handle DMA border. */ if (intmask & SDHCI_INT_DMA_END) { data = slot->curcmd->data; + sdma_bbufsz = slot->sdma_bbufsz; /* Unload DMA buffer ... */ left = data->len - slot->offset; @@ -2122,26 +2175,28 @@ sdhci_data_irq(struct sdhci_slot *slot, uint32_t intma bus_dmamap_sync(slot->dmatag, slot->dmamap, BUS_DMASYNC_POSTREAD); memcpy((u_char*)data->data + slot->offset, slot->dmamem, - (left < DMA_BLOCK_SIZE) ? left : DMA_BLOCK_SIZE); + ulmin(left, sdma_bbufsz)); } else { bus_dmamap_sync(slot->dmatag, slot->dmamap, BUS_DMASYNC_POSTWRITE); } /* ... and reload it again. */ - slot->offset += DMA_BLOCK_SIZE; + slot->offset += sdma_bbufsz; left = data->len - slot->offset; if (data->flags & MMC_DATA_READ) { bus_dmamap_sync(slot->dmatag, slot->dmamap, BUS_DMASYNC_PREREAD); } else { memcpy(slot->dmamem, (u_char*)data->data + slot->offset, - (left < DMA_BLOCK_SIZE)? left : DMA_BLOCK_SIZE); + ulmin(left, sdma_bbufsz)); bus_dmamap_sync(slot->dmatag, slot->dmamap, BUS_DMASYNC_PREWRITE); } - /* Interrupt aggregation: Mask border interrupt - * for the last page. */ - if (left == DMA_BLOCK_SIZE) { + /* + * Interrupt aggregation: Mask border interrupt for the last + * bounce buffer. + */ + if (left == sdma_bbufsz) { slot->intmask &= ~SDHCI_INT_DMA_END; WR4(slot, SDHCI_SIGNAL_ENABLE, slot->intmask); } @@ -2264,7 +2319,7 @@ int sdhci_generic_read_ivar(device_t bus, device_t child, int which, uintptr_t *result) { - struct sdhci_slot *slot = device_get_ivars(child); + const struct sdhci_slot *slot = device_get_ivars(child); switch (which) { default: @@ -2427,6 +2482,7 @@ sdhci_generic_write_ivar(device_t bus, device_t child, void sdhci_start_slot(struct sdhci_slot *slot) { + if ((slot->devq = cam_simq_alloc(1)) == NULL) { goto fail; } @@ -2586,7 +2642,8 @@ sdhci_cam_poll(struct cam_sim *sim) } static int -sdhci_cam_get_possible_host_clock(struct sdhci_slot *slot, int proposed_clock) +sdhci_cam_get_possible_host_clock(const struct sdhci_slot *slot, + int proposed_clock) { int max_clock, clock, i; @@ -2613,15 +2670,14 @@ sdhci_cam_get_possible_host_clock(struct sdhci_slot *s return clock; } -int +static int sdhci_cam_settran_settings(struct sdhci_slot *slot, union ccb *ccb) { struct mmc_ios *ios; - struct mmc_ios *new_ios; - struct ccb_trans_settings_mmc *cts; + const struct mmc_ios *new_ios; + const struct ccb_trans_settings_mmc *cts; ios = &slot->host.ios; - cts = &ccb->cts.proto_specific.mmc; new_ios = &cts->ios; @@ -2659,7 +2715,7 @@ sdhci_cam_settran_settings(struct sdhci_slot *slot, un return (sdhci_cam_update_ios(slot)); } -int +static int sdhci_cam_update_ios(struct sdhci_slot *slot) { struct mmc_ios *ios = &slot->host.ios; @@ -2701,10 +2757,10 @@ sdhci_cam_update_ios(struct sdhci_slot *slot) return (0); } -int +static int sdhci_cam_request(struct sdhci_slot *slot, union ccb *ccb) { - struct ccb_mmcio *mmcio; + const struct ccb_mmcio *mmcio; mmcio = &ccb->mmcio; @@ -2739,4 +2795,4 @@ sdhci_cam_request(struct sdhci_slot *slot, union ccb * } #endif /* MMCCAM */ -MODULE_VERSION(sdhci, 1); +MODULE_VERSION(sdhci, SDHCI_VERSION); Modified: head/sys/dev/sdhci/sdhci.h ============================================================================== --- head/sys/dev/sdhci/sdhci.h Sun Dec 30 23:04:02 2018 (r342633) +++ head/sys/dev/sdhci/sdhci.h Sun Dec 30 23:08:06 2018 (r342634) @@ -32,8 +32,8 @@ #include "opt_mmccam.h" -#define DMA_BLOCK_SIZE 4096 -#define DMA_BOUNDARY 0 /* DMA reload every 4K */ +/* Macro for sizing the SDMA bounce buffer on the SDMA buffer boundary. */ +#define SDHCI_SDMA_BNDRY_TO_BBUFSZ(bndry) (4096 * (1 << bndry)) /* Controller doesn't honor resets unless we touch the clock register */ #define SDHCI_QUIRK_CLOCK_BEFORE_RESET (1 << 0) @@ -95,6 +95,8 @@ #define SDHCI_QUIRK_BROKEN_AUTO_STOP (1 << 28) /* Controller supports eMMC HS400 mode if SDHCI_CAN_SDR104 is set. */ #define SDHCI_QUIRK_MMC_HS400_IF_CAN_SDR104 (1 << 29) +/* SDMA boundary in SDHCI_BLOCK_SIZE broken - use front-end supplied value. */ +#define SDHCI_QUIRK_BROKEN_SDMA_BOUNDARY (1 << 30) /* * Controller registers @@ -102,6 +104,14 @@ #define SDHCI_DMA_ADDRESS 0x00 #define SDHCI_BLOCK_SIZE 0x04 +#define SDHCI_BLKSZ_SDMA_BNDRY_4K 0x00 +#define SDHCI_BLKSZ_SDMA_BNDRY_8K 0x01 +#define SDHCI_BLKSZ_SDMA_BNDRY_16K 0x02 +#define SDHCI_BLKSZ_SDMA_BNDRY_32K 0x03 +#define SDHCI_BLKSZ_SDMA_BNDRY_64K 0x04 +#define SDHCI_BLKSZ_SDMA_BNDRY_128K 0x05 +#define SDHCI_BLKSZ_SDMA_BNDRY_256K 0x06 +#define SDHCI_BLKSZ_SDMA_BNDRY_512K 0x07 #define SDHCI_MAKE_BLKSZ(dma, blksz) (((dma & 0x7) << 12) | (blksz & 0xFFF)) #define SDHCI_BLOCK_COUNT 0x06 @@ -362,6 +372,8 @@ struct sdhci_slot { bus_dmamap_t dmamap; u_char *dmamem; bus_addr_t paddr; /* DMA buffer address */ + uint32_t sdma_bbufsz; /* SDMA bounce buffer size */ + uint8_t sdma_boundary; /* SDMA boundary */ struct task card_task; /* Card presence check task */ struct timeout_task card_delayed_task;/* Card insert delayed task */ @@ -433,5 +445,10 @@ uint32_t sdhci_generic_min_freq(device_t brdev, struct bool sdhci_generic_get_card_present(device_t brdev, struct sdhci_slot *slot); void sdhci_generic_set_uhs_timing(device_t brdev, struct sdhci_slot *slot); void sdhci_handle_card_present(struct sdhci_slot *slot, bool is_present); + +#define SDHCI_VERSION 2 + +#define SDHCI_DEPEND(name) \ + MODULE_DEPEND(name, sdhci, SDHCI_VERSION, SDHCI_VERSION, SDHCI_VERSION); #endif /* __SDHCI_H__ */ Modified: head/sys/dev/sdhci/sdhci_acpi.c ============================================================================== --- head/sys/dev/sdhci/sdhci_acpi.c Sun Dec 30 23:04:02 2018 (r342633) +++ head/sys/dev/sdhci/sdhci_acpi.c Sun Dec 30 23:08:06 2018 (r342634) @@ -457,7 +457,7 @@ static devclass_t sdhci_acpi_devclass; DRIVER_MODULE(sdhci_acpi, acpi, sdhci_acpi_driver, sdhci_acpi_devclass, NULL, NULL); -MODULE_DEPEND(sdhci_acpi, sdhci, 1, 1, 1); +SDHCI_DEPEND(sdhci_acpi); #ifndef MMCCAM MMC_DECLARE_BRIDGE(sdhci_acpi); Modified: head/sys/dev/sdhci/sdhci_fdt.c ============================================================================== --- head/sys/dev/sdhci/sdhci_fdt.c Sun Dec 30 23:04:02 2018 (r342633) +++ head/sys/dev/sdhci/sdhci_fdt.c Sun Dec 30 23:08:06 2018 (r342634) @@ -80,6 +80,7 @@ struct sdhci_fdt_softc { u_int quirks; /* Chip specific quirks */ u_int caps; /* If we override SDHCI_CAPABILITIES */ uint32_t max_clk; /* Max possible freq */ + uint8_t sdma_boundary; /* If we override the SDMA boundary */ struct resource *irq_res; /* IRQ resource */ void *intrhand; /* Interrupt handle */ @@ -206,7 +207,9 @@ sdhci_fdt_probe(device_t dev) device_set_desc(dev, "generic fdt SDHCI controller"); break; case SDHCI_FDT_QUALCOMM: - sc->quirks = SDHCI_QUIRK_ALL_SLOTS_NON_REMOVABLE; + sc->quirks = SDHCI_QUIRK_ALL_SLOTS_NON_REMOVABLE | + SDHCI_QUIRK_BROKEN_SDMA_BOUNDARY; + sc->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_4K; device_set_desc(dev, "Qualcomm FDT SDHCI controller"); break; case SDHCI_FDT_XLNX_ZY7: @@ -271,6 +274,7 @@ sdhci_fdt_attach(device_t dev) slot->quirks = sc->quirks; slot->caps = sc->caps; slot->max_clk = sc->max_clk; + slot->sdma_boundary = sc->sdma_boundary; if (sdhci_init_slot(dev, slot, i) != 0) continue; @@ -353,7 +357,7 @@ static devclass_t sdhci_fdt_devclass; DRIVER_MODULE(sdhci_fdt, simplebus, sdhci_fdt_driver, sdhci_fdt_devclass, NULL, NULL); -MODULE_DEPEND(sdhci_fdt, sdhci, 1, 1, 1); +SDHCI_DEPEND(sdhci_fdt); #ifndef MMCCAM MMC_DECLARE_BRIDGE(sdhci_fdt); #endif Modified: head/sys/dev/sdhci/sdhci_pci.c ============================================================================== --- head/sys/dev/sdhci/sdhci_pci.c Sun Dec 30 23:04:02 2018 (r342633) +++ head/sys/dev/sdhci/sdhci_pci.c Sun Dec 30 23:08:06 2018 (r342634) @@ -526,7 +526,7 @@ static devclass_t sdhci_pci_devclass; DRIVER_MODULE(sdhci_pci, pci, sdhci_pci_driver, sdhci_pci_devclass, NULL, NULL); -MODULE_DEPEND(sdhci_pci, sdhci, 1, 1, 1); +SDHCI_DEPEND(sdhci_pci); #ifndef MMCCAM MMC_DECLARE_BRIDGE(sdhci_pci); Modified: head/sys/dev/sdhci/sdhci_xenon.c ============================================================================== --- head/sys/dev/sdhci/sdhci_xenon.c Sun Dec 30 23:04:02 2018 (r342633) +++ head/sys/dev/sdhci/sdhci_xenon.c Sun Dec 30 23:08:06 2018 (r342634) @@ -550,7 +550,7 @@ static devclass_t sdhci_xenon_devclass; DRIVER_MODULE(sdhci_xenon, simplebus, sdhci_xenon_driver, sdhci_xenon_devclass, NULL, NULL); -MODULE_DEPEND(sdhci_xenon, sdhci, 1, 1, 1); +SDHCI_DEPEND(sdhci_xenon); #ifndef MMCCAM MMC_DECLARE_BRIDGE(sdhci_xenon); #endif