diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/ethoc.c | 64 |
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 | ||
22 | static int buffer_size = 0x8000; /* 32 KBytes */ | ||
23 | module_param(buffer_size, int, 0); | ||
24 | MODULE_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 @@ | |||
185 | struct ethoc { | 190 | struct 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); |
1039 | free: | 1058 | free: |
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); |
1041 | out: | 1063 | out: |
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 | } |