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 <sys/conf.h>
 #include <sys/kernel.h>
 #include <sys/kobj.h>
+#include <sys/libkern.h>
 #include <sys/lock.h>
 #include <sys/malloc.h>
 #include <sys/module.h>
@@ -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
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to