From: David Brownell <[email protected]>

Simplify mmc_davinci_send_dma_request() by relying on constraints
provided through its call stack.  Document those constraints a bit
better.

Lift the unnecessary constraint that blocks not cross scatterlist
segments.  If we handle multi-segment transfers at all, there's no
need for such a restriction.

(This is a code shrink that *should* change no behavior.)

Signed-off-by: David Brownell <[email protected]>
---
 drivers/mmc/host/davinci_mmc.c |   58 ++++++++++++++-------------------------
 1 file changed, 21 insertions(+), 37 deletions(-)

--- a/drivers/mmc/host/davinci_mmc.c
+++ b/drivers/mmc/host/davinci_mmc.c
@@ -442,7 +442,9 @@ static int mmc_davinci_send_dma_request(
 {
        int sync_dev;
        unsigned char i, j;
-       u16             acnt, bcnt, ccnt;
+       const u16       acnt = 4;
+       const u16       bcnt = rw_threshold >> 2;
+       u16             ccnt;
        u32             src_port, dst_port;
        s16             src_bidx, dst_bidx;
        s16             src_cidx, dst_cidx;
@@ -451,34 +453,11 @@ static int mmc_davinci_send_dma_request(
        struct scatterlist *sg = &data->sg[0];
        unsigned        count = sg_dma_len(sg);
 
-       if ((data->blocks == 1) && (count > data->blksz))
-               count = data->blksz;
-
-       if ((count & (rw_threshold - 1)) == 0) {
-               /* This should always be true due to an earlier check */
-               acnt = 4;
-               bcnt = rw_threshold >> 2;
-               ccnt = count >> ((rw_threshold == 32) ? 5 : 4);
-       } else if (count < rw_threshold) {
-               if ((count&3) == 0) {
-                       acnt = 4;
-                       bcnt = count>>2;
-               } else if ((count&1) == 0) {
-                       acnt = 2;
-                       bcnt = count>>1;
-               } else {
-                       acnt = 1;
-                       bcnt = count;
-               }
-               ccnt = 1;
-       } else {
-               acnt = 4;
-               bcnt = rw_threshold >> 2;
-               ccnt = count >> ((rw_threshold == 32) ? 5 : 4);
-               dev_warn(mmc_dev(host->mmc),
-                       "MMC: count of 0x%x unsupported, truncating transfer\n",
-                       count);
-       }
+       /* If this scatterlist segment (e.g. one page) is bigger than
+        * the transfer (e.g. a block) don't use the whole segment.
+        */
+       if (count > host->bytes_left)
+               count = host->bytes_left;
 
        /*
         * A-B Sync transfer:  each DMA request is for one "frame" of
@@ -490,6 +469,8 @@ static int mmc_davinci_send_dma_request(
         * The FIFOs are read/written in 4-byte chunks (acnt == 4) and
         * EDMA will optimize memory operations to use larger bursts.
         */
+       ccnt = count >> ((rw_threshold == 32) ? 5 : 4);
+
        if (host->data_dir == DAVINCI_MMC_DATADIR_WRITE) {
                sync_dev = host->txdma;
 
@@ -567,9 +548,6 @@ static int mmc_davinci_send_dma_request(
                        edma_chan_num = host->edma_ch_details.chanel_num[0];
 
                        count = sg_dma_len(sg);
-                       if ((data->blocks == 1) && (count > data->blksz))
-                               count = data->blksz;
-
                        ccnt = count >> ((rw_threshold == 32) ? 5 : 4);
 
                        if (sync_dev == host->txdma)
@@ -608,7 +586,7 @@ static int mmc_davinci_start_dma_transfe
                                ? DMA_TO_DEVICE
                                : DMA_FROM_DEVICE));
 
-       /* Decide if we can use DMA */
+       /* no individual DMA segment should need a partial FIFO */
        for (i = 0; i < host->sg_len; i++) {
                if (sg_dma_len(data->sg + i) & mask) {
                        dma_unmap_sg(mmc_dev(host->mmc),
@@ -706,7 +684,7 @@ static void
 mmc_davinci_prepare_data(struct mmc_davinci_host *host, struct mmc_request 
*req)
 {
        int fifo_lev = (rw_threshold == 32) ? MMCFIFOCTL_FIFOLEV : 0;
-       int timeout, sg_len;
+       int timeout;
 
        host->data = req->data;
        if (req->data == NULL) {
@@ -760,11 +738,17 @@ mmc_davinci_prepare_data(struct mmc_davi
                break;
        }
 
-       sg_len = (req->data->blocks == 1) ? 1 : req->data->sg_len;
-       host->sg_len = sg_len;
-
+       host->sg_len = req->data->sg_len;
        host->bytes_left = req->data->blocks * req->data->blksz;
 
+       /* For now we try to use DMA whenever we won't need partial FIFO
+        * reads or writes, either for the whole transfer (as tested here)
+        * or for any individual scatterlist segment (tested when we call
+        * start_dma_transfer).
+        *
+        * While we *could* change that, unusual block sizes are rarely
+        * used.  The occasional fallback to PIO should't hurt.
+        */
        if (host->use_dma && (host->bytes_left & (rw_threshold - 1)) == 0
                        && mmc_davinci_start_dma_transfer(host, req) == 0) {
                host->buffer = NULL;

_______________________________________________
Davinci-linux-open-source mailing list
[email protected]
http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source

Reply via email to