* [PATCH v4] sun4i-emac.c: add dma support
@ 2021-12-24 14:44 conleylee
2021-12-28 2:35 ` Jakub Kicinski
[not found] ` <tencent_A7052D6C7B1E2AEFA505D7A52E5B974D8508@qq.com>
0 siblings, 2 replies; 16+ messages in thread
From: conleylee @ 2021-12-24 14:44 UTC (permalink / raw)
To: davem, kuba, mripard, wens; +Cc: netdev, Conley Lee
From: Conley Lee <conleylee@foxmail.com>
This patch adds support for the emac rx dma present on sun4i.
The emac is able to move packets from rx fifo to RAM by using dma.
Signed-off-by: Conley Lee <conleylee@foxmail.com>
---
drivers/net/ethernet/allwinner/sun4i-emac.c | 209 +++++++++++++++++++-
1 file changed, 200 insertions(+), 9 deletions(-)
diff --git a/drivers/net/ethernet/allwinner/sun4i-emac.c b/drivers/net/ethernet/allwinner/sun4i-emac.c
index cccf8a3ead5e..b17d2df17335 100644
--- a/drivers/net/ethernet/allwinner/sun4i-emac.c
+++ b/drivers/net/ethernet/allwinner/sun4i-emac.c
@@ -29,6 +29,7 @@
#include <linux/platform_device.h>
#include <linux/phy.h>
#include <linux/soc/sunxi/sunxi_sram.h>
+#include <linux/dmaengine.h>
#include "sun4i-emac.h"
@@ -86,6 +87,16 @@ struct emac_board_info {
unsigned int duplex;
phy_interface_t phy_interface;
+ struct dma_chan *rx_chan;
+ phys_addr_t emac_rx_fifo;
+};
+
+struct emac_dma_req {
+ struct emac_board_info *db;
+ struct dma_async_tx_descriptor *desc;
+ struct sk_buff *sbk;
+ dma_addr_t rxbuf;
+ int count;
};
static void emac_update_speed(struct net_device *dev)
@@ -205,6 +216,113 @@ static void emac_inblk_32bit(void __iomem *reg, void *data, int count)
readsl(reg, data, round_up(count, 4) / 4);
}
+static struct emac_dma_req *
+alloc_emac_dma_req(struct emac_board_info *db,
+ struct dma_async_tx_descriptor *desc, struct sk_buff *skb,
+ dma_addr_t rxbuf, int count)
+{
+ struct emac_dma_req *req =
+ kzalloc(sizeof(struct emac_dma_req), GFP_KERNEL);
+ if (!req)
+ return NULL;
+
+ req->db = db;
+ req->desc = desc;
+ req->sbk = skb;
+ req->rxbuf = rxbuf;
+ req->count = count;
+ return req;
+}
+
+static void free_emac_dma_req(struct emac_dma_req *req)
+{
+ kfree(req);
+}
+
+static void emac_dma_done_callback(void *arg)
+{
+ struct emac_dma_req *req = arg;
+ struct emac_board_info *db = req->db;
+ struct sk_buff *skb = req->sbk;
+ struct net_device *dev = db->ndev;
+ int rxlen = req->count;
+ u32 reg_val;
+
+ dma_unmap_single(db->dev, req->rxbuf, rxlen, DMA_FROM_DEVICE);
+
+ skb->protocol = eth_type_trans(skb, dev);
+ netif_rx(skb);
+ dev->stats.rx_bytes += rxlen;
+ /* Pass to upper layer */
+ dev->stats.rx_packets++;
+
+ //re enable cpu receive
+ reg_val = readl(db->membase + EMAC_RX_CTL_REG);
+ reg_val &= ~EMAC_RX_CTL_DMA_EN;
+ writel(reg_val, db->membase + EMAC_RX_CTL_REG);
+
+ //re enable interrupt
+ reg_val = readl(db->membase + EMAC_INT_CTL_REG);
+ reg_val |= (0x01 << 8);
+ writel(reg_val, db->membase + EMAC_INT_CTL_REG);
+
+ db->emacrx_completed_flag = 1;
+ free_emac_dma_req(req);
+}
+
+static void emac_dma_inblk_32bit(struct emac_board_info *db,
+ struct sk_buff *skb, int count)
+{
+ struct dma_async_tx_descriptor *desc;
+ dma_cookie_t cookie;
+ dma_addr_t rxbuf;
+ void *rdptr;
+ struct emac_dma_req *req;
+
+ rdptr = skb_put(skb, count - 4);
+ rxbuf = dma_map_single(db->dev, rdptr, count, DMA_FROM_DEVICE);
+
+ if (dma_mapping_error(db->dev, rxbuf)) {
+ dev_err(db->dev, "dma mapping error.\n");
+ return;
+ }
+
+ desc = dmaengine_prep_slave_single(db->rx_chan, rxbuf, count,
+ DMA_DEV_TO_MEM,
+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ if (!desc) {
+ dev_err(db->dev, "prepare slave single failed\n");
+ goto prepare_err;
+ }
+
+ req = alloc_emac_dma_req(db, desc, skb, rxbuf, count);
+ if (!req) {
+ dev_err(db->dev, "alloc emac dma req error.\n");
+ goto alloc_req_err;
+ }
+
+ desc->callback_param = req;
+ desc->callback = emac_dma_done_callback;
+
+ cookie = dmaengine_submit(desc);
+ if (dma_submit_error(cookie)) {
+ dev_err(db->dev, "dma submit error.\n");
+ goto submit_err;
+ }
+
+ dma_async_issue_pending(db->rx_chan);
+ return;
+
+submit_err:
+ free_emac_dma_req(req);
+
+alloc_req_err:
+ dmaengine_desc_free(desc);
+
+prepare_err:
+ dma_unmap_single(db->dev, rxbuf, count, DMA_FROM_DEVICE);
+}
+
/* ethtool ops */
static void emac_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *info)
@@ -599,20 +717,28 @@ static void emac_rx(struct net_device *dev)
if (!skb)
continue;
skb_reserve(skb, 2);
- rdptr = skb_put(skb, rxlen - 4);
/* Read received packet from RX SRAM */
if (netif_msg_rx_status(db))
dev_dbg(db->dev, "RxLen %x\n", rxlen);
- emac_inblk_32bit(db->membase + EMAC_RX_IO_DATA_REG,
- rdptr, rxlen);
- dev->stats.rx_bytes += rxlen;
-
- /* Pass to upper layer */
- skb->protocol = eth_type_trans(skb, dev);
- netif_rx(skb);
- dev->stats.rx_packets++;
+ if (rxlen < dev->mtu || !db->rx_chan) {
+ rdptr = skb_put(skb, rxlen - 4);
+ emac_inblk_32bit(db->membase + EMAC_RX_IO_DATA_REG,
+ rdptr, rxlen);
+ dev->stats.rx_bytes += rxlen;
+
+ /* Pass to upper layer */
+ skb->protocol = eth_type_trans(skb, dev);
+ netif_rx(skb);
+ dev->stats.rx_packets++;
+ } else {
+ reg_val = readl(db->membase + EMAC_RX_CTL_REG);
+ reg_val |= EMAC_RX_CTL_DMA_EN;
+ writel(reg_val, db->membase + EMAC_RX_CTL_REG);
+ emac_dma_inblk_32bit(db, skb, rxlen);
+ break;
+ }
}
}
}
@@ -659,7 +785,12 @@ static irqreturn_t emac_interrupt(int irq, void *dev_id)
reg_val = readl(db->membase + EMAC_INT_CTL_REG);
reg_val |= (0xf << 0) | (0x01 << 8);
writel(reg_val, db->membase + EMAC_INT_CTL_REG);
+ } else {
+ reg_val = readl(db->membase + EMAC_INT_CTL_REG);
+ reg_val |= (0xf << 0);
+ writel(reg_val, db->membase + EMAC_INT_CTL_REG);
}
+
spin_unlock(&db->lock);
return IRQ_HANDLED;
@@ -764,6 +895,58 @@ static const struct net_device_ops emac_netdev_ops = {
#endif
};
+static int emac_configure_dma(struct emac_board_info *db)
+{
+ struct platform_device *pdev = db->pdev;
+ struct net_device *ndev = db->ndev;
+ struct dma_slave_config conf = {};
+ struct resource *regs;
+ int err = 0;
+
+ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!regs) {
+ netdev_err(ndev, "get io resource from device failed.\n");
+ err = -ENOMEM;
+ goto out_clear_chan;
+ }
+
+ netdev_info(ndev, "get io resource from device: 0x%x, size = %u\n",
+ regs->start, resource_size(regs));
+ db->emac_rx_fifo = regs->start + EMAC_RX_IO_DATA_REG;
+
+ db->rx_chan = dma_request_chan(&pdev->dev, "rx");
+ if (IS_ERR(db->rx_chan)) {
+ netdev_err(ndev,
+ "failed to request dma channel. dma is disabled");
+ err = PTR_ERR(db->rx_chan);
+ goto out_clear_chan;
+ }
+
+ conf.direction = DMA_DEV_TO_MEM;
+ conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ conf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ conf.src_addr = db->emac_rx_fifo;
+ conf.dst_maxburst = 4;
+ conf.src_maxburst = 4;
+ conf.device_fc = false;
+
+ err = dmaengine_slave_config(db->rx_chan, &conf);
+ if (err) {
+ netdev_err(ndev, "config dma slave failed\n");
+ err = -EINVAL;
+ goto out_slave_configure_err;
+ }
+
+ return err;
+
+out_slave_configure_err:
+ dma_release_channel(db->rx_chan);
+
+out_clear_chan:
+ db->rx_chan = NULL;
+ return err;
+}
+
/* Search EMAC board, allocate space and register it
*/
static int emac_probe(struct platform_device *pdev)
@@ -806,6 +989,9 @@ static int emac_probe(struct platform_device *pdev)
goto out_iounmap;
}
+ if (emac_configure_dma(db))
+ netdev_info(ndev, "configure dma failed. disable dma.\n");
+
db->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(db->clk)) {
ret = PTR_ERR(db->clk);
@@ -888,6 +1074,11 @@ static int emac_remove(struct platform_device *pdev)
struct net_device *ndev = platform_get_drvdata(pdev);
struct emac_board_info *db = netdev_priv(ndev);
+ if (db->rx_chan) {
+ dmaengine_terminate_all(db->rx_chan);
+ dma_release_channel(db->rx_chan);
+ }
+
unregister_netdev(ndev);
sunxi_sram_release(&pdev->dev);
clk_disable_unprepare(db->clk);
--
2.34.1
^ permalink raw reply related [flat|nested] 16+ messages in thread* Re: [PATCH v4] sun4i-emac.c: add dma support
2021-12-24 14:44 [PATCH v4] sun4i-emac.c: add dma support conleylee
@ 2021-12-28 2:35 ` Jakub Kicinski
[not found] ` <tencent_A7052D6C7B1E2AEFA505D7A52E5B974D8508@qq.com>
1 sibling, 0 replies; 16+ messages in thread
From: Jakub Kicinski @ 2021-12-28 2:35 UTC (permalink / raw)
To: conleylee; +Cc: davem, mripard, wens, netdev
On Fri, 24 Dec 2021 22:44:31 +0800 conleylee@foxmail.com wrote:
> From: Conley Lee <conleylee@foxmail.com>
>
> This patch adds support for the emac rx dma present on sun4i.
> The emac is able to move packets from rx fifo to RAM by using dma.
>
> Signed-off-by: Conley Lee <conleylee@foxmail.com>
> ---
> drivers/net/ethernet/allwinner/sun4i-emac.c | 209 +++++++++++++++++++-
> 1 file changed, 200 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/net/ethernet/allwinner/sun4i-emac.c b/drivers/net/ethernet/allwinner/sun4i-emac.c
> index cccf8a3ead5e..b17d2df17335 100644
> --- a/drivers/net/ethernet/allwinner/sun4i-emac.c
> +++ b/drivers/net/ethernet/allwinner/sun4i-emac.c
> @@ -29,6 +29,7 @@
> #include <linux/platform_device.h>
> #include <linux/phy.h>
> #include <linux/soc/sunxi/sunxi_sram.h>
> +#include <linux/dmaengine.h>
>
> #include "sun4i-emac.h"
>
> @@ -86,6 +87,16 @@ struct emac_board_info {
> unsigned int duplex;
>
> phy_interface_t phy_interface;
> + struct dma_chan *rx_chan;
> + phys_addr_t emac_rx_fifo;
> +};
> +
> +struct emac_dma_req {
> + struct emac_board_info *db;
> + struct dma_async_tx_descriptor *desc;
> + struct sk_buff *sbk;
sbk -> skb ?
> + dma_addr_t rxbuf;
> + int count;
> };
>
> static void emac_update_speed(struct net_device *dev)
> @@ -205,6 +216,113 @@ static void emac_inblk_32bit(void __iomem *reg, void *data, int count)
> readsl(reg, data, round_up(count, 4) / 4);
> }
>
> +static struct emac_dma_req *
> +alloc_emac_dma_req(struct emac_board_info *db,
nit: please use "emac" as a prefix of the name, instead of putting it
inside the name.
> + struct dma_async_tx_descriptor *desc, struct sk_buff *skb,
> + dma_addr_t rxbuf, int count)
> +{
> + struct emac_dma_req *req =
> + kzalloc(sizeof(struct emac_dma_req), GFP_KERNEL);
Please don't put complex initializers inline, also missing an empty
line between variable declaration and code. Should be:
struct emac_dma_req *req;
req = kzalloc(...);
if (!req)
...
You seem to call this from an IRQ handler, shouldn't the flags be
GFP_ATOMIC? Please test with CONFIG_DEBUG_ATOMIC_SLEEP=y.
> + if (!req)
> + return NULL;
> +
> + req->db = db;
> + req->desc = desc;
> + req->sbk = skb;
> + req->rxbuf = rxbuf;
> + req->count = count;
> + return req;
> +}
> +
> +static void free_emac_dma_req(struct emac_dma_req *req)
> +{
> + kfree(req);
> +}
> +
> +static void emac_dma_done_callback(void *arg)
> +{
> + struct emac_dma_req *req = arg;
> + struct emac_board_info *db = req->db;
> + struct sk_buff *skb = req->sbk;
> + struct net_device *dev = db->ndev;
> + int rxlen = req->count;
> + u32 reg_val;
> +
> + dma_unmap_single(db->dev, req->rxbuf, rxlen, DMA_FROM_DEVICE);
> +
> + skb->protocol = eth_type_trans(skb, dev);
> + netif_rx(skb);
> + dev->stats.rx_bytes += rxlen;
> + /* Pass to upper layer */
> + dev->stats.rx_packets++;
> +
> + //re enable cpu receive
Please use the /**/ comment style consistently
> + reg_val = readl(db->membase + EMAC_RX_CTL_REG);
> + reg_val &= ~EMAC_RX_CTL_DMA_EN;
> + writel(reg_val, db->membase + EMAC_RX_CTL_REG);
> +
> + //re enable interrupt
> + reg_val = readl(db->membase + EMAC_INT_CTL_REG);
> + reg_val |= (0x01 << 8);
> + writel(reg_val, db->membase + EMAC_INT_CTL_REG);
> +
> + db->emacrx_completed_flag = 1;
> + free_emac_dma_req(req);
> +}
> +
> +static void emac_dma_inblk_32bit(struct emac_board_info *db,
> + struct sk_buff *skb, int count)
> +{
> + struct dma_async_tx_descriptor *desc;
> + dma_cookie_t cookie;
> + dma_addr_t rxbuf;
> + void *rdptr;
> + struct emac_dma_req *req;
> +
> + rdptr = skb_put(skb, count - 4);
The skb_put can be factored out from both branches it seems.
> + rxbuf = dma_map_single(db->dev, rdptr, count, DMA_FROM_DEVICE);
> +
> + if (dma_mapping_error(db->dev, rxbuf)) {
> + dev_err(db->dev, "dma mapping error.\n");
> + return;
You seem to leak the skb if this function fails, no?
> + }
> +
> + desc = dmaengine_prep_slave_single(db->rx_chan, rxbuf, count,
> + DMA_DEV_TO_MEM,
> + DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
> + if (!desc) {
> + dev_err(db->dev, "prepare slave single failed\n");
> + goto prepare_err;
> + }
> +
> + req = alloc_emac_dma_req(db, desc, skb, rxbuf, count);
> + if (!req) {
> + dev_err(db->dev, "alloc emac dma req error.\n");
> + goto alloc_req_err;
> + }
> +
> + desc->callback_param = req;
> + desc->callback = emac_dma_done_callback;
> +
> + cookie = dmaengine_submit(desc);
> + if (dma_submit_error(cookie)) {
> + dev_err(db->dev, "dma submit error.\n");
> + goto submit_err;
> + }
> +
> + dma_async_issue_pending(db->rx_chan);
> + return;
> +
> +submit_err:
> + free_emac_dma_req(req);
> +
> +alloc_req_err:
> + dmaengine_desc_free(desc);
> +
> +prepare_err:
> + dma_unmap_single(db->dev, rxbuf, count, DMA_FROM_DEVICE);
> +}
> - /* Pass to upper layer */
> - skb->protocol = eth_type_trans(skb, dev);
> - netif_rx(skb);
> - dev->stats.rx_packets++;
> + if (rxlen < dev->mtu || !db->rx_chan) {
> + rdptr = skb_put(skb, rxlen - 4);
> + emac_inblk_32bit(db->membase + EMAC_RX_IO_DATA_REG,
> + rdptr, rxlen);
> + dev->stats.rx_bytes += rxlen;
> +
> + /* Pass to upper layer */
> + skb->protocol = eth_type_trans(skb, dev);
> + netif_rx(skb);
> + dev->stats.rx_packets++;
> + } else {
> + reg_val = readl(db->membase + EMAC_RX_CTL_REG);
> + reg_val |= EMAC_RX_CTL_DMA_EN;
> + writel(reg_val, db->membase + EMAC_RX_CTL_REG);
> + emac_dma_inblk_32bit(db, skb, rxlen);
> + break;
> + }
> }
> +static int emac_configure_dma(struct emac_board_info *db)
> +{
> + struct platform_device *pdev = db->pdev;
> + struct net_device *ndev = db->ndev;
> + struct dma_slave_config conf = {};
> + struct resource *regs;
> + int err = 0;
> +
> + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + if (!regs) {
> + netdev_err(ndev, "get io resource from device failed.\n");
> + err = -ENOMEM;
> + goto out_clear_chan;
> + }
> +
> + netdev_info(ndev, "get io resource from device: 0x%x, size = %u\n",
> + regs->start, resource_size(regs));
> + db->emac_rx_fifo = regs->start + EMAC_RX_IO_DATA_REG;
> +
> + db->rx_chan = dma_request_chan(&pdev->dev, "rx");
> + if (IS_ERR(db->rx_chan)) {
> + netdev_err(ndev,
> + "failed to request dma channel. dma is disabled");
nit: this message lacks '\n' at the end
> + err = PTR_ERR(db->rx_chan);
> + goto out_clear_chan;
> + }
^ permalink raw reply [flat|nested] 16+ messages in thread[parent not found: <tencent_A7052D6C7B1E2AEFA505D7A52E5B974D8508@qq.com>]
* Re: [PATCH v5] sun4i-emac.c: add dma support
[not found] ` <tencent_A7052D6C7B1E2AEFA505D7A52E5B974D8508@qq.com>
@ 2021-12-29 0:48 ` Jakub Kicinski
2021-12-29 1:43 ` [PATCH v6] " conleylee
0 siblings, 1 reply; 16+ messages in thread
From: Jakub Kicinski @ 2021-12-29 0:48 UTC (permalink / raw)
To: conleylee; +Cc: davem, mripard, wens, netdev, linux-arm-kernel, linux-kernel
On Tue, 28 Dec 2021 19:42:04 +0800 conleylee@foxmail.com wrote:
> +static void free_emac_dma_req(struct emac_dma_req *req)
emac_free_dma_req
> +prepare_err:
> + dma_unmap_single(db->dev, rxbuf, count, DMA_FROM_DEVICE);
> + return ret;
incorrect whitespace here
> @@ -599,12 +721,25 @@ static void emac_rx(struct net_device *dev)
> if (!skb)
> continue;
> skb_reserve(skb, 2);
> - rdptr = skb_put(skb, rxlen - 4);
>
> /* Read received packet from RX SRAM */
> if (netif_msg_rx_status(db))
> dev_dbg(db->dev, "RxLen %x\n", rxlen);
>
> + rdptr = skb_put(skb, rxlen - 4);
no reason to move this line
^ permalink raw reply [flat|nested] 16+ messages in thread* [PATCH v6] sun4i-emac.c: add dma support
2021-12-29 0:48 ` [PATCH v5] " Jakub Kicinski
@ 2021-12-29 1:43 ` conleylee
2021-12-30 2:00 ` patchwork-bot+netdevbpf
` (2 more replies)
0 siblings, 3 replies; 16+ messages in thread
From: conleylee @ 2021-12-29 1:43 UTC (permalink / raw)
To: davem, kuba, mripard, wens
Cc: netdev, linux-arm-kernel, linux-kernel, Conley Lee
From: Conley Lee <conleylee@foxmail.com>
Thanks for your review. Here is the new version for this patch.
This patch adds support for the emac rx dma present on sun4i. The emac
is able to move packets from rx fifo to RAM by using dma.
Change since v4.
- rename sbk field to skb
- rename alloc_emac_dma_req to emac_alloc_dma_req
- using kzalloc(..., GPF_ATOMIC) in interrupt context to avoid
sleeping
- retry by using emac_inblk_32bit when emac_dma_inblk_32bit fails
- fix some code style issues
Change since v5.
- fix some code style issue
Signed-off-by: Conley Lee <conleylee@foxmail.com>
---
drivers/net/ethernet/allwinner/sun4i-emac.c | 200 ++++++++++++++++++++
1 file changed, 200 insertions(+)
diff --git a/drivers/net/ethernet/allwinner/sun4i-emac.c b/drivers/net/ethernet/allwinner/sun4i-emac.c
index cccf8a3ead5e..964227e342ee 100644
--- a/drivers/net/ethernet/allwinner/sun4i-emac.c
+++ b/drivers/net/ethernet/allwinner/sun4i-emac.c
@@ -29,6 +29,7 @@
#include <linux/platform_device.h>
#include <linux/phy.h>
#include <linux/soc/sunxi/sunxi_sram.h>
+#include <linux/dmaengine.h>
#include "sun4i-emac.h"
@@ -86,6 +87,16 @@ struct emac_board_info {
unsigned int duplex;
phy_interface_t phy_interface;
+ struct dma_chan *rx_chan;
+ phys_addr_t emac_rx_fifo;
+};
+
+struct emac_dma_req {
+ struct emac_board_info *db;
+ struct dma_async_tx_descriptor *desc;
+ struct sk_buff *skb;
+ dma_addr_t rxbuf;
+ int count;
};
static void emac_update_speed(struct net_device *dev)
@@ -205,6 +216,117 @@ static void emac_inblk_32bit(void __iomem *reg, void *data, int count)
readsl(reg, data, round_up(count, 4) / 4);
}
+static struct emac_dma_req *
+emac_alloc_dma_req(struct emac_board_info *db,
+ struct dma_async_tx_descriptor *desc, struct sk_buff *skb,
+ dma_addr_t rxbuf, int count)
+{
+ struct emac_dma_req *req;
+
+ req = kzalloc(sizeof(struct emac_dma_req), GFP_ATOMIC);
+ if (!req)
+ return NULL;
+
+ req->db = db;
+ req->desc = desc;
+ req->skb = skb;
+ req->rxbuf = rxbuf;
+ req->count = count;
+ return req;
+}
+
+static void emac_free_dma_req(struct emac_dma_req *req)
+{
+ kfree(req);
+}
+
+static void emac_dma_done_callback(void *arg)
+{
+ struct emac_dma_req *req = arg;
+ struct emac_board_info *db = req->db;
+ struct sk_buff *skb = req->skb;
+ struct net_device *dev = db->ndev;
+ int rxlen = req->count;
+ u32 reg_val;
+
+ dma_unmap_single(db->dev, req->rxbuf, rxlen, DMA_FROM_DEVICE);
+
+ skb->protocol = eth_type_trans(skb, dev);
+ netif_rx(skb);
+ dev->stats.rx_bytes += rxlen;
+ /* Pass to upper layer */
+ dev->stats.rx_packets++;
+
+ /* re enable cpu receive */
+ reg_val = readl(db->membase + EMAC_RX_CTL_REG);
+ reg_val &= ~EMAC_RX_CTL_DMA_EN;
+ writel(reg_val, db->membase + EMAC_RX_CTL_REG);
+
+ /* re enable interrupt */
+ reg_val = readl(db->membase + EMAC_INT_CTL_REG);
+ reg_val |= (0x01 << 8);
+ writel(reg_val, db->membase + EMAC_INT_CTL_REG);
+
+ db->emacrx_completed_flag = 1;
+ emac_free_dma_req(req);
+}
+
+static int emac_dma_inblk_32bit(struct emac_board_info *db,
+ struct sk_buff *skb, void *rdptr, int count)
+{
+ struct dma_async_tx_descriptor *desc;
+ dma_cookie_t cookie;
+ dma_addr_t rxbuf;
+ struct emac_dma_req *req;
+ int ret = 0;
+
+ rxbuf = dma_map_single(db->dev, rdptr, count, DMA_FROM_DEVICE);
+ ret = dma_mapping_error(db->dev, rxbuf);
+ if (ret) {
+ dev_err(db->dev, "dma mapping error.\n");
+ return ret;
+ }
+
+ desc = dmaengine_prep_slave_single(db->rx_chan, rxbuf, count,
+ DMA_DEV_TO_MEM,
+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ if (!desc) {
+ dev_err(db->dev, "prepare slave single failed\n");
+ ret = -ENOMEM;
+ goto prepare_err;
+ }
+
+ req = emac_alloc_dma_req(db, desc, skb, rxbuf, count);
+ if (!req) {
+ dev_err(db->dev, "alloc emac dma req error.\n");
+ ret = -ENOMEM;
+ goto alloc_req_err;
+ }
+
+ desc->callback_param = req;
+ desc->callback = emac_dma_done_callback;
+
+ cookie = dmaengine_submit(desc);
+ ret = dma_submit_error(cookie);
+ if (ret) {
+ dev_err(db->dev, "dma submit error.\n");
+ goto submit_err;
+ }
+
+ dma_async_issue_pending(db->rx_chan);
+ return ret;
+
+submit_err:
+ emac_free_dma_req(req);
+
+alloc_req_err:
+ dmaengine_desc_free(desc);
+
+prepare_err:
+ dma_unmap_single(db->dev, rxbuf, count, DMA_FROM_DEVICE);
+ return ret;
+}
+
/* ethtool ops */
static void emac_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *info)
@@ -605,6 +727,19 @@ static void emac_rx(struct net_device *dev)
if (netif_msg_rx_status(db))
dev_dbg(db->dev, "RxLen %x\n", rxlen);
+ if (rxlen >= dev->mtu && db->rx_chan) {
+ reg_val = readl(db->membase + EMAC_RX_CTL_REG);
+ reg_val |= EMAC_RX_CTL_DMA_EN;
+ writel(reg_val, db->membase + EMAC_RX_CTL_REG);
+ if (!emac_dma_inblk_32bit(db, skb, rdptr, rxlen))
+ break;
+
+ /* re enable cpu receive. then try to receive by emac_inblk_32bit */
+ reg_val = readl(db->membase + EMAC_RX_CTL_REG);
+ reg_val &= ~EMAC_RX_CTL_DMA_EN;
+ writel(reg_val, db->membase + EMAC_RX_CTL_REG);
+ }
+
emac_inblk_32bit(db->membase + EMAC_RX_IO_DATA_REG,
rdptr, rxlen);
dev->stats.rx_bytes += rxlen;
@@ -659,7 +794,12 @@ static irqreturn_t emac_interrupt(int irq, void *dev_id)
reg_val = readl(db->membase + EMAC_INT_CTL_REG);
reg_val |= (0xf << 0) | (0x01 << 8);
writel(reg_val, db->membase + EMAC_INT_CTL_REG);
+ } else {
+ reg_val = readl(db->membase + EMAC_INT_CTL_REG);
+ reg_val |= (0xf << 0);
+ writel(reg_val, db->membase + EMAC_INT_CTL_REG);
}
+
spin_unlock(&db->lock);
return IRQ_HANDLED;
@@ -764,6 +904,58 @@ static const struct net_device_ops emac_netdev_ops = {
#endif
};
+static int emac_configure_dma(struct emac_board_info *db)
+{
+ struct platform_device *pdev = db->pdev;
+ struct net_device *ndev = db->ndev;
+ struct dma_slave_config conf = {};
+ struct resource *regs;
+ int err = 0;
+
+ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!regs) {
+ netdev_err(ndev, "get io resource from device failed.\n");
+ err = -ENOMEM;
+ goto out_clear_chan;
+ }
+
+ netdev_info(ndev, "get io resource from device: 0x%x, size = %u\n",
+ regs->start, resource_size(regs));
+ db->emac_rx_fifo = regs->start + EMAC_RX_IO_DATA_REG;
+
+ db->rx_chan = dma_request_chan(&pdev->dev, "rx");
+ if (IS_ERR(db->rx_chan)) {
+ netdev_err(ndev,
+ "failed to request dma channel. dma is disabled\n");
+ err = PTR_ERR(db->rx_chan);
+ goto out_clear_chan;
+ }
+
+ conf.direction = DMA_DEV_TO_MEM;
+ conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ conf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ conf.src_addr = db->emac_rx_fifo;
+ conf.dst_maxburst = 4;
+ conf.src_maxburst = 4;
+ conf.device_fc = false;
+
+ err = dmaengine_slave_config(db->rx_chan, &conf);
+ if (err) {
+ netdev_err(ndev, "config dma slave failed\n");
+ err = -EINVAL;
+ goto out_slave_configure_err;
+ }
+
+ return err;
+
+out_slave_configure_err:
+ dma_release_channel(db->rx_chan);
+
+out_clear_chan:
+ db->rx_chan = NULL;
+ return err;
+}
+
/* Search EMAC board, allocate space and register it
*/
static int emac_probe(struct platform_device *pdev)
@@ -806,6 +998,9 @@ static int emac_probe(struct platform_device *pdev)
goto out_iounmap;
}
+ if (emac_configure_dma(db))
+ netdev_info(ndev, "configure dma failed. disable dma.\n");
+
db->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(db->clk)) {
ret = PTR_ERR(db->clk);
@@ -888,6 +1083,11 @@ static int emac_remove(struct platform_device *pdev)
struct net_device *ndev = platform_get_drvdata(pdev);
struct emac_board_info *db = netdev_priv(ndev);
+ if (db->rx_chan) {
+ dmaengine_terminate_all(db->rx_chan);
+ dma_release_channel(db->rx_chan);
+ }
+
unregister_netdev(ndev);
sunxi_sram_release(&pdev->dev);
clk_disable_unprepare(db->clk);
--
2.31.1
^ permalink raw reply related [flat|nested] 16+ messages in thread* Re: [PATCH v6] sun4i-emac.c: add dma support
2021-12-29 1:43 ` [PATCH v6] " conleylee
@ 2021-12-30 2:00 ` patchwork-bot+netdevbpf
2022-05-30 4:51 ` Corentin Labbe
2021-12-31 10:43 ` Corentin Labbe
2022-01-07 23:34 ` [PATCH v6] sun4i-emac.c: add dma support Kees Cook
2 siblings, 1 reply; 16+ messages in thread
From: patchwork-bot+netdevbpf @ 2021-12-30 2:00 UTC (permalink / raw)
To: None; +Cc: davem, kuba, mripard, wens, netdev, linux-arm-kernel,
linux-kernel
Hello:
This patch was applied to netdev/net-next.git (master)
by Jakub Kicinski <kuba@kernel.org>:
On Wed, 29 Dec 2021 09:43:51 +0800 you wrote:
> From: Conley Lee <conleylee@foxmail.com>
>
> Thanks for your review. Here is the new version for this patch.
>
> This patch adds support for the emac rx dma present on sun4i. The emac
> is able to move packets from rx fifo to RAM by using dma.
>
> [...]
Here is the summary with links:
- [v6] sun4i-emac.c: add dma support
https://git.kernel.org/netdev/net-next/c/47869e82c8b8
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH v6] sun4i-emac.c: add dma support
2021-12-30 2:00 ` patchwork-bot+netdevbpf
@ 2022-05-30 4:51 ` Corentin Labbe
2022-05-30 18:48 ` Jakub Kicinski
0 siblings, 1 reply; 16+ messages in thread
From: Corentin Labbe @ 2022-05-30 4:51 UTC (permalink / raw)
To: patchwork-bot+netdevbpf
Cc: None, davem, kuba, mripard, wens, netdev, linux-arm-kernel,
linux-kernel
Le Thu, Dec 30, 2021 at 02:00:11AM +0000, patchwork-bot+netdevbpf@kernel.org a écrit :
> Hello:
>
> This patch was applied to netdev/net-next.git (master)
> by Jakub Kicinski <kuba@kernel.org>:
>
> On Wed, 29 Dec 2021 09:43:51 +0800 you wrote:
> > From: Conley Lee <conleylee@foxmail.com>
> >
> > Thanks for your review. Here is the new version for this patch.
> >
> > This patch adds support for the emac rx dma present on sun4i. The emac
> > is able to move packets from rx fifo to RAM by using dma.
> >
> > [...]
>
> Here is the summary with links:
> - [v6] sun4i-emac.c: add dma support
> https://git.kernel.org/netdev/net-next/c/47869e82c8b8
>
> You are awesome, thank you!
> --
> Deet-doot-dot, I am a bot.
> https://korg.docs.kernel.org/patchwork/pwbot.html
>
Hello
Any news on patch which enable sun4i-emac DMA in DT ?
Regards
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v6] sun4i-emac.c: add dma support
2022-05-30 4:51 ` Corentin Labbe
@ 2022-05-30 18:48 ` Jakub Kicinski
2022-05-30 18:55 ` Corentin Labbe
0 siblings, 1 reply; 16+ messages in thread
From: Jakub Kicinski @ 2022-05-30 18:48 UTC (permalink / raw)
To: Corentin Labbe
Cc: patchwork-bot+netdevbpf, None, davem, mripard, wens, netdev,
linux-arm-kernel, linux-kernel
On Mon, 30 May 2022 06:51:14 +0200 Corentin Labbe wrote:
> Any news on patch which enable sun4i-emac DMA in DT ?
Who are you directing this question to and where's that patch posted?
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v6] sun4i-emac.c: add dma support
2022-05-30 18:48 ` Jakub Kicinski
@ 2022-05-30 18:55 ` Corentin Labbe
0 siblings, 0 replies; 16+ messages in thread
From: Corentin Labbe @ 2022-05-30 18:55 UTC (permalink / raw)
To: Jakub Kicinski
Cc: None, davem, mripard, wens, netdev, linux-arm-kernel,
linux-kernel
Le Mon, May 30, 2022 at 11:48:19AM -0700, Jakub Kicinski a écrit :
> On Mon, 30 May 2022 06:51:14 +0200 Corentin Labbe wrote:
> > Any news on patch which enable sun4i-emac DMA in DT ?
>
> Who are you directing this question to and where's that patch posted?
I am sorry, I fail to set the right "to:"
My question was for Conley Lee.
This serie was applied but the DT part was never posted.
So sun4i-emac can handle DMA but is not enabled at all.
The DT patch is easy, so without answer, I will send it.
Regards
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v6] sun4i-emac.c: add dma support
2021-12-29 1:43 ` [PATCH v6] " conleylee
2021-12-30 2:00 ` patchwork-bot+netdevbpf
@ 2021-12-31 10:43 ` Corentin Labbe
[not found] ` <tencent_57960DDC83F43DA3E0A2F47DEBAD69A4A005@qq.com>
2022-01-07 23:34 ` [PATCH v6] sun4i-emac.c: add dma support Kees Cook
2 siblings, 1 reply; 16+ messages in thread
From: Corentin Labbe @ 2021-12-31 10:43 UTC (permalink / raw)
To: conleylee
Cc: davem, kuba, mripard, wens, netdev, linux-arm-kernel,
linux-kernel
Le Wed, Dec 29, 2021 at 09:43:51AM +0800, conleylee@foxmail.com a écrit :
> From: Conley Lee <conleylee@foxmail.com>
>
> Thanks for your review. Here is the new version for this patch.
>
> This patch adds support for the emac rx dma present on sun4i. The emac
> is able to move packets from rx fifo to RAM by using dma.
>
> Change since v4.
> - rename sbk field to skb
> - rename alloc_emac_dma_req to emac_alloc_dma_req
> - using kzalloc(..., GPF_ATOMIC) in interrupt context to avoid
> sleeping
> - retry by using emac_inblk_32bit when emac_dma_inblk_32bit fails
> - fix some code style issues
>
> Change since v5.
> - fix some code style issue
>
Hello
I just tested this on a sun4i-a10-olinuxino-lime
I got:
[ 2.922812] sun4i-emac 1c0b000.ethernet (unnamed net_device) (uninitialized): get io resource from device: 0x1c0b000, size = 4096
[ 2.934512] sun4i-emac 1c0b000.ethernet (unnamed net_device) (uninitialized): failed to request dma channel. dma is disabled
[ 2.945740] sun4i-emac 1c0b000.ethernet (unnamed net_device) (uninitialized): configure dma failed. disable dma.
[ 2.957887] sun4i-emac 1c0b000.ethernet: eth0: at (ptrval), IRQ 19 MAC: 02:49:09:40:ab:3d
On which board did you test it and how ?
Regards
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH v6] sun4i-emac.c: add dma support
2021-12-29 1:43 ` [PATCH v6] " conleylee
2021-12-30 2:00 ` patchwork-bot+netdevbpf
2021-12-31 10:43 ` Corentin Labbe
@ 2022-01-07 23:34 ` Kees Cook
2022-01-08 2:34 ` Jakub Kicinski
2 siblings, 1 reply; 16+ messages in thread
From: Kees Cook @ 2022-01-07 23:34 UTC (permalink / raw)
To: conleylee
Cc: davem, kuba, mripard, wens, netdev, linux-arm-kernel,
linux-kernel
On Wed, Dec 29, 2021 at 09:43:51AM +0800, conleylee@foxmail.com wrote:
> From: Conley Lee <conleylee@foxmail.com>
>
> Thanks for your review. Here is the new version for this patch.
>
> This patch adds support for the emac rx dma present on sun4i. The emac
> is able to move packets from rx fifo to RAM by using dma.
>
> Change since v4.
> - rename sbk field to skb
> - rename alloc_emac_dma_req to emac_alloc_dma_req
> - using kzalloc(..., GPF_ATOMIC) in interrupt context to avoid
> sleeping
> - retry by using emac_inblk_32bit when emac_dma_inblk_32bit fails
> - fix some code style issues
>
> Change since v5.
> - fix some code style issue
>
> Signed-off-by: Conley Lee <conleylee@foxmail.com>
> ---
> drivers/net/ethernet/allwinner/sun4i-emac.c | 200 ++++++++++++++++++++
> 1 file changed, 200 insertions(+)
This is causing build failures:
$ make CROSS_COMPILE=aarch64-linux-gnu- ARCH=arm64 allmodconfig
$ make CROSS_COMPILE=aarch64-linux-gnu- ARCH=arm64 -j... -k -s
drivers/net/ethernet/allwinner/sun4i-emac.c: In function 'emac_configure_dma':
drivers/net/ethernet/allwinner/sun4i-emac.c:922:60: error: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'resource_size_t' {aka 'long long unsigned int'} [-Werror=format=]
922 | netdev_info(ndev, "get io resource from device: 0x%x, size = %u\n",
| ~^
| | | unsigned int
| %llx
923 | regs->start, resource_size(regs));
| ~~~~~~~~~~~
| |
| resource_size_t {aka long long unsigned int}
drivers/net/ethernet/allwinner/sun4i-emac.c:922:71: error: format '%u' expects argument of type 'unsigned int', but argument 4 has type 'resource_size_t' {aka 'long long unsigned int'} [-Werror=format=]
922 | netdev_info(ndev, "get io resource from device: 0x%x, size = %u\n",
| ~^
| |
| unsigned int
| %llu
923 | regs->start, resource_size(regs));
| ~~~~~~~~~~~~~~~~~~~
| |
| resource_size_t {aka long long unsigned int}
--
Kees Cook
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH v6] sun4i-emac.c: add dma support
2022-01-07 23:34 ` [PATCH v6] sun4i-emac.c: add dma support Kees Cook
@ 2022-01-08 2:34 ` Jakub Kicinski
0 siblings, 0 replies; 16+ messages in thread
From: Jakub Kicinski @ 2022-01-08 2:34 UTC (permalink / raw)
To: Kees Cook
Cc: conleylee, davem, mripard, wens, netdev, linux-arm-kernel,
linux-kernel
On Fri, 7 Jan 2022 15:34:18 -0800 Kees Cook wrote:
> On Wed, Dec 29, 2021 at 09:43:51AM +0800, conleylee@foxmail.com wrote:
> > From: Conley Lee <conleylee@foxmail.com>
> >
> > Thanks for your review. Here is the new version for this patch.
> >
> > This patch adds support for the emac rx dma present on sun4i. The emac
> > is able to move packets from rx fifo to RAM by using dma.
> >
> > Change since v4.
> > - rename sbk field to skb
> > - rename alloc_emac_dma_req to emac_alloc_dma_req
> > - using kzalloc(..., GPF_ATOMIC) in interrupt context to avoid
> > sleeping
> > - retry by using emac_inblk_32bit when emac_dma_inblk_32bit fails
> > - fix some code style issues
> >
> > Change since v5.
> > - fix some code style issue
> >
> > Signed-off-by: Conley Lee <conleylee@foxmail.com>
>
> This is causing build failures:
>
> $ make CROSS_COMPILE=aarch64-linux-gnu- ARCH=arm64 allmodconfig
> $ make CROSS_COMPILE=aarch64-linux-gnu- ARCH=arm64 -j... -k -s
> drivers/net/ethernet/allwinner/sun4i-emac.c: In function 'emac_configure_dma':
> drivers/net/ethernet/allwinner/sun4i-emac.c:922:60: error: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'resource_size_t' {aka 'long long unsigned int'} [-Werror=format=]
> 922 | netdev_info(ndev, "get io resource from device: 0x%x, size = %u\n",
> | ~^
> | | | unsigned int
> | %llx
> 923 | regs->start, resource_size(regs));
> | ~~~~~~~~~~~
> | |
> | resource_size_t {aka long long unsigned int}
> drivers/net/ethernet/allwinner/sun4i-emac.c:922:71: error: format '%u' expects argument of type 'unsigned int', but argument 4 has type 'resource_size_t' {aka 'long long unsigned int'} [-Werror=format=]
> 922 | netdev_info(ndev, "get io resource from device: 0x%x, size = %u\n",
> | ~^
> | |
> | unsigned int
> | %llu
> 923 | regs->start, resource_size(regs));
> | ~~~~~~~~~~~~~~~~~~~
> | |
> | resource_size_t {aka long long unsigned int}
>
Ugh, I saw this and somehow it didn't enter my brain that it's new.
%pa right? Let me test that and send a fix before we close net-next..
^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2022-05-30 18:55 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-12-24 14:44 [PATCH v4] sun4i-emac.c: add dma support conleylee
2021-12-28 2:35 ` Jakub Kicinski
[not found] ` <tencent_A7052D6C7B1E2AEFA505D7A52E5B974D8508@qq.com>
2021-12-29 0:48 ` [PATCH v5] " Jakub Kicinski
2021-12-29 1:43 ` [PATCH v6] " conleylee
2021-12-30 2:00 ` patchwork-bot+netdevbpf
2022-05-30 4:51 ` Corentin Labbe
2022-05-30 18:48 ` Jakub Kicinski
2022-05-30 18:55 ` Corentin Labbe
2021-12-31 10:43 ` Corentin Labbe
[not found] ` <tencent_57960DDC83F43DA3E0A2F47DEBAD69A4A005@qq.com>
2022-01-02 17:38 ` Corentin Labbe
[not found] ` <tencent_67023336008FE777A58293D2D32DEFA69107@qq.com>
2022-01-03 11:42 ` Corentin Labbe
2022-01-03 12:21 ` Conley Lee
[not found] ` <tencent_E4BA4D6105A46CCC1E8AEF48057EA5FE5B08@qq.com>
2022-01-09 20:45 ` [PATCH v1] sun4i-emac.c: enable emac tx dma Corentin Labbe
2022-01-10 7:47 ` Conley Lee
2022-01-07 23:34 ` [PATCH v6] sun4i-emac.c: add dma support Kees Cook
2022-01-08 2:34 ` Jakub Kicinski
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).