X-Git-Url: http://git.ozo.com/?p=openwrt-10.03%2F.git;a=blobdiff_plain;f=target%2Flinux%2Far71xx%2Ffiles%2Fdrivers%2Fnet%2Fag71xx%2Fag71xx_main.c;h=0eb5ce15bd49319366ac9281717ce3310539d022;hp=54a6005b5936672d27c08bcf6ab85b5e1411f562;hb=bd1ff6ccf38da4bc8de14989cdc904dcfdd7e630;hpb=3b5ec501f5b1e70443fbb356b181ec167af5a9c4 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 54a6005b5..0eb5ce15b 100644 --- a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_main.c +++ b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_main.c @@ -14,14 +14,14 @@ #include "ag71xx.h" #define AG71XX_DEFAULT_MSG_ENABLE \ - ( NETIF_MSG_DRV \ + (NETIF_MSG_DRV \ | NETIF_MSG_PROBE \ | NETIF_MSG_LINK \ | NETIF_MSG_TIMER \ | NETIF_MSG_IFDOWN \ | NETIF_MSG_IFUP \ | NETIF_MSG_RX_ERR \ - | NETIF_MSG_TX_ERR ) + | NETIF_MSG_TX_ERR) static int ag71xx_msg_level = -1; @@ -119,14 +119,15 @@ static int ag71xx_ring_alloc(struct ag71xx_ring *ring, unsigned int size) } for (i = 0; i < size; i++) { - ring->buf[i].desc = (struct ag71xx_desc *)&ring->descs_cpu[i * ring->desc_size]; + int idx = i * ring->desc_size; + ring->buf[i].desc = (struct ag71xx_desc *)&ring->descs_cpu[idx]; DBG("ag71xx: ring %p, desc %d at %p\n", ring, i, ring->buf[i].desc); } return 0; - err: +err: return err; } @@ -192,9 +193,28 @@ static void ag71xx_ring_rx_clean(struct ag71xx *ag) } } +static int ag71xx_rx_reserve(struct ag71xx *ag) +{ + int reserve = 0; + + if (ag71xx_get_pdata(ag)->is_ar724x) { + if (!ag71xx_has_ar8216(ag)) + reserve = 2; + + if (ag->phy_dev) + reserve += 4 - (ag->phy_dev->pkt_align % 4); + + reserve %= 4; + } + + return reserve + AG71XX_RX_PKT_RESERVE; +} + + static int ag71xx_ring_rx_init(struct ag71xx *ag) { struct ag71xx_ring *ring = &ag->rx_ring; + unsigned int reserve = ag71xx_rx_reserve(ag); unsigned int i; int ret; @@ -212,14 +232,14 @@ static int ag71xx_ring_rx_init(struct ag71xx *ag) struct sk_buff *skb; dma_addr_t dma_addr; - skb = dev_alloc_skb(AG71XX_RX_PKT_SIZE + AG71XX_RX_PKT_RESERVE); + skb = dev_alloc_skb(AG71XX_RX_PKT_SIZE + reserve); if (!skb) { ret = -ENOMEM; break; } skb->dev = ag->dev; - skb_reserve(skb, AG71XX_RX_PKT_RESERVE); + skb_reserve(skb, reserve); dma_addr = dma_map_single(&ag->dev->dev, skb->data, AG71XX_RX_PKT_SIZE, @@ -242,6 +262,7 @@ static int ag71xx_ring_rx_init(struct ag71xx *ag) static int ag71xx_ring_rx_refill(struct ag71xx *ag) { struct ag71xx_ring *ring = &ag->rx_ring; + unsigned int reserve = ag71xx_rx_reserve(ag); unsigned int count; count = 0; @@ -254,12 +275,11 @@ static int ag71xx_ring_rx_refill(struct ag71xx *ag) dma_addr_t dma_addr; struct sk_buff *skb; - skb = dev_alloc_skb(AG71XX_RX_PKT_SIZE + - AG71XX_RX_PKT_RESERVE); + skb = dev_alloc_skb(AG71XX_RX_PKT_SIZE + reserve); if (skb == NULL) break; - skb_reserve(skb, AG71XX_RX_PKT_RESERVE); + skb_reserve(skb, reserve); skb->dev = ag->dev; dma_addr = dma_map_single(&ag->dev->dev, skb->data, @@ -560,8 +580,6 @@ static int ag71xx_open(struct net_device *dev) if (ret) goto err; - ag71xx_hw_init(ag); - napi_enable(&ag->napi); netif_carrier_off(dev); @@ -578,7 +596,7 @@ static int ag71xx_open(struct net_device *dev) return 0; - err: +err: ag71xx_rings_cleanup(ag); return ret; } @@ -634,6 +652,7 @@ static netdev_tx_t ag71xx_hard_start_xmit(struct sk_buff *skb, DMA_TO_DEVICE); ring->buf[i].skb = skb; + ring->buf[i].timestamp = jiffies; /* setup descriptor fields */ desc->data = (u32) dma_addr; @@ -655,7 +674,7 @@ static netdev_tx_t ag71xx_hard_start_xmit(struct sk_buff *skb, return NETDEV_TX_OK; - err_drop: +err_drop: dev->stats.tx_dropped++; dev_kfree_skb(skb); @@ -664,7 +683,6 @@ static netdev_tx_t ag71xx_hard_start_xmit(struct sk_buff *skb, static int ag71xx_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { - struct mii_ioctl_data *data = (struct mii_ioctl_data *) &ifr->ifr_data; struct ag71xx *ag = netdev_priv(dev); int ret; @@ -696,7 +714,7 @@ static int ag71xx_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) if (ag->phy_dev == NULL) break; - return phy_mii_ioctl(ag->phy_dev, data, cmd); + return phy_mii_ioctl(ag->phy_dev, if_mii(ifr), cmd); default: break; @@ -726,8 +744,13 @@ static void ag71xx_tx_timeout(struct net_device *dev) static void ag71xx_restart_work_func(struct work_struct *work) { struct ag71xx *ag = container_of(work, struct ag71xx, restart_work); + struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); ag71xx_stop(ag->dev); + + if (pdata->is_ar724x) + ag71xx_hw_init(ag); + ag71xx_open(ag->dev); } @@ -767,32 +790,6 @@ static int ag71xx_tx_packets(struct ag71xx *ag) return sent; } -static int ag71xx_rx_copy_skb(struct ag71xx *ag, struct sk_buff **pskb, - int pktlen) -{ - struct sk_buff *copy_skb; - - if (ag->phy_dev && (ag->phy_dev->pkt_align % 4) == 2) - goto keep; - - copy_skb = netdev_alloc_skb(ag->dev, pktlen + NET_IP_ALIGN); - if (!copy_skb) - return -ENOMEM; - - skb_reserve(copy_skb, NET_IP_ALIGN); - skb_copy_from_linear_data(*pskb, copy_skb->data, pktlen); - skb_put(copy_skb, pktlen); - - dev_kfree_skb_any(*pskb); - *pskb = copy_skb; - - return 0; - - keep: - skb_put(*pskb, pktlen); - return 0; -} - static int ag71xx_rx_packets(struct ag71xx *ag, int limit) { struct net_device *dev = ag->dev; @@ -830,10 +827,9 @@ static int ag71xx_rx_packets(struct ag71xx *ag, int limit) dev->stats.rx_packets++; dev->stats.rx_bytes += pktlen; + skb_put(skb, pktlen); if (ag71xx_has_ar8216(ag)) err = ag71xx_remove_ar8216_header(ag, skb, pktlen); - else - err = ag71xx_rx_copy_skb(ag, &skb, pktlen); if (err) { dev->stats.rx_dropped++; @@ -915,12 +911,12 @@ static int ag71xx_poll(struct napi_struct *napi, int limit) return rx_done; } - more: +more: DBG("%s: stay in polling mode, rx=%d, tx=%d, limit=%d\n", dev->name, rx_done, tx_done, limit); return rx_done; - oom: +oom: if (netif_msg_rx_err(ag)) printk(KERN_DEBUG "%s: out of memory\n", dev->name); @@ -997,7 +993,7 @@ static const struct net_device_ops ag71xx_netdev_ops = { #endif }; -static int __init ag71xx_probe(struct platform_device *pdev) +static int __devinit ag71xx_probe(struct platform_device *pdev) { struct net_device *dev; struct resource *res; @@ -1064,7 +1060,7 @@ static int __init ag71xx_probe(struct platform_device *pdev) dev->irq = platform_get_irq(pdev, 0); err = request_irq(dev->irq, ag71xx_interrupt, - IRQF_DISABLED | IRQF_SAMPLE_RANDOM, + IRQF_DISABLED, dev->name, dev); if (err) { dev_err(&pdev->dev, "unable to request IRQ %d\n", dev->irq); @@ -1112,24 +1108,24 @@ static int __init ag71xx_probe(struct platform_device *pdev) return 0; - err_phy_disconnect: +err_phy_disconnect: ag71xx_phy_disconnect(ag); - err_unregister_netdev: +err_unregister_netdev: unregister_netdev(dev); - err_free_irq: +err_free_irq: free_irq(dev->irq, dev); - err_unmap_mii_ctrl: +err_unmap_mii_ctrl: iounmap(ag->mii_ctrl); - err_unmap_base: +err_unmap_base: iounmap(ag->mac_base); - err_free_dev: +err_free_dev: kfree(dev); - err_out: +err_out: platform_set_drvdata(pdev, NULL); return err; } -static int __exit ag71xx_remove(struct platform_device *pdev) +static int __devexit ag71xx_remove(struct platform_device *pdev) { struct net_device *dev = platform_get_drvdata(pdev); @@ -1175,11 +1171,11 @@ static int __init ag71xx_module_init(void) return 0; - err_mdio_exit: +err_mdio_exit: ag71xx_mdio_driver_exit(); - err_debugfs_exit: +err_debugfs_exit: ag71xx_debugfs_root_exit(); - err_out: +err_out: return ret; }