[PATCH v9 net-next 2/5] net: ethernet: ti: davinci_cpdma: add dma mapped submit

2019-07-08 Thread Ivan Khoronzhuk
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 
---

v8..v9:
- fix warnings on arm64 caused by typos in type casting

 drivers/net/ethernet/ti/davinci_cpdma.c | 89 ++---
 drivers/net/ethernet/ti/davinci_cpdma.h |  4 ++
 2 files changed, 83 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ethernet/ti/davinci_cpdma.c 
b/drivers/net/ethernet/ti/davinci_cpdma.c
index 5cf1758d425b..4e693c3aab27 100644
--- a/drivers/net/ethernet/ti/davinci_cpdma.c
+++ b/drivers/net/ethernet/ti/davinci_cpdma.c
@@ -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, >hw_mode);
writel_relaxed((uintptr_t)si->token, >sw_token);
writel_relaxed(buffer, >sw_buffer);
-   writel_relaxed(len, >sw_len);
+   writel_relaxed(swlen, >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(>lock, flags);
+   if (chan->state == CPDMA_STATE_TEARDOWN) {
+   spin_unlock_irqrestore(>lock, flags);
+   return -EINVAL;
+   }
+
+   ret = cpdma_chan_submit_si();
+   spin_unlock_irqrestore(>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(>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(>lock, flags);
+   if (chan->state != CPDMA_STATE_ACTIVE) {
+   spin_unlock_irqrestore(>lock, flags);
+   return -EINVAL;
+   }
+
+   ret = cpdma_chan_submit_si();
+   spin_unlock_irqrestore(>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 = 

[PATCH v9 net-next 2/5] net: ethernet: ti: davinci_cpdma: add dma mapped submit

2019-07-05 Thread Ivan Khoronzhuk
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 
---

v9..v8
- fix potential warnings on arm64 caused by typos in type casting

 drivers/net/ethernet/ti/davinci_cpdma.c | 89 ++---
 drivers/net/ethernet/ti/davinci_cpdma.h |  4 ++
 2 files changed, 83 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ethernet/ti/davinci_cpdma.c 
b/drivers/net/ethernet/ti/davinci_cpdma.c
index 5cf1758d425b..4e693c3aab27 100644
--- a/drivers/net/ethernet/ti/davinci_cpdma.c
+++ b/drivers/net/ethernet/ti/davinci_cpdma.c
@@ -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, >hw_mode);
writel_relaxed((uintptr_t)si->token, >sw_token);
writel_relaxed(buffer, >sw_buffer);
-   writel_relaxed(len, >sw_len);
+   writel_relaxed(swlen, >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(>lock, flags);
+   if (chan->state == CPDMA_STATE_TEARDOWN) {
+   spin_unlock_irqrestore(>lock, flags);
+   return -EINVAL;
+   }
+
+   ret = cpdma_chan_submit_si();
+   spin_unlock_irqrestore(>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(>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(>lock, flags);
+   if (chan->state != CPDMA_STATE_ACTIVE) {
+   spin_unlock_irqrestore(>lock, flags);
+   return -EINVAL;
+   }
+
+   ret = cpdma_chan_submit_si();
+   spin_unlock_irqrestore(>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;
+