X-Git-Url: https://git.archive.openwrt.org/?a=blobdiff_plain;f=target%2Flinux%2Far71xx%2Ffiles%2Fdrivers%2Fnet%2Fag71xx%2Fag71xx_main.c;h=88edb2fd4c93c07bbeba749205358650b0e26851;hb=5608c597c3b0b5652356c3a9cddda53b315070cb;hp=6302bf648c60b40ae87ea91859952fd19e470420;hpb=788424fcb7a569af63373e199df562f36f39360c;p=openwrt.git diff --git a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_main.c b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_main.c index 6302bf648c..88edb2fd4c 100644 --- a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_main.c +++ b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_main.c @@ -11,6 +11,7 @@ * by the Free Software Foundation. */ +#include #include "ag71xx.h" #define AG71XX_DEFAULT_MSG_ENABLE \ @@ -23,10 +24,10 @@ | NETIF_MSG_RX_ERR \ | NETIF_MSG_TX_ERR ) -static int ag71xx_debug = -1; +static int ag71xx_msg_level = -1; -module_param(ag71xx_debug, int, 0); -MODULE_PARM_DESC(ag71xx_debug, "Debug level (-1=defaults,0=none,...,16=all)"); +module_param_named(msg_level, ag71xx_msg_level, int, 0); +MODULE_PARM_DESC(msg_level, "Message level (-1=defaults,0=none,...,16=all)"); static void ag71xx_dump_dma_regs(struct ag71xx *ag) { @@ -86,7 +87,7 @@ static void ag71xx_ring_free(struct ag71xx_ring *ring) kfree(ring->buf); if (ring->descs_cpu) - dma_free_coherent(NULL, ring->size * sizeof(struct ag71xx_desc), + dma_free_coherent(NULL, ring->size * ring->desc_size, ring->descs_cpu, ring->descs_dma); } @@ -95,10 +96,16 @@ static int ag71xx_ring_alloc(struct ag71xx_ring *ring, unsigned int size) int err; int i; - ring->descs_cpu = dma_alloc_coherent(NULL, - size * sizeof(struct ag71xx_desc), - &ring->descs_dma, - GFP_ATOMIC); + ring->desc_size = sizeof(struct ag71xx_desc); + if (ring->desc_size % cache_line_size()) { + DBG("ag71xx: ring %p, desc size %u rounded to %u\n", + ring, ring->desc_size, + roundup(ring->desc_size, cache_line_size())); + ring->desc_size = roundup(ring->desc_size, cache_line_size()); + } + + ring->descs_cpu = dma_alloc_coherent(NULL, size * ring->desc_size, + &ring->descs_dma, GFP_ATOMIC); if (!ring->descs_cpu) { err = -ENOMEM; goto err; @@ -113,8 +120,9 @@ static int ag71xx_ring_alloc(struct ag71xx_ring *ring, unsigned int size) } for (i = 0; i < size; i++) { - struct ag71xx_desc *descs = (struct ag71xx_desc *) ring->descs_cpu; - ring->buf[i].desc = &descs[i]; + ring->buf[i].desc = (struct ag71xx_desc *)&ring->descs_cpu[i * ring->desc_size]; + DBG("ag71xx: ring %p, desc %d at %p\n", + ring, i, ring->buf[i].desc); } return 0; @@ -156,7 +164,7 @@ static void ag71xx_ring_tx_init(struct ag71xx *ag) for (i = 0; i < AG71XX_TX_RING_SIZE; i++) { ring->buf[i].desc->next = (u32) (ring->descs_dma + - sizeof(struct ag71xx_desc) * ((i + 1) % AG71XX_TX_RING_SIZE)); + ring->desc_size * ((i + 1) % AG71XX_TX_RING_SIZE)); ring->buf[i].desc->ctrl = DESC_EMPTY; ring->buf[i].skb = NULL; @@ -190,9 +198,14 @@ static int ag71xx_ring_rx_init(struct ag71xx *ag) int ret; ret = 0; - for (i = 0; i < AG71XX_RX_RING_SIZE; i++) + for (i = 0; i < AG71XX_RX_RING_SIZE; i++) { ring->buf[i].desc->next = (u32) (ring->descs_dma + - sizeof(struct ag71xx_desc) * ((i + 1) % AG71XX_RX_RING_SIZE)); + ring->desc_size * ((i + 1) % AG71XX_RX_RING_SIZE)); + + DBG("ag71xx: RX desc at %p, next is %08x\n", + ring->buf[i].desc, + ring->buf[i].desc->next); + } for (i = 0; i < AG71XX_RX_RING_SIZE; i++) { struct sk_buff *skb; @@ -305,6 +318,7 @@ static void ag71xx_hw_set_macaddr(struct ag71xx *ag, unsigned char *mac) static void ag71xx_dma_reset(struct ag71xx *ag) { + u32 val; int i; ag71xx_dump_dma_regs(ag); @@ -327,13 +341,19 @@ static void ag71xx_dma_reset(struct ag71xx *ag) ag71xx_wr(ag, AG71XX_REG_RX_STATUS, RX_STATUS_BE | RX_STATUS_OF); ag71xx_wr(ag, AG71XX_REG_TX_STATUS, TX_STATUS_BE | TX_STATUS_UR); - if (ag71xx_rr(ag, AG71XX_REG_RX_STATUS)) - printk(KERN_ALERT "%s: unable to clear DMA Rx status\n", - ag->dev->name); + val = ag71xx_rr(ag, AG71XX_REG_RX_STATUS); + if (val) + printk(KERN_ALERT "%s: unable to clear DMA Rx status: %08x\n", + ag->dev->name, val); + + val = ag71xx_rr(ag, AG71XX_REG_TX_STATUS); - if (ag71xx_rr(ag, AG71XX_REG_TX_STATUS)) - printk(KERN_ALERT "%s: unable to clear DMA Tx status\n", - ag->dev->name); + /* mask out reserved bits */ + val &= ~0xff000000; + + if (val) + printk(KERN_ALERT "%s: unable to clear DMA Tx status: %08x\n", + ag->dev->name, val); ag71xx_dump_dma_regs(ag); } @@ -382,8 +402,13 @@ static void ag71xx_hw_init(struct ag71xx *ag) /* setup FIFO configuration registers */ ag71xx_wr(ag, AG71XX_REG_FIFO_CFG0, FIFO_CFG0_INIT); - ag71xx_wr(ag, AG71XX_REG_FIFO_CFG1, 0x0fff0000); - ag71xx_wr(ag, AG71XX_REG_FIFO_CFG2, 0x00001fff); + if (pdata->is_ar724x) { + ag71xx_wr(ag, AG71XX_REG_FIFO_CFG1, pdata->fifo_cfg1); + ag71xx_wr(ag, AG71XX_REG_FIFO_CFG2, pdata->fifo_cfg2); + } else { + ag71xx_wr(ag, AG71XX_REG_FIFO_CFG1, 0x0fff0000); + ag71xx_wr(ag, AG71XX_REG_FIFO_CFG2, 0x00001fff); + } ag71xx_wr(ag, AG71XX_REG_FIFO_CFG4, FIFO_CFG4_INIT); ag71xx_wr(ag, AG71XX_REG_FIFO_CFG5, FIFO_CFG5_INIT); @@ -410,12 +435,16 @@ static void ag71xx_hw_stop(struct ag71xx *ag) static int ag71xx_open(struct net_device *dev) { struct ag71xx *ag = netdev_priv(dev); - int ret; + int err; - ret = ag71xx_rings_init(ag); - if (ret) + err = ag71xx_phy_connect(ag); + if (err) goto err; + err = ag71xx_rings_init(ag); + if (err) + goto err_ring_cleanup; + napi_enable(&ag->napi); netif_carrier_off(dev); @@ -432,9 +461,10 @@ static int ag71xx_open(struct net_device *dev) return 0; - err: + err_ring_cleanup: ag71xx_rings_cleanup(ag); - return ret; + err: + return err; } static int ag71xx_stop(struct net_device *dev) @@ -457,6 +487,7 @@ static int ag71xx_stop(struct net_device *dev) spin_unlock_irqrestore(&ag->lock, flags); ag71xx_rings_cleanup(ag); + ag71xx_phy_disconnect(ag); return 0; } @@ -793,6 +824,12 @@ static int __init ag71xx_probe(struct platform_device *pdev) goto err_out; } + if (pdata->mii_bus_dev == NULL) { + dev_err(&pdev->dev, "no MII bus device specified\n"); + err = -EINVAL; + goto err_out; + } + dev = alloc_etherdev(sizeof(*ag)); if (!dev) { dev_err(&pdev->dev, "alloc_etherdev failed\n"); @@ -805,8 +842,7 @@ static int __init ag71xx_probe(struct platform_device *pdev) ag = netdev_priv(dev); ag->pdev = pdev; ag->dev = dev; - ag->mii_bus = ag71xx_mdio_bus->mii_bus; - ag->msg_enable = netif_msg_init(ag71xx_debug, + ag->msg_enable = netif_msg_init(ag71xx_msg_level, AG71XX_DEFAULT_MSG_ENABLE); spin_lock_init(&ag->lock); @@ -824,32 +860,18 @@ static int __init ag71xx_probe(struct platform_device *pdev) goto err_free_dev; } - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mac_base2"); - if (!res) { - dev_err(&pdev->dev, "no mac_base2 resource found\n"); - err = -ENXIO; - goto err_unmap_base1; - } - - ag->mac_base2 = ioremap_nocache(res->start, res->end - res->start + 1); - if (!ag->mac_base) { - dev_err(&pdev->dev, "unable to ioremap mac_base2\n"); - err = -ENOMEM; - goto err_unmap_base1; - } - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mii_ctrl"); if (!res) { dev_err(&pdev->dev, "no mii_ctrl resource found\n"); err = -ENXIO; - goto err_unmap_base2; + goto err_unmap_base; } ag->mii_ctrl = ioremap_nocache(res->start, res->end - res->start + 1); if (!ag->mii_ctrl) { dev_err(&pdev->dev, "unable to ioremap mii_ctrl\n"); err = -ENOMEM; - goto err_unmap_base2; + goto err_unmap_base; } dev->irq = platform_get_irq(pdev, 0); @@ -902,23 +924,15 @@ static int __init ag71xx_probe(struct platform_device *pdev) mutex_unlock(&ag->mii_bus->mdio_lock); } - err = ag71xx_phy_connect(ag); - if (err) - goto err_unregister_netdev; - platform_set_drvdata(pdev, dev); return 0; - err_unregister_netdev: - unregister_netdev(dev); err_free_irq: free_irq(dev->irq, dev); err_unmap_mii_ctrl: iounmap(ag->mii_ctrl); - err_unmap_base2: - iounmap(ag->mac_base2); - err_unmap_base1: + err_unmap_base: iounmap(ag->mac_base); err_free_dev: kfree(dev); @@ -934,11 +948,9 @@ static int __exit ag71xx_remove(struct platform_device *pdev) if (dev) { struct ag71xx *ag = netdev_priv(dev); - ag71xx_phy_disconnect(ag); unregister_netdev(dev); free_irq(dev->irq, dev); iounmap(ag->mii_ctrl); - iounmap(ag->mac_base2); iounmap(ag->mac_base); kfree(dev); platform_set_drvdata(pdev, NULL);