--- linux-2.6.22.14/drivers/net/via-rhine.c 2008-01-22 14:03:03.000000000 +0200 +++ linux/drivers/net/via-rhine.c 2008-01-15 11:04:02.000000000 +0200 @@ -48,6 +48,9 @@ static int rx_copybreak; power state D3 so PXE booting fails. bootparam(7): via-rhine.avoid_D3=1 */ static int avoid_D3; +/* Work-around for systems, where link should be on immediately after enable */ +static int disable_sleep_mode; + /* * In case you are looking for 'options[]' or 'full_duplex[]', they * are gone. Use ethtool(8) instead. @@ -65,13 +68,9 @@ static const int multicast_filter_limit Making the Tx ring too large decreases the effectiveness of channel bonding and packet priority. There are no ill effects from too-large receive rings. */ -#define TX_RING_SIZE 16 -#define TX_QUEUE_LEN 10 /* Limit ring entries actually used. */ -#ifdef CONFIG_VIA_RHINE_NAPI -#define RX_RING_SIZE 64 -#else -#define RX_RING_SIZE 16 -#endif +#define TX_RING_SIZE 128 +#define TX_QUEUE_LEN 120 /* Limit ring entries actually used. */ +#define RX_RING_SIZE 128 /* Operational parameters that usually are not changed. */ @@ -101,6 +100,7 @@ static const int multicast_filter_limit #include #include #include +#include #include /* Processor type for cache alignment. */ #include #include @@ -118,6 +118,10 @@ KERN_INFO DRV_NAME ".c:v1.10-LK" DRV_VER #else #endif +#ifdef CONFIG_MIPS_MIKROTIK +#undef USE_MMIO +#endif + MODULE_AUTHOR("Donald Becker "); MODULE_DESCRIPTION("VIA Rhine PCI Fast Ethernet driver"); MODULE_LICENSE("GPL"); @@ -126,10 +130,12 @@ module_param(max_interrupt_work, int, 0) module_param(debug, int, 0); module_param(rx_copybreak, int, 0); module_param(avoid_D3, bool, 0); +module_param(disable_sleep_mode, bool, 0); MODULE_PARM_DESC(max_interrupt_work, "VIA Rhine maximum events handled per interrupt"); MODULE_PARM_DESC(debug, "VIA Rhine debug level (0-7)"); MODULE_PARM_DESC(rx_copybreak, "VIA Rhine copy breakpoint for copy-only-tiny-frames"); MODULE_PARM_DESC(avoid_D3, "Avoid power state D3 (work-around for broken BIOSes)"); +MODULE_PARM_DESC(disable_sleep_mode, "Completely disable VIA Rhine D3"); /* Theory of Operation @@ -400,6 +406,16 @@ struct rhine_private { void __iomem *base; }; +static int rhine_change_mtu(struct net_device *dev, int new_mtu) { + struct rhine_private *rp = netdev_priv(dev); + + if (new_mtu < 68 || new_mtu > 1600) return -EINVAL; + if ((rp->quirks & rqRhineI) && new_mtu > 1500) return -EINVAL; + + dev->mtu = new_mtu; + return 0; +} + static int mdio_read(struct net_device *dev, int phy_id, int location); static void mdio_write(struct net_device *dev, int phy_id, int location, int value); static int rhine_open(struct net_device *dev); @@ -575,31 +591,57 @@ static void rhine_poll(struct net_device } #endif -#ifdef CONFIG_VIA_RHINE_NAPI static int rhine_napipoll(struct net_device *dev, int *budget) { struct rhine_private *rp = netdev_priv(dev); void __iomem *ioaddr = rp->base; int done, limit = min(dev->quota, *budget); + u32 intr_status; + + intr_status = get_intr_status(dev); + + /* Acknowledge all of the current interrupt sources ASAP. */ + if (intr_status & IntrTxDescRace) + iowrite8(0x08, ioaddr + IntrStatus2); + iowrite16(intr_status & 0xffff, ioaddr + IntrStatus); + + if (intr_status & IntrTxErrSummary) { + /* Avoid scavenging before Tx engine turned off */ + RHINE_WAIT_FOR(!(ioread8(ioaddr+ChipCmd) & CmdTxOn)); + if (debug > 2 && ioread8(ioaddr+ChipCmd) & CmdTxOn) + printk(KERN_WARNING "%s: " + "rhine_interrupt() Tx engine" + "still on.\n", dev->name); + } + rhine_tx(dev); + + /* Abnormal error summary/uncommon events handlers. */ + if (intr_status & (IntrPCIErr | IntrLinkChange | + IntrStatsMax | IntrTxError | IntrTxAborted | + IntrTxUnderrun | IntrTxDescRace)) + rhine_error(dev, intr_status); + done = rhine_rx(dev, limit); *budget -= done; dev->quota -= done; - if (done < limit) { + if (done >= limit) + return 1; + if (get_intr_status(dev) & 0xffff) + return 1; + netif_rx_complete(dev); + /* Enable interrupts by setting the interrupt mask. */ iowrite16(IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow | IntrRxDropped | IntrRxNoBuf | IntrTxAborted | IntrTxDone | IntrTxError | IntrTxUnderrun | IntrPCIErr | IntrStatsMax | IntrLinkChange, ioaddr + IntrEnable); + return 0; - } - else - return 1; } -#endif static void rhine_hw_init(struct net_device *dev, long pioaddr) { @@ -612,8 +654,10 @@ static void rhine_hw_init(struct net_dev if (rp->quirks & rqRhineI) msleep(5); +#if !defined CONFIG_MIPS_MIKROTIK && !defined CONFIG_RB_PPC /* Reload EEPROM controlled bytes cleared by soft reset */ rhine_reload_eeprom(pioaddr, dev); +#endif } static int __devinit rhine_init_one(struct pci_dev *pdev, @@ -672,6 +716,7 @@ static int __devinit rhine_init_one(stru rc = pci_enable_device(pdev); if (rc) goto err_out; + pci_set_power_state(pdev, PCI_D0); /* this should always be supported */ rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); @@ -777,14 +822,13 @@ static int __devinit rhine_init_one(stru dev->do_ioctl = netdev_ioctl; dev->ethtool_ops = &netdev_ethtool_ops; dev->tx_timeout = rhine_tx_timeout; + dev->change_mtu = rhine_change_mtu; dev->watchdog_timeo = TX_TIMEOUT; #ifdef CONFIG_NET_POLL_CONTROLLER dev->poll_controller = rhine_poll; #endif -#ifdef CONFIG_VIA_RHINE_NAPI dev->poll = rhine_napipoll; dev->weight = 64; -#endif if (rp->quirks & rqRhineI) dev->features |= NETIF_F_SG|NETIF_F_HW_CSUM; @@ -834,6 +878,14 @@ static int __devinit rhine_init_one(stru printk(KERN_INFO "%s: No D3 power state at shutdown.\n", dev->name); + if (!disable_sleep_mode) { + /* shut down until somebody really needs it */ + rtnl_lock(); + iowrite8(0x80, ioaddr + 0xa1); + pci_set_power_state(pdev, PCI_D3hot); + rtnl_unlock(); + } + return 0; err_out_unmap: @@ -1115,6 +1167,8 @@ static int mdio_read(struct net_device * void __iomem *ioaddr = rp->base; int result; + if (rp->pdev->current_state != PCI_D0) return 0; + rhine_disable_linkmon(ioaddr, rp->quirks); /* rhine_disable_linkmon already cleared MIICmd */ @@ -1133,6 +1187,8 @@ static void mdio_write(struct net_device struct rhine_private *rp = netdev_priv(dev); void __iomem *ioaddr = rp->base; + if (rp->pdev->current_state != PCI_D0) return; + rhine_disable_linkmon(ioaddr, rp->quirks); /* rhine_disable_linkmon already cleared MIICmd */ @@ -1151,6 +1207,9 @@ static int rhine_open(struct net_device void __iomem *ioaddr = rp->base; int rc; + pci_enable_device(rp->pdev); + pci_set_power_state(rp->pdev, PCI_D0); + rc = request_irq(rp->pdev->irq, &rhine_interrupt, IRQF_SHARED, dev->name, dev); if (rc) @@ -1261,7 +1320,7 @@ static int rhine_start_tx(struct sk_buff cpu_to_le32(TXDESC | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN)); /* lock eth irq */ - spin_lock_irq(&rp->lock); + spin_lock(&rp->lock); wmb(); rp->tx_ring[entry].tx_status = cpu_to_le32(DescOwn); wmb(); @@ -1280,7 +1339,7 @@ static int rhine_start_tx(struct sk_buff dev->trans_start = jiffies; - spin_unlock_irq(&rp->lock); + spin_unlock(&rp->lock); if (debug > 4) { printk(KERN_DEBUG "%s: Transmit frame #%d queued in slot %d.\n", @@ -1296,68 +1355,13 @@ static irqreturn_t rhine_interrupt(int i struct net_device *dev = dev_instance; struct rhine_private *rp = netdev_priv(dev); void __iomem *ioaddr = rp->base; - u32 intr_status; - int boguscnt = max_interrupt_work; - int handled = 0; - - while ((intr_status = get_intr_status(dev))) { - handled = 1; - - /* Acknowledge all of the current interrupt sources ASAP. */ - if (intr_status & IntrTxDescRace) - iowrite8(0x08, ioaddr + IntrStatus2); - iowrite16(intr_status & 0xffff, ioaddr + IntrStatus); - IOSYNC; - - if (debug > 4) - printk(KERN_DEBUG "%s: Interrupt, status %8.8x.\n", - dev->name, intr_status); - - if (intr_status & (IntrRxDone | IntrRxErr | IntrRxDropped | - IntrRxWakeUp | IntrRxEmpty | IntrRxNoBuf)) { -#ifdef CONFIG_VIA_RHINE_NAPI - iowrite16(IntrTxAborted | - IntrTxDone | IntrTxError | IntrTxUnderrun | - IntrPCIErr | IntrStatsMax | IntrLinkChange, - ioaddr + IntrEnable); + if (get_intr_status(dev)) { + iowrite16(0, ioaddr + IntrEnable); netif_rx_schedule(dev); -#else - rhine_rx(dev, RX_RING_SIZE); -#endif + return IRQ_HANDLED; } - - if (intr_status & (IntrTxErrSummary | IntrTxDone)) { - if (intr_status & IntrTxErrSummary) { - /* Avoid scavenging before Tx engine turned off */ - RHINE_WAIT_FOR(!(ioread8(ioaddr+ChipCmd) & CmdTxOn)); - if (debug > 2 && - ioread8(ioaddr+ChipCmd) & CmdTxOn) - printk(KERN_WARNING "%s: " - "rhine_interrupt() Tx engine" - "still on.\n", dev->name); - } - rhine_tx(dev); - } - - /* Abnormal error summary/uncommon events handlers. */ - if (intr_status & (IntrPCIErr | IntrLinkChange | - IntrStatsMax | IntrTxError | IntrTxAborted | - IntrTxUnderrun | IntrTxDescRace)) - rhine_error(dev, intr_status); - - if (--boguscnt < 0) { - printk(KERN_WARNING "%s: Too much work at interrupt, " - "status=%#8.8x.\n", - dev->name, intr_status); - break; - } - } - - if (debug > 3) - printk(KERN_DEBUG "%s: exiting interrupt, status=%8.8x.\n", - dev->name, ioread16(ioaddr + IntrStatus)); - return IRQ_RETVAL(handled); + return IRQ_NONE; } /* This routine is logically part of the interrupt handler, but isolated @@ -1413,7 +1417,7 @@ static void rhine_tx(struct net_device * rp->tx_skbuff[entry]->len, PCI_DMA_TODEVICE); } - dev_kfree_skb_irq(rp->tx_skbuff[entry]); + dev_kfree_skb(rp->tx_skbuff[entry]); rp->tx_skbuff[entry] = NULL; entry = (++rp->dirty_tx) % TX_RING_SIZE; } @@ -1512,15 +1516,11 @@ static int rhine_rx(struct net_device *d skb_put(skb, pkt_len); pci_unmap_single(rp->pdev, rp->rx_skbuff_dma[entry], - rp->rx_buf_sz, + pkt_len, PCI_DMA_FROMDEVICE); } skb->protocol = eth_type_trans(skb, dev); -#ifdef CONFIG_VIA_RHINE_NAPI netif_receive_skb(skb); -#else - netif_rx(skb); -#endif dev->last_rx = jiffies; rp->stats.rx_bytes += pkt_len; rp->stats.rx_packets++; @@ -1858,6 +1858,11 @@ static int rhine_close(struct net_device free_tbufs(dev); free_ring(dev); + if (!disable_sleep_mode) { + iowrite8(0x80, ioaddr + 0xa1); + pci_set_power_state(rp->pdev, PCI_D3hot); + } + return 0; }