]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
net: ethernet: ti: davinci_cpdma: add dma mapped submit
authorIvan Khoronzhuk <ivan.khoronzhuk@linaro.org>
Mon, 8 Jul 2019 21:34:29 +0000 (00:34 +0300)
committerDavid S. Miller <davem@davemloft.net>
Mon, 8 Jul 2019 21:58:04 +0000 (14:58 -0700)
In case if dma mapped packet needs to be sent, like with XDP
page pool, the "mapped" submit can be used. This patch adds dma
mapped submit based on regular one.

Signed-off-by: Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/ti/davinci_cpdma.c
drivers/net/ethernet/ti/davinci_cpdma.h

index 5cf1758d425bd1717270f5f785b1e9f8788342c8..4e693c3aab27fead9698e1ad9f9dcfd6e45c2235 100644 (file)
@@ -139,6 +139,7 @@ struct submit_info {
        int directed;
        void *token;
        void *data;
+       int flags;
        int len;
 };
 
@@ -184,6 +185,8 @@ static struct cpdma_control_info controls[] = {
                                 (directed << CPDMA_TO_PORT_SHIFT));    \
        } while (0)
 
+#define CPDMA_DMA_EXT_MAP              BIT(16)
+
 static void cpdma_desc_pool_destroy(struct cpdma_ctlr *ctlr)
 {
        struct cpdma_desc_pool *pool = ctlr->pool;
@@ -1015,6 +1018,7 @@ static int cpdma_chan_submit_si(struct submit_info *si)
        struct cpdma_chan               *chan = si->chan;
        struct cpdma_ctlr               *ctlr = chan->ctlr;
        int                             len = si->len;
+       int                             swlen = len;
        struct cpdma_desc __iomem       *desc;
        dma_addr_t                      buffer;
        u32                             mode;
@@ -1036,16 +1040,22 @@ static int cpdma_chan_submit_si(struct submit_info *si)
                chan->stats.runt_transmit_buff++;
        }
 
-       buffer = dma_map_single(ctlr->dev, si->data, len, chan->dir);
-       ret = dma_mapping_error(ctlr->dev, buffer);
-       if (ret) {
-               cpdma_desc_free(ctlr->pool, desc, 1);
-               return -EINVAL;
-       }
-
        mode = CPDMA_DESC_OWNER | CPDMA_DESC_SOP | CPDMA_DESC_EOP;
        cpdma_desc_to_port(chan, mode, si->directed);
 
+       if (si->flags & CPDMA_DMA_EXT_MAP) {
+               buffer = (dma_addr_t)si->data;
+               dma_sync_single_for_device(ctlr->dev, buffer, len, chan->dir);
+               swlen |= CPDMA_DMA_EXT_MAP;
+       } else {
+               buffer = dma_map_single(ctlr->dev, si->data, len, chan->dir);
+               ret = dma_mapping_error(ctlr->dev, buffer);
+               if (ret) {
+                       cpdma_desc_free(ctlr->pool, desc, 1);
+                       return -EINVAL;
+               }
+       }
+
        /* Relaxed IO accessors can be used here as there is read barrier
         * at the end of write sequence.
         */
@@ -1055,7 +1065,7 @@ static int cpdma_chan_submit_si(struct submit_info *si)
        writel_relaxed(mode | len, &desc->hw_mode);
        writel_relaxed((uintptr_t)si->token, &desc->sw_token);
        writel_relaxed(buffer, &desc->sw_buffer);
-       writel_relaxed(len, &desc->sw_len);
+       writel_relaxed(swlen, &desc->sw_len);
        desc_read(desc, sw_len);
 
        __cpdma_chan_submit(chan, desc);
@@ -1079,6 +1089,32 @@ int cpdma_chan_idle_submit(struct cpdma_chan *chan, void *token, void *data,
        si.data = data;
        si.len = len;
        si.directed = directed;
+       si.flags = 0;
+
+       spin_lock_irqsave(&chan->lock, flags);
+       if (chan->state == CPDMA_STATE_TEARDOWN) {
+               spin_unlock_irqrestore(&chan->lock, flags);
+               return -EINVAL;
+       }
+
+       ret = cpdma_chan_submit_si(&si);
+       spin_unlock_irqrestore(&chan->lock, flags);
+       return ret;
+}
+
+int cpdma_chan_idle_submit_mapped(struct cpdma_chan *chan, void *token,
+                                 dma_addr_t data, int len, int directed)
+{
+       struct submit_info si;
+       unsigned long flags;
+       int ret;
+
+       si.chan = chan;
+       si.token = token;
+       si.data = (void *)data;
+       si.len = len;
+       si.directed = directed;
+       si.flags = CPDMA_DMA_EXT_MAP;
 
        spin_lock_irqsave(&chan->lock, flags);
        if (chan->state == CPDMA_STATE_TEARDOWN) {
@@ -1103,6 +1139,32 @@ int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data,
        si.data = data;
        si.len = len;
        si.directed = directed;
+       si.flags = 0;
+
+       spin_lock_irqsave(&chan->lock, flags);
+       if (chan->state != CPDMA_STATE_ACTIVE) {
+               spin_unlock_irqrestore(&chan->lock, flags);
+               return -EINVAL;
+       }
+
+       ret = cpdma_chan_submit_si(&si);
+       spin_unlock_irqrestore(&chan->lock, flags);
+       return ret;
+}
+
+int cpdma_chan_submit_mapped(struct cpdma_chan *chan, void *token,
+                            dma_addr_t data, int len, int directed)
+{
+       struct submit_info si;
+       unsigned long flags;
+       int ret;
+
+       si.chan = chan;
+       si.token = token;
+       si.data = (void *)data;
+       si.len = len;
+       si.directed = directed;
+       si.flags = CPDMA_DMA_EXT_MAP;
 
        spin_lock_irqsave(&chan->lock, flags);
        if (chan->state != CPDMA_STATE_ACTIVE) {
@@ -1140,10 +1202,17 @@ static void __cpdma_chan_free(struct cpdma_chan *chan,
        uintptr_t                       token;
 
        token      = desc_read(desc, sw_token);
-       buff_dma   = desc_read(desc, sw_buffer);
        origlen    = desc_read(desc, sw_len);
 
-       dma_unmap_single(ctlr->dev, buff_dma, origlen, chan->dir);
+       buff_dma   = desc_read(desc, sw_buffer);
+       if (origlen & CPDMA_DMA_EXT_MAP) {
+               origlen &= ~CPDMA_DMA_EXT_MAP;
+               dma_sync_single_for_cpu(ctlr->dev, buff_dma, origlen,
+                                       chan->dir);
+       } else {
+               dma_unmap_single(ctlr->dev, buff_dma, origlen, chan->dir);
+       }
+
        cpdma_desc_free(pool, desc, 1);
        (*chan->handler)((void *)token, outlen, status);
 }
index 9343c8c73c1baea28253c3a1630c7153d437635d..0271a20c2e090117392a0227c12efa664aad8e35 100644 (file)
@@ -77,8 +77,12 @@ int cpdma_chan_stop(struct cpdma_chan *chan);
 
 int cpdma_chan_get_stats(struct cpdma_chan *chan,
                         struct cpdma_chan_stats *stats);
+int cpdma_chan_submit_mapped(struct cpdma_chan *chan, void *token,
+                            dma_addr_t data, int len, int directed);
 int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data,
                      int len, int directed);
+int cpdma_chan_idle_submit_mapped(struct cpdma_chan *chan, void *token,
+                                 dma_addr_t data, int len, int directed);
 int cpdma_chan_idle_submit(struct cpdma_chan *chan, void *token, void *data,
                           int len, int directed);
 int cpdma_chan_process(struct cpdma_chan *chan, int quota);