aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethoc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethoc.c')
-rw-r--r--drivers/net/ethoc.c81
1 files changed, 54 insertions, 27 deletions
diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
index b7311bc00258..34d0c69e67f7 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;
@@ -284,7 +290,7 @@ static int ethoc_init_ring(struct ethoc *dev)
284 dev->cur_rx = 0; 290 dev->cur_rx = 0;
285 291
286 /* setup transmission buffers */ 292 /* setup transmission buffers */
287 bd.addr = 0; 293 bd.addr = virt_to_phys(dev->membase);
288 bd.stat = TX_BD_IRQ | TX_BD_CRC; 294 bd.stat = TX_BD_IRQ | TX_BD_CRC;
289 295
290 for (i = 0; i < dev->num_tx; i++) { 296 for (i = 0; i < dev->num_tx; i++) {
@@ -295,7 +301,6 @@ static int ethoc_init_ring(struct ethoc *dev)
295 bd.addr += ETHOC_BUFSIZ; 301 bd.addr += ETHOC_BUFSIZ;
296 } 302 }
297 303
298 bd.addr = dev->num_tx * ETHOC_BUFSIZ;
299 bd.stat = RX_BD_EMPTY | RX_BD_IRQ; 304 bd.stat = RX_BD_EMPTY | RX_BD_IRQ;
300 305
301 for (i = 0; i < dev->num_rx; i++) { 306 for (i = 0; i < dev->num_rx; i++) {
@@ -400,8 +405,12 @@ static int ethoc_rx(struct net_device *dev, int limit)
400 if (ethoc_update_rx_stats(priv, &bd) == 0) { 405 if (ethoc_update_rx_stats(priv, &bd) == 0) {
401 int size = bd.stat >> 16; 406 int size = bd.stat >> 16;
402 struct sk_buff *skb = netdev_alloc_skb(dev, size); 407 struct sk_buff *skb = netdev_alloc_skb(dev, size);
408
409 size -= 4; /* strip the CRC */
410 skb_reserve(skb, 2); /* align TCP/IP header */
411
403 if (likely(skb)) { 412 if (likely(skb)) {
404 void *src = priv->membase + bd.addr; 413 void *src = phys_to_virt(bd.addr);
405 memcpy_fromio(skb_put(skb, size), src, size); 414 memcpy_fromio(skb_put(skb, size), src, size);
406 skb->protocol = eth_type_trans(skb, dev); 415 skb->protocol = eth_type_trans(skb, dev);
407 priv->stats.rx_packets++; 416 priv->stats.rx_packets++;
@@ -653,9 +662,9 @@ static int ethoc_open(struct net_device *dev)
653 if (ret) 662 if (ret)
654 return ret; 663 return ret;
655 664
656 /* calculate the number of TX/RX buffers */ 665 /* calculate the number of TX/RX buffers, maximum 128 supported */
657 num_bd = (dev->mem_end - dev->mem_start + 1) / ETHOC_BUFSIZ; 666 num_bd = min(128, (dev->mem_end - dev->mem_start + 1) / ETHOC_BUFSIZ);
658 priv->num_tx = min(min_tx, num_bd / 4); 667 priv->num_tx = max(min_tx, num_bd / 4);
659 priv->num_rx = num_bd - priv->num_tx; 668 priv->num_rx = num_bd - priv->num_tx;
660 ethoc_write(priv, TX_BD_NUM, priv->num_tx); 669 ethoc_write(priv, TX_BD_NUM, priv->num_tx);
661 670
@@ -823,7 +832,7 @@ static netdev_tx_t ethoc_start_xmit(struct sk_buff *skb, struct net_device *dev)
823 else 832 else
824 bd.stat &= ~TX_BD_PAD; 833 bd.stat &= ~TX_BD_PAD;
825 834
826 dest = priv->membase + bd.addr; 835 dest = phys_to_virt(bd.addr);
827 memcpy_toio(dest, skb->data, skb->len); 836 memcpy_toio(dest, skb->data, skb->len);
828 837
829 bd.stat &= ~(TX_BD_STATS | TX_BD_LEN_MASK); 838 bd.stat &= ~(TX_BD_STATS | TX_BD_LEN_MASK);
@@ -903,22 +912,19 @@ static int ethoc_probe(struct platform_device *pdev)
903 912
904 /* obtain buffer memory space */ 913 /* obtain buffer memory space */
905 res = platform_get_resource(pdev, IORESOURCE_MEM, 1); 914 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
906 if (!res) { 915 if (res) {
907 dev_err(&pdev->dev, "cannot obtain memory space\n"); 916 mem = devm_request_mem_region(&pdev->dev, res->start,
908 ret = -ENXIO;
909 goto free;
910 }
911
912 mem = devm_request_mem_region(&pdev->dev, res->start,
913 res->end - res->start + 1, res->name); 917 res->end - res->start + 1, res->name);
914 if (!mem) { 918 if (!mem) {
915 dev_err(&pdev->dev, "cannot request memory space\n"); 919 dev_err(&pdev->dev, "cannot request memory space\n");
916 ret = -ENXIO; 920 ret = -ENXIO;
917 goto free; 921 goto free;
922 }
923
924 netdev->mem_start = mem->start;
925 netdev->mem_end = mem->end;
918 } 926 }
919 927
920 netdev->mem_start = mem->start;
921 netdev->mem_end = mem->end;
922 928
923 /* obtain device IRQ number */ 929 /* obtain device IRQ number */
924 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 930 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
@@ -933,6 +939,7 @@ static int ethoc_probe(struct platform_device *pdev)
933 /* setup driver-private data */ 939 /* setup driver-private data */
934 priv = netdev_priv(netdev); 940 priv = netdev_priv(netdev);
935 priv->netdev = netdev; 941 priv->netdev = netdev;
942 priv->dma_alloc = 0;
936 943
937 priv->iobase = devm_ioremap_nocache(&pdev->dev, netdev->base_addr, 944 priv->iobase = devm_ioremap_nocache(&pdev->dev, netdev->base_addr,
938 mmio->end - mmio->start + 1); 945 mmio->end - mmio->start + 1);
@@ -942,12 +949,27 @@ static int ethoc_probe(struct platform_device *pdev)
942 goto error; 949 goto error;
943 } 950 }
944 951
945 priv->membase = devm_ioremap_nocache(&pdev->dev, netdev->mem_start, 952 if (netdev->mem_end) {
946 mem->end - mem->start + 1); 953 priv->membase = devm_ioremap_nocache(&pdev->dev,
947 if (!priv->membase) { 954 netdev->mem_start, mem->end - mem->start + 1);
948 dev_err(&pdev->dev, "cannot remap memory space\n"); 955 if (!priv->membase) {
949 ret = -ENXIO; 956 dev_err(&pdev->dev, "cannot remap memory space\n");
950 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;
951 } 973 }
952 974
953 /* Allow the platform setup code to pass in a MAC address. */ 975 /* Allow the platform setup code to pass in a MAC address. */
@@ -1034,6 +1056,9 @@ free_mdio:
1034 kfree(priv->mdio->irq); 1056 kfree(priv->mdio->irq);
1035 mdiobus_free(priv->mdio); 1057 mdiobus_free(priv->mdio);
1036free: 1058free:
1059 if (priv->dma_alloc)
1060 dma_free_coherent(NULL, priv->dma_alloc, priv->membase,
1061 netdev->mem_start);
1037 free_netdev(netdev); 1062 free_netdev(netdev);
1038out: 1063out:
1039 return ret; 1064 return ret;
@@ -1059,7 +1084,9 @@ static int ethoc_remove(struct platform_device *pdev)
1059 kfree(priv->mdio->irq); 1084 kfree(priv->mdio->irq);
1060 mdiobus_free(priv->mdio); 1085 mdiobus_free(priv->mdio);
1061 } 1086 }
1062 1087 if (priv->dma_alloc)
1088 dma_free_coherent(NULL, priv->dma_alloc, priv->membase,
1089 netdev->mem_start);
1063 unregister_netdev(netdev); 1090 unregister_netdev(netdev);
1064 free_netdev(netdev); 1091 free_netdev(netdev);
1065 } 1092 }