aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Chou <thomas@wytron.com.tw>2009-10-04 19:33:20 -0400
committerDavid S. Miller <davem@davemloft.net>2009-10-07 06:50:14 -0400
commit0baa080c75cea6357bfba9b93ba598d747457cbd (patch)
treefdfc6dbcb0d93226dd95a84d31192f43d147cfb6
parent050f91dcd9a45a14449dded5180f633692b588d2 (diff)
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: Thomas Chou <thomas@wytron.com.tw> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethoc.c64
1 files changed, 44 insertions, 20 deletions
diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
index 0c6c7f47ace4..6d82dc646ac0 100644
--- a/drivers/net/ethoc.c
+++ b/drivers/net/ethoc.c
@@ -19,6 +19,10 @@
19#include <linux/platform_device.h> 19#include <linux/platform_device.h>
20#include <net/ethoc.h> 20#include <net/ethoc.h>
21 21
22static int buffer_size = 0x8000; /* 32 KBytes */
23module_param(buffer_size, int, 0);
24MODULE_PARM_DESC(buffer_size, "DMA buffer allocation size");
25
22/* register offsets */ 26/* register offsets */
23#define MODER 0x00 27#define MODER 0x00
24#define INT_SOURCE 0x04 28#define INT_SOURCE 0x04
@@ -167,6 +171,7 @@
167 * struct ethoc - driver-private device structure 171 * struct ethoc - driver-private device structure
168 * @iobase: pointer to I/O memory region 172 * @iobase: pointer to I/O memory region
169 * @membase: pointer to buffer memory region 173 * @membase: pointer to buffer memory region
174 * @dma_alloc: dma allocated buffer size
170 * @num_tx: number of send buffers 175 * @num_tx: number of send buffers
171 * @cur_tx: last send buffer written 176 * @cur_tx: last send buffer written
172 * @dty_tx: last buffer actually sent 177 * @dty_tx: last buffer actually sent
@@ -185,6 +190,7 @@
185struct ethoc { 190struct ethoc {
186 void __iomem *iobase; 191 void __iomem *iobase;
187 void __iomem *membase; 192 void __iomem *membase;
193 int dma_alloc;
188 194
189 unsigned int num_tx; 195 unsigned int num_tx;
190 unsigned int cur_tx; 196 unsigned int cur_tx;
@@ -906,22 +912,19 @@ static int ethoc_probe(struct platform_device *pdev)
906 912
907 /* obtain buffer memory space */ 913 /* obtain buffer memory space */
908 res = platform_get_resource(pdev, IORESOURCE_MEM, 1); 914 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
909 if (!res) { 915 if (res) {
910 dev_err(&pdev->dev, "cannot obtain memory space\n"); 916 mem = devm_request_mem_region(&pdev->dev, res->start,
911 ret = -ENXIO;
912 goto free;
913 }
914
915 mem = devm_request_mem_region(&pdev->dev, res->start,
916 res->end - res->start + 1, res->name); 917 res->end - res->start + 1, res->name);
917 if (!mem) { 918 if (!mem) {
918 dev_err(&pdev->dev, "cannot request memory space\n"); 919 dev_err(&pdev->dev, "cannot request memory space\n");
919 ret = -ENXIO; 920 ret = -ENXIO;
920 goto free; 921 goto free;
922 }
923
924 netdev->mem_start = mem->start;
925 netdev->mem_end = mem->end;
921 } 926 }
922 927
923 netdev->mem_start = mem->start;
924 netdev->mem_end = mem->end;
925 928
926 /* obtain device IRQ number */ 929 /* obtain device IRQ number */
927 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 930 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
@@ -936,6 +939,7 @@ static int ethoc_probe(struct platform_device *pdev)
936 /* setup driver-private data */ 939 /* setup driver-private data */
937 priv = netdev_priv(netdev); 940 priv = netdev_priv(netdev);
938 priv->netdev = netdev; 941 priv->netdev = netdev;
942 priv->dma_alloc = 0;
939 943
940 priv->iobase = devm_ioremap_nocache(&pdev->dev, netdev->base_addr, 944 priv->iobase = devm_ioremap_nocache(&pdev->dev, netdev->base_addr,
941 mmio->end - mmio->start + 1); 945 mmio->end - mmio->start + 1);
@@ -945,12 +949,27 @@ static int ethoc_probe(struct platform_device *pdev)
945 goto error; 949 goto error;
946 } 950 }
947 951
948 priv->membase = devm_ioremap_nocache(&pdev->dev, netdev->mem_start, 952 if (netdev->mem_end) {
949 mem->end - mem->start + 1); 953 priv->membase = devm_ioremap_nocache(&pdev->dev,
950 if (!priv->membase) { 954 netdev->mem_start, mem->end - mem->start + 1);
951 dev_err(&pdev->dev, "cannot remap memory space\n"); 955 if (!priv->membase) {
952 ret = -ENXIO; 956 dev_err(&pdev->dev, "cannot remap memory space\n");
953 goto error; 957 ret = -ENXIO;
958 goto error;
959 }
960 } else {
961 /* Allocate buffer memory */
962 priv->membase = dma_alloc_coherent(NULL,
963 buffer_size, (void *)&netdev->mem_start,
964 GFP_KERNEL);
965 if (!priv->membase) {
966 dev_err(&pdev->dev, "cannot allocate %dB buffer\n",
967 buffer_size);
968 ret = -ENOMEM;
969 goto error;
970 }
971 netdev->mem_end = netdev->mem_start + buffer_size;
972 priv->dma_alloc = buffer_size;
954 } 973 }
955 974
956 /* Allow the platform setup code to pass in a MAC address. */ 975 /* Allow the platform setup code to pass in a MAC address. */
@@ -1037,6 +1056,9 @@ free_mdio:
1037 kfree(priv->mdio->irq); 1056 kfree(priv->mdio->irq);
1038 mdiobus_free(priv->mdio); 1057 mdiobus_free(priv->mdio);
1039free: 1058free:
1059 if (priv->dma_alloc)
1060 dma_free_coherent(NULL, priv->dma_alloc, priv->membase,
1061 netdev->mem_start);
1040 free_netdev(netdev); 1062 free_netdev(netdev);
1041out: 1063out:
1042 return ret; 1064 return ret;
@@ -1062,7 +1084,9 @@ static int ethoc_remove(struct platform_device *pdev)
1062 kfree(priv->mdio->irq); 1084 kfree(priv->mdio->irq);
1063 mdiobus_free(priv->mdio); 1085 mdiobus_free(priv->mdio);
1064 } 1086 }
1065 1087 if (priv->dma_alloc)
1088 dma_free_coherent(NULL, priv->dma_alloc, priv->membase,
1089 netdev->mem_start);
1066 unregister_netdev(netdev); 1090 unregister_netdev(netdev);
1067 free_netdev(netdev); 1091 free_netdev(netdev);
1068 } 1092 }