X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fnet%2F8139too.c;h=7d5b69adbed77ccbc58b5973669e6de4dba7c1a7;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=426273c0ccd77520296385f8563d99ed54655076;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c index 426273c0c..7d5b69adb 100644 --- a/drivers/net/8139too.c +++ b/drivers/net/8139too.c @@ -87,8 +87,6 @@ "rtl8139-diag -mmmaaavvveefN" output enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log - See 8139too.txt for more details. - */ #define DRV_NAME "8139too" @@ -110,7 +108,6 @@ #include #include #include -#include #include #include #include @@ -171,7 +168,11 @@ static int debug = -1; * Receive ring size * Warning: 64K ring has hardware issues and may lock up. */ +#if defined(CONFIG_SH_DREAMCAST) +#define RX_BUF_IDX 1 /* 16K ring */ +#else #define RX_BUF_IDX 2 /* 32K ring */ +#endif #define RX_BUF_LEN (8192 << RX_BUF_IDX) #define RX_BUF_PAD 16 #define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */ @@ -565,7 +566,6 @@ struct rtl8139_private { void *mmio_addr; int drv_flags; struct pci_dev *pci_dev; - u32 pci_state[16]; u32 msg_enable; struct net_device_stats stats; unsigned char *rx_ring; @@ -591,16 +591,18 @@ struct rtl8139_private { int time_to_die; struct mii_if_info mii; unsigned int regs_len; + unsigned long fifo_copy_timeout; }; MODULE_AUTHOR ("Jeff Garzik "); MODULE_DESCRIPTION ("RealTek RTL-8139 Fast Ethernet driver"); MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_VERSION); -MODULE_PARM (multicast_filter_limit, "i"); -MODULE_PARM (media, "1-" __MODULE_STRING(MAX_UNITS) "i"); -MODULE_PARM (full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); -MODULE_PARM (debug, "i"); +module_param(multicast_filter_limit, int, 0); +module_param_array(media, int, NULL, 0); +module_param_array(full_duplex, int, NULL, 0); +module_param(debug, int, 0); MODULE_PARM_DESC (debug, "8139too bitmapped message enable number"); MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses"); MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); @@ -611,7 +613,7 @@ static int rtl8139_open (struct net_device *dev); 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 val); -static inline void rtl8139_start_thread(struct net_device *dev); +static void rtl8139_start_thread(struct net_device *dev); static void rtl8139_tx_timeout (struct net_device *dev); static void rtl8139_init_ring (struct net_device *dev); static int rtl8139_start_xmit (struct sk_buff *skb, @@ -775,7 +777,7 @@ static int __devinit rtl8139_init_board (struct pci_dev *pdev, u8 tmp8; int rc; unsigned int i; - u32 pio_start, pio_end, pio_flags, pio_len; + unsigned long pio_start, pio_end, pio_flags, pio_len; unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; u32 version; @@ -1622,8 +1624,7 @@ static int rtl8139_thread (void *data) do { timeout = interruptible_sleep_on_timeout (&tp->thr_wait, timeout); /* make swsusp happy with our thread */ - if (current->flags & PF_FREEZE) - refrigerator(PF_FREEZE); + try_to_freeze(PF_FREEZE); } while (!signal_pending (current) && (timeout > 0)); if (signal_pending (current)) { @@ -1633,7 +1634,8 @@ static int rtl8139_thread (void *data) if (tp->time_to_die) break; - rtnl_lock (); + if (rtnl_lock_interruptible ()) + break; rtl8139_thread_iter (dev, tp, tp->mmio_addr); rtnl_unlock (); } @@ -1641,7 +1643,7 @@ static int rtl8139_thread (void *data) complete_and_exit (&tp->thr_exited, 0); } -static inline void rtl8139_start_thread(struct net_device *dev) +static void rtl8139_start_thread(struct net_device *dev) { struct rtl8139_private *tp = dev->priv; @@ -1677,11 +1679,17 @@ static void rtl8139_tx_timeout (struct net_device *dev) u8 tmp8; unsigned long flags; - DPRINTK ("%s: Transmit timeout, status %2.2x %4.4x " - "media %2.2x.\n", dev->name, - RTL_R8 (ChipCmd), - RTL_R16 (IntrStatus), - RTL_R8 (MediaStatus)); + printk (KERN_DEBUG "%s: Transmit timeout, status %2.2x %4.4x %4.4x " + "media %2.2x.\n", dev->name, RTL_R8 (ChipCmd), + RTL_R16(IntrStatus), RTL_R16(IntrMask), RTL_R8(MediaStatus)); + /* Emit info to figure out what went wrong. */ + printk (KERN_DEBUG "%s: Tx queue start entry %ld dirty entry %ld.\n", + dev->name, tp->cur_tx, tp->dirty_tx); + for (i = 0; i < NUM_TX_DESC; i++) + printk (KERN_DEBUG "%s: Tx descriptor %d is %8.8lx.%s\n", + dev->name, i, RTL_R32 (TxStatus0 + (i * 4)), + i == tp->dirty_tx % NUM_TX_DESC ? + " (queue head)" : ""); tp->xstats.tx_timeouts++; @@ -1694,15 +1702,6 @@ static void rtl8139_tx_timeout (struct net_device *dev) /* Disable interrupts by clearing the interrupt mask. */ RTL_W16 (IntrMask, 0x0000); - /* Emit info to figure out what went wrong. */ - printk (KERN_DEBUG "%s: Tx queue start entry %ld dirty entry %ld.\n", - dev->name, tp->cur_tx, tp->dirty_tx); - for (i = 0; i < NUM_TX_DESC; i++) - printk (KERN_DEBUG "%s: Tx descriptor %d is %8.8lx.%s\n", - dev->name, i, RTL_R32 (TxStatus0 + (i * 4)), - i == tp->dirty_tx % NUM_TX_DESC ? - " (queue head)" : ""); - /* Stop a shared interrupt from scavenging while we are. */ spin_lock_irqsave (&tp->lock, flags); rtl8139_tx_clear (tp); @@ -1714,7 +1713,6 @@ static void rtl8139_tx_timeout (struct net_device *dev) netif_wake_queue (dev); } spin_unlock(&tp->rx_lock); - } @@ -1929,6 +1927,24 @@ static __inline__ void wrap_copy(struct sk_buff *skb, const unsigned char *ring, } #endif +static void rtl8139_isr_ack(struct rtl8139_private *tp) +{ + void *ioaddr = tp->mmio_addr; + u16 status; + + status = RTL_R16 (IntrStatus) & RxAckBits; + + /* Clear out errors and receive interrupts */ + if (likely(status != 0)) { + if (unlikely(status & (RxFIFOOver | RxOverflow))) { + tp->stats.rx_errors++; + if (status & RxFIFOOver) + tp->stats.rx_fifo_errors++; + } + RTL_W16_F (IntrStatus, RxAckBits); + } +} + static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, int budget) { @@ -1936,9 +1952,10 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, int received = 0; unsigned char *rx_ring = tp->rx_ring; unsigned int cur_rx = tp->cur_rx; + unsigned int rx_size = 0; DPRINTK ("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, + " free to %4.4x, Cmd %2.2x.\n", dev->name, (u16)cur_rx, RTL_R16 (RxBufAddr), RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); @@ -1946,10 +1963,8 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { u32 ring_offset = cur_rx % RX_BUF_LEN; u32 rx_status; - unsigned int rx_size; unsigned int pkt_size; struct sk_buff *skb; - u16 status; rmb(); @@ -1978,10 +1993,24 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, * since EarlyRx is disabled. */ if (unlikely(rx_size == 0xfff0)) { + if (!tp->fifo_copy_timeout) + tp->fifo_copy_timeout = jiffies + 2; + else if (time_after(jiffies, tp->fifo_copy_timeout)) { + DPRINTK ("%s: hung FIFO. Reset.", dev->name); + rx_size = 0; + goto no_early_rx; + } + if (netif_msg_intr(tp)) { + printk(KERN_DEBUG "%s: fifo copy in progress.", + dev->name); + } tp->xstats.early_rx++; - goto done; + break; } +no_early_rx: + tp->fifo_copy_timeout = 0; + /* If Rx err or invalid rx_size/rx_status received * (which happens if we get lost in the ring), * Rx process gets reset, so we abort any further @@ -1991,7 +2020,8 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, (rx_size < 8) || (!(rx_status & RxStatusOK)))) { rtl8139_rx_err (rx_status, dev, tp, ioaddr); - return -1; + received = -1; + goto out; } /* Malloc up new buffer, compatible with net-2e. */ @@ -2027,19 +2057,11 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; RTL_W16 (RxBufPtr, (u16) (cur_rx - 16)); - /* Clear out errors and receive interrupts */ - status = RTL_R16 (IntrStatus) & RxAckBits; - if (likely(status != 0)) { - if (unlikely(status & (RxFIFOOver | RxOverflow))) { - tp->stats.rx_errors++; - if (status & RxFIFOOver) - tp->stats.rx_fifo_errors++; - } - RTL_W16_F (IntrStatus, RxAckBits); - } + rtl8139_isr_ack(tp); } - done: + if (unlikely(!received || rx_size == 0xfff0)) + rtl8139_isr_ack(tp); #if RTL8139_DEBUG > 1 DPRINTK ("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x," @@ -2049,6 +2071,15 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, #endif tp->cur_rx = cur_rx; + + /* + * The receive buffer should be mostly empty. + * Tell NAPI to reenable the Rx irq. + */ + if (tp->fifo_copy_timeout) + received = budget; + +out: return received; } @@ -2458,14 +2489,13 @@ static struct ethtool_ops rtl8139_ethtool_ops = { static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { struct rtl8139_private *np = dev->priv; - struct mii_ioctl_data *data = (struct mii_ioctl_data *) & rq->ifr_data; int rc; if (!netif_running(dev)) return -EINVAL; spin_lock_irq(&np->lock); - rc = generic_mii_ioctl(&np->mii, data, cmd, NULL); + rc = generic_mii_ioctl(&np->mii, if_mii(rq), cmd, NULL); spin_unlock_irq(&np->lock); return rc; @@ -2558,6 +2588,8 @@ static int rtl8139_suspend (struct pci_dev *pdev, u32 state) void *ioaddr = tp->mmio_addr; unsigned long flags; + pci_save_state (pdev); + if (!netif_running (dev)) return 0; @@ -2575,8 +2607,7 @@ static int rtl8139_suspend (struct pci_dev *pdev, u32 state) spin_unlock_irqrestore (&tp->lock, flags); - pci_set_power_state (pdev, 3); - pci_save_state (pdev, tp->pci_state); + pci_set_power_state (pdev, PCI_D3hot); return 0; } @@ -2585,12 +2616,11 @@ static int rtl8139_suspend (struct pci_dev *pdev, u32 state) static int rtl8139_resume (struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = dev->priv; + pci_restore_state (pdev); if (!netif_running (dev)) return 0; - pci_restore_state (pdev, tp->pci_state); - pci_set_power_state (pdev, 0); + pci_set_power_state (pdev, PCI_D0); rtl8139_init_ring (dev); rtl8139_hw_start (dev); netif_device_attach (dev);