The access patterns inside the driver assume uncached memory but the memory returned by netdev_priv is cached. The bug manifests itself in packets taking a long time to be sent or received because the owner flag in the DMA descriptor is still in the cache.
Signed-off-by: Daniel Glöckner <daniel...@gmx.net> --- drivers/net/jz_eth.c | 39 ++++++++++++++++++++++++++++++--------- 1 files changed, 30 insertions(+), 9 deletions(-) diff --git a/drivers/net/jz_eth.c b/drivers/net/jz_eth.c index e81e6da..1f4cec4 100644 --- a/drivers/net/jz_eth.c +++ b/drivers/net/jz_eth.c @@ -1262,12 +1262,12 @@ static int __init jz_eth_init(void) { struct net_device *dev; struct jz_eth_private *np; - int err; + int err = -ENOMEM; dev = alloc_etherdev(sizeof(struct jz_eth_private)); if (!dev) { printk(KERN_ERR "%s: alloc_etherdev failed\n", DRV_NAME); - return -ENOMEM; + goto err_out; } netdev = dev; @@ -1279,13 +1279,20 @@ static int __init jz_eth_init(void) if (!np->vaddr_rx_buf) { printk(KERN_ERR "%s: Cannot alloc dma buffers\n", DRV_NAME); - unregister_netdev(dev); - free_netdev(dev); - return -ENOMEM; + goto err_free_netdev; } - np->dma_rx_ring = virt_to_bus(np->rx_ring); - np->dma_tx_ring = virt_to_bus(np->tx_ring); + np->tx_ring = dma_alloc_coherent(NULL, (NUM_TX_DESCS + NUM_RX_DESCS) + * sizeof(jz_desc_t), + &np->dma_tx_ring, GFP_KERNEL); + + if (!np->tx_ring) { + printk(KERN_ERR "%s: Cannot alloc dma descriptors\n", DRV_NAME); + goto err_free_buf; + } + + np->rx_ring = np->tx_ring + NUM_TX_DESCS; + np->dma_rx_ring = np->dma_tx_ring + sizeof(jz_desc_t) * NUM_TX_DESCS; np->full_duplex = 1; np->link_state = 1; @@ -1301,8 +1308,7 @@ static int __init jz_eth_init(void) if ((err = register_netdev(dev)) != 0) { printk(KERN_ERR "%s: Cannot register net device, error %d\n", DRV_NAME, err); - free_netdev(dev); - return -ENOMEM; + goto err_free_descs; } //#ifdef 0 //CONFIG_PM @@ -1312,6 +1318,18 @@ static int __init jz_eth_init(void) //#endif return 0; + +err_free_descs: + dma_free_coherent(NULL, (NUM_TX_DESCS + NUM_RX_DESCS) + * sizeof(jz_desc_t), + np->tx_ring, np->dma_tx_ring); +err_free_buf: + dma_free_noncoherent(NULL, NUM_RX_DESCS * RX_BUF_SIZE, + (void *)np->vaddr_rx_buf, np->dma_rx_buf); +err_free_netdev: + free_netdev(dev); +err_out: + return err; } static void __exit jz_eth_exit(void) @@ -1320,6 +1338,9 @@ static void __exit jz_eth_exit(void) struct jz_eth_private *np = netdev_priv(dev); unregister_netdev(dev); + dma_free_coherent(NULL, (NUM_TX_DESCS + NUM_RX_DESCS) + * sizeof(jz_desc_t), + np->tx_ring, np->dma_tx_ring); dma_free_noncoherent(NULL, NUM_RX_DESCS * RX_BUF_SIZE, (void *)np->vaddr_rx_buf, np->dma_rx_buf); free_netdev(dev); -- 1.7.0.5 _______________________________________________ Mipsbook-devel mailing list Mipsbook-devel@linuxtogo.org http://lists.linuxtogo.org/cgi-bin/mailman/listinfo/mipsbook-devel