Commit 0baa080c authored by Thomas Chou's avatar Thomas Chou Committed by David S. Miller

ethoc: use system memory as buffer

This patch enabled the ethoc to allocate system memory as buffer
when there is no dedicated buffer memory.

Some hardware designs may not have dedicated buffer memory such as
on chip or off chip SRAM. In this case, only one memory resource is
supplied in the platform data instead of two. Then a DMA buffer can
be allocated from system memory and used for the transfer.
Signed-off-by: default avatarThomas Chou <thomas@wytron.com.tw>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 050f91dc
...@@ -19,6 +19,10 @@ ...@@ -19,6 +19,10 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <net/ethoc.h> #include <net/ethoc.h>
static int buffer_size = 0x8000; /* 32 KBytes */
module_param(buffer_size, int, 0);
MODULE_PARM_DESC(buffer_size, "DMA buffer allocation size");
/* register offsets */ /* register offsets */
#define MODER 0x00 #define MODER 0x00
#define INT_SOURCE 0x04 #define INT_SOURCE 0x04
...@@ -167,6 +171,7 @@ ...@@ -167,6 +171,7 @@
* struct ethoc - driver-private device structure * struct ethoc - driver-private device structure
* @iobase: pointer to I/O memory region * @iobase: pointer to I/O memory region
* @membase: pointer to buffer memory region * @membase: pointer to buffer memory region
* @dma_alloc: dma allocated buffer size
* @num_tx: number of send buffers * @num_tx: number of send buffers
* @cur_tx: last send buffer written * @cur_tx: last send buffer written
* @dty_tx: last buffer actually sent * @dty_tx: last buffer actually sent
...@@ -185,6 +190,7 @@ ...@@ -185,6 +190,7 @@
struct ethoc { struct ethoc {
void __iomem *iobase; void __iomem *iobase;
void __iomem *membase; void __iomem *membase;
int dma_alloc;
unsigned int num_tx; unsigned int num_tx;
unsigned int cur_tx; unsigned int cur_tx;
...@@ -906,12 +912,7 @@ static int ethoc_probe(struct platform_device *pdev) ...@@ -906,12 +912,7 @@ static int ethoc_probe(struct platform_device *pdev)
/* obtain buffer memory space */ /* obtain buffer memory space */
res = platform_get_resource(pdev, IORESOURCE_MEM, 1); res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
if (!res) { if (res) {
dev_err(&pdev->dev, "cannot obtain memory space\n");
ret = -ENXIO;
goto free;
}
mem = devm_request_mem_region(&pdev->dev, res->start, mem = devm_request_mem_region(&pdev->dev, res->start,
res->end - res->start + 1, res->name); res->end - res->start + 1, res->name);
if (!mem) { if (!mem) {
...@@ -922,6 +923,8 @@ static int ethoc_probe(struct platform_device *pdev) ...@@ -922,6 +923,8 @@ static int ethoc_probe(struct platform_device *pdev)
netdev->mem_start = mem->start; netdev->mem_start = mem->start;
netdev->mem_end = mem->end; netdev->mem_end = mem->end;
}
/* obtain device IRQ number */ /* obtain device IRQ number */
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
...@@ -936,6 +939,7 @@ static int ethoc_probe(struct platform_device *pdev) ...@@ -936,6 +939,7 @@ static int ethoc_probe(struct platform_device *pdev)
/* setup driver-private data */ /* setup driver-private data */
priv = netdev_priv(netdev); priv = netdev_priv(netdev);
priv->netdev = netdev; priv->netdev = netdev;
priv->dma_alloc = 0;
priv->iobase = devm_ioremap_nocache(&pdev->dev, netdev->base_addr, priv->iobase = devm_ioremap_nocache(&pdev->dev, netdev->base_addr,
mmio->end - mmio->start + 1); mmio->end - mmio->start + 1);
...@@ -945,13 +949,28 @@ static int ethoc_probe(struct platform_device *pdev) ...@@ -945,13 +949,28 @@ static int ethoc_probe(struct platform_device *pdev)
goto error; goto error;
} }
priv->membase = devm_ioremap_nocache(&pdev->dev, netdev->mem_start, if (netdev->mem_end) {
mem->end - mem->start + 1); priv->membase = devm_ioremap_nocache(&pdev->dev,
netdev->mem_start, mem->end - mem->start + 1);
if (!priv->membase) { if (!priv->membase) {
dev_err(&pdev->dev, "cannot remap memory space\n"); dev_err(&pdev->dev, "cannot remap memory space\n");
ret = -ENXIO; ret = -ENXIO;
goto error; goto error;
} }
} else {
/* Allocate buffer memory */
priv->membase = dma_alloc_coherent(NULL,
buffer_size, (void *)&netdev->mem_start,
GFP_KERNEL);
if (!priv->membase) {
dev_err(&pdev->dev, "cannot allocate %dB buffer\n",
buffer_size);
ret = -ENOMEM;
goto error;
}
netdev->mem_end = netdev->mem_start + buffer_size;
priv->dma_alloc = buffer_size;
}
/* Allow the platform setup code to pass in a MAC address. */ /* Allow the platform setup code to pass in a MAC address. */
if (pdev->dev.platform_data) { if (pdev->dev.platform_data) {
...@@ -1037,6 +1056,9 @@ static int ethoc_probe(struct platform_device *pdev) ...@@ -1037,6 +1056,9 @@ static int ethoc_probe(struct platform_device *pdev)
kfree(priv->mdio->irq); kfree(priv->mdio->irq);
mdiobus_free(priv->mdio); mdiobus_free(priv->mdio);
free: free:
if (priv->dma_alloc)
dma_free_coherent(NULL, priv->dma_alloc, priv->membase,
netdev->mem_start);
free_netdev(netdev); free_netdev(netdev);
out: out:
return ret; return ret;
...@@ -1062,7 +1084,9 @@ static int ethoc_remove(struct platform_device *pdev) ...@@ -1062,7 +1084,9 @@ static int ethoc_remove(struct platform_device *pdev)
kfree(priv->mdio->irq); kfree(priv->mdio->irq);
mdiobus_free(priv->mdio); mdiobus_free(priv->mdio);
} }
if (priv->dma_alloc)
dma_free_coherent(NULL, priv->dma_alloc, priv->membase,
netdev->mem_start);
unregister_netdev(netdev); unregister_netdev(netdev);
free_netdev(netdev); free_netdev(netdev);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment