|
@@ -19,6 +19,10 @@
|
|
|
#include <linux/platform_device.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 */
|
|
|
#define MODER 0x00
|
|
|
#define INT_SOURCE 0x04
|
|
@@ -167,6 +171,7 @@
|
|
|
* struct ethoc - driver-private device structure
|
|
|
* @iobase: pointer to I/O memory region
|
|
|
* @membase: pointer to buffer memory region
|
|
|
+ * @dma_alloc: dma allocated buffer size
|
|
|
* @num_tx: number of send buffers
|
|
|
* @cur_tx: last send buffer written
|
|
|
* @dty_tx: last buffer actually sent
|
|
@@ -185,6 +190,7 @@
|
|
|
struct ethoc {
|
|
|
void __iomem *iobase;
|
|
|
void __iomem *membase;
|
|
|
+ int dma_alloc;
|
|
|
|
|
|
unsigned int num_tx;
|
|
|
unsigned int cur_tx;
|
|
@@ -906,22 +912,19 @@ static int ethoc_probe(struct platform_device *pdev)
|
|
|
|
|
|
/* obtain buffer memory space */
|
|
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
|
|
- if (!res) {
|
|
|
- dev_err(&pdev->dev, "cannot obtain memory space\n");
|
|
|
- ret = -ENXIO;
|
|
|
- goto free;
|
|
|
- }
|
|
|
-
|
|
|
- mem = devm_request_mem_region(&pdev->dev, res->start,
|
|
|
+ if (res) {
|
|
|
+ mem = devm_request_mem_region(&pdev->dev, res->start,
|
|
|
res->end - res->start + 1, res->name);
|
|
|
- if (!mem) {
|
|
|
- dev_err(&pdev->dev, "cannot request memory space\n");
|
|
|
- ret = -ENXIO;
|
|
|
- goto free;
|
|
|
+ if (!mem) {
|
|
|
+ dev_err(&pdev->dev, "cannot request memory space\n");
|
|
|
+ ret = -ENXIO;
|
|
|
+ goto free;
|
|
|
+ }
|
|
|
+
|
|
|
+ netdev->mem_start = mem->start;
|
|
|
+ netdev->mem_end = mem->end;
|
|
|
}
|
|
|
|
|
|
- netdev->mem_start = mem->start;
|
|
|
- netdev->mem_end = mem->end;
|
|
|
|
|
|
/* obtain device IRQ number */
|
|
|
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
|
@@ -936,6 +939,7 @@ static int ethoc_probe(struct platform_device *pdev)
|
|
|
/* setup driver-private data */
|
|
|
priv = netdev_priv(netdev);
|
|
|
priv->netdev = netdev;
|
|
|
+ priv->dma_alloc = 0;
|
|
|
|
|
|
priv->iobase = devm_ioremap_nocache(&pdev->dev, netdev->base_addr,
|
|
|
mmio->end - mmio->start + 1);
|
|
@@ -945,12 +949,27 @@ static int ethoc_probe(struct platform_device *pdev)
|
|
|
goto error;
|
|
|
}
|
|
|
|
|
|
- priv->membase = devm_ioremap_nocache(&pdev->dev, netdev->mem_start,
|
|
|
- mem->end - mem->start + 1);
|
|
|
- if (!priv->membase) {
|
|
|
- dev_err(&pdev->dev, "cannot remap memory space\n");
|
|
|
- ret = -ENXIO;
|
|
|
- goto error;
|
|
|
+ if (netdev->mem_end) {
|
|
|
+ priv->membase = devm_ioremap_nocache(&pdev->dev,
|
|
|
+ netdev->mem_start, mem->end - mem->start + 1);
|
|
|
+ if (!priv->membase) {
|
|
|
+ dev_err(&pdev->dev, "cannot remap memory space\n");
|
|
|
+ ret = -ENXIO;
|
|
|
+ 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. */
|
|
@@ -1037,6 +1056,9 @@ free_mdio:
|
|
|
kfree(priv->mdio->irq);
|
|
|
mdiobus_free(priv->mdio);
|
|
|
free:
|
|
|
+ if (priv->dma_alloc)
|
|
|
+ dma_free_coherent(NULL, priv->dma_alloc, priv->membase,
|
|
|
+ netdev->mem_start);
|
|
|
free_netdev(netdev);
|
|
|
out:
|
|
|
return ret;
|
|
@@ -1062,7 +1084,9 @@ static int ethoc_remove(struct platform_device *pdev)
|
|
|
kfree(priv->mdio->irq);
|
|
|
mdiobus_free(priv->mdio);
|
|
|
}
|
|
|
-
|
|
|
+ if (priv->dma_alloc)
|
|
|
+ dma_free_coherent(NULL, priv->dma_alloc, priv->membase,
|
|
|
+ netdev->mem_start);
|
|
|
unregister_netdev(netdev);
|
|
|
free_netdev(netdev);
|
|
|
}
|