2009-10-05 08:20:44

by Thomas Chou

[permalink] [raw]
Subject: [PATCH 1/4] ethoc: fix typo to compute number of tx descriptors

It should be max() instead of min(). Use 1/4 of available
descriptors for tx, and there should be at least 2 tx
descriptors.

Signed-off-by: Thomas Chou <[email protected]>
---
drivers/net/ethoc.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
index b7311bc..7475620 100644
--- a/drivers/net/ethoc.c
+++ b/drivers/net/ethoc.c
@@ -655,7 +655,7 @@ static int ethoc_open(struct net_device *dev)

/* calculate the number of TX/RX buffers */
num_bd = (dev->mem_end - dev->mem_start + 1) / ETHOC_BUFSIZ;
- priv->num_tx = min(min_tx, num_bd / 4);
+ priv->num_tx = max(min_tx, num_bd / 4);
priv->num_rx = num_bd - priv->num_tx;
ethoc_write(priv, TX_BD_NUM, priv->num_tx);

--
1.6.2.5


2009-10-05 08:21:37

by Thomas Chou

[permalink] [raw]
Subject: [PATCH 2/4] ethoc: fix buffer address mapping

The pointer address in buffer descriptors is physical address. The
pointer that processor used to access packet is virtual address.

Though the higher bits of pointer address used by the MAC may be
truncated to zero in special case, it is not always true in larger
designs.

Signed-off-by: Thomas Chou <[email protected]>
---
drivers/net/ethoc.c | 7 +++----
1 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
index 7475620..f92747f 100644
--- a/drivers/net/ethoc.c
+++ b/drivers/net/ethoc.c
@@ -284,7 +284,7 @@ static int ethoc_init_ring(struct ethoc *dev)
dev->cur_rx = 0;

/* setup transmission buffers */
- bd.addr = 0;
+ bd.addr = virt_to_phys(dev->membase);
bd.stat = TX_BD_IRQ | TX_BD_CRC;

for (i = 0; i < dev->num_tx; i++) {
@@ -295,7 +295,6 @@ static int ethoc_init_ring(struct ethoc *dev)
bd.addr += ETHOC_BUFSIZ;
}

- bd.addr = dev->num_tx * ETHOC_BUFSIZ;
bd.stat = RX_BD_EMPTY | RX_BD_IRQ;

for (i = 0; i < dev->num_rx; i++) {
@@ -401,7 +400,7 @@ static int ethoc_rx(struct net_device *dev, int limit)
int size = bd.stat >> 16;
struct sk_buff *skb = netdev_alloc_skb(dev, size);
if (likely(skb)) {
- void *src = priv->membase + bd.addr;
+ void *src = phys_to_virt(bd.addr);
memcpy_fromio(skb_put(skb, size), src, size);
skb->protocol = eth_type_trans(skb, dev);
priv->stats.rx_packets++;
@@ -823,7 +822,7 @@ static netdev_tx_t ethoc_start_xmit(struct sk_buff *skb, struct net_device *dev)
else
bd.stat &= ~TX_BD_PAD;

- dest = priv->membase + bd.addr;
+ dest = phys_to_virt(bd.addr);
memcpy_toio(dest, skb->data, skb->len);

bd.stat &= ~(TX_BD_STATS | TX_BD_LEN_MASK);
--
1.6.2.5

2009-10-05 08:21:20

by Thomas Chou

[permalink] [raw]
Subject: [PATCH 3/4] ethoc: align received packet to make IP header at word boundary

The packet buffer is allocated at 4 bytes boundary, but the IP header
length and version bits is located at byte 14. These bit fields access
as 32 bits word and caused exception on processors that do not support
unaligned access.

The patch adds 2 bytes offset to make the bit fields word aligned.

Signed-off-by: Thomas Chou <[email protected]>
---
drivers/net/ethoc.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
index f92747f..0c6c7f4 100644
--- a/drivers/net/ethoc.c
+++ b/drivers/net/ethoc.c
@@ -399,6 +399,10 @@ static int ethoc_rx(struct net_device *dev, int limit)
if (ethoc_update_rx_stats(priv, &bd) == 0) {
int size = bd.stat >> 16;
struct sk_buff *skb = netdev_alloc_skb(dev, size);
+
+ size -= 4; /* strip the CRC */
+ skb_reserve(skb, 2); /* align TCP/IP header */
+
if (likely(skb)) {
void *src = phys_to_virt(bd.addr);
memcpy_fromio(skb_put(skb, size), src, size);
--
1.6.2.5

2009-10-05 08:25:49

by Thomas Chou

[permalink] [raw]
Subject: [PATCH 4/4] 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 <[email protected]>
---
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 0c6c7f4..6d82dc6 100644
--- a/drivers/net/ethoc.c
+++ b/drivers/net/ethoc.c
@@ -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);
}
--
1.6.2.5

2009-10-05 08:51:00

by David Miller

[permalink] [raw]
Subject: Re: [PATCH 1/4] ethoc: fix typo to compute number of tx descriptors


Please post networking patches CC:'d to [email protected]
or else they will not get tracked properly at:

http://patchwork.ozlabs.org/project/netdev/list/

and thus they might get lost.

Thank you.