diff -r 2c22f3bea8ba -r a89e2bedf004 devices/r8169-2.6.31-ethercat.c --- a/devices/r8169-2.6.31-ethercat.c Fri Mar 19 13:27:08 2010 +0100 +++ b/devices/r8169-2.6.31-ethercat.c Thu Apr 29 14:05:15 2010 +0200 @@ -56,6 +56,9 @@ #define TX_BUFFS_AVAIL(tp) \ (tp->dirty_tx + NUM_TX_DESC - tp->cur_tx - 1) +/* Maximum events (Rx packets, etc.) to handle at each interrupt. */ +static const int max_interrupt_work = 20; + /* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). The RTL chips use a 64 element hash table based on the Ethernet CRC. */ static const int multicast_filter_limit = 32; @@ -68,6 +71,7 @@ #define RX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ #define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ #define EarlyTxThld 0x3F /* 0x3F means NO early transmit */ +#define RxPacketMaxSize 0x3FE8 /* 16K - 1 - ETH_HLEN - VLAN - CRC... */ #define SafeMtu 0x1c20 /* ... actually life sucks beyond ~7k */ #define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ @@ -95,7 +99,6 @@ #define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg))) enum mac_version { - RTL_GIGA_MAC_NONE = 0x00, RTL_GIGA_MAC_VER_01 = 0x01, // 8169 RTL_GIGA_MAC_VER_02 = 0x02, // 8169S RTL_GIGA_MAC_VER_03 = 0x03, // 8110S @@ -440,22 +443,6 @@ RTL_FEATURE_GMII = (1 << 2), }; -struct rtl8169_counters { - __le64 tx_packets; - __le64 rx_packets; - __le64 tx_errors; - __le32 rx_errors; - __le16 rx_missed; - __le16 align_errors; - __le32 tx_one_collision; - __le32 tx_multi_collision; - __le64 rx_unicast; - __le64 rx_broadcast; - __le32 rx_multicast; - __le16 tx_aborted; - __le16 tx_underun; -}; - struct rtl8169_private { void __iomem *mmio_addr; /* memory map physical address */ struct pci_dev *pci_dev; /* Index of PCI device */ @@ -482,6 +469,7 @@ u16 intr_event; u16 napi_event; u16 intr_mask; + int phy_auto_nego_reg; int phy_1000_ctrl_reg; #ifdef CONFIG_R8169_VLAN struct vlan_group *vlgrp; @@ -492,13 +480,11 @@ void (*hw_start)(struct net_device *); unsigned int (*phy_reset_pending)(void __iomem *); unsigned int (*link_ok)(void __iomem *); - int (*do_ioctl)(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd); int pcie_cap; struct delayed_work task; unsigned features; struct mii_if_info mii; - struct rtl8169_counters counters; ec_device_t *ecdev; unsigned long ec_watchdog_jiffies; @@ -854,81 +840,76 @@ { struct rtl8169_private *tp = netdev_priv(dev); void __iomem *ioaddr = tp->mmio_addr; - int giga_ctrl, bmcr; + int auto_nego, giga_ctrl; + + auto_nego = mdio_read(ioaddr, MII_ADVERTISE); + auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL | + ADVERTISE_100HALF | ADVERTISE_100FULL); + giga_ctrl = mdio_read(ioaddr, MII_CTRL1000); + giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); if (autoneg == AUTONEG_ENABLE) { - int auto_nego; - - auto_nego = mdio_read(ioaddr, MII_ADVERTISE); auto_nego |= (ADVERTISE_10HALF | ADVERTISE_10FULL | ADVERTISE_100HALF | ADVERTISE_100FULL); - auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; - - giga_ctrl = mdio_read(ioaddr, MII_CTRL1000); - giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); - - /* The 8100e/8101e/8102e do Fast Ethernet only. */ - if ((tp->mac_version != RTL_GIGA_MAC_VER_07) && - (tp->mac_version != RTL_GIGA_MAC_VER_08) && - (tp->mac_version != RTL_GIGA_MAC_VER_09) && - (tp->mac_version != RTL_GIGA_MAC_VER_10) && - (tp->mac_version != RTL_GIGA_MAC_VER_13) && - (tp->mac_version != RTL_GIGA_MAC_VER_14) && - (tp->mac_version != RTL_GIGA_MAC_VER_15) && - (tp->mac_version != RTL_GIGA_MAC_VER_16)) { + giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF; + } else { + if (speed == SPEED_10) + auto_nego |= ADVERTISE_10HALF | ADVERTISE_10FULL; + else if (speed == SPEED_100) + auto_nego |= ADVERTISE_100HALF | ADVERTISE_100FULL; + else if (speed == SPEED_1000) giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF; - } else if (netif_msg_link(tp)) { + + if (duplex == DUPLEX_HALF) + auto_nego &= ~(ADVERTISE_10FULL | ADVERTISE_100FULL); + + if (duplex == DUPLEX_FULL) + auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_100HALF); + + /* This tweak comes straight from Realtek's driver. */ + if ((speed == SPEED_100) && (duplex == DUPLEX_HALF) && + ((tp->mac_version == RTL_GIGA_MAC_VER_13) || + (tp->mac_version == RTL_GIGA_MAC_VER_16))) { + auto_nego = ADVERTISE_100HALF | ADVERTISE_CSMA; + } + } + + /* The 8100e/8101e/8102e do Fast Ethernet only. */ + if ((tp->mac_version == RTL_GIGA_MAC_VER_07) || + (tp->mac_version == RTL_GIGA_MAC_VER_08) || + (tp->mac_version == RTL_GIGA_MAC_VER_09) || + (tp->mac_version == RTL_GIGA_MAC_VER_10) || + (tp->mac_version == RTL_GIGA_MAC_VER_13) || + (tp->mac_version == RTL_GIGA_MAC_VER_14) || + (tp->mac_version == RTL_GIGA_MAC_VER_15) || + (tp->mac_version == RTL_GIGA_MAC_VER_16)) { + if ((giga_ctrl & (ADVERTISE_1000FULL | ADVERTISE_1000HALF)) && + netif_msg_link(tp)) { printk(KERN_INFO "%s: PHY does not support 1000Mbps.\n", dev->name); } - - bmcr = BMCR_ANENABLE | BMCR_ANRESTART; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_11) || - (tp->mac_version == RTL_GIGA_MAC_VER_12) || - (tp->mac_version >= RTL_GIGA_MAC_VER_17)) { - /* - * Wake up the PHY. - * Vendor specific (0x1f) and reserved (0x0e) MII - * registers. - */ - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_write(ioaddr, 0x0e, 0x0000); - } - - mdio_write(ioaddr, MII_ADVERTISE, auto_nego); - mdio_write(ioaddr, MII_CTRL1000, giga_ctrl); - } else { - giga_ctrl = 0; - - if (speed == SPEED_10) - bmcr = 0; - else if (speed == SPEED_100) - bmcr = BMCR_SPEED100; - else - return -EINVAL; - - if (duplex == DUPLEX_FULL) - bmcr |= BMCR_FULLDPLX; - + giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); + } + + auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; + + if ((tp->mac_version == RTL_GIGA_MAC_VER_11) || + (tp->mac_version == RTL_GIGA_MAC_VER_12) || + (tp->mac_version >= RTL_GIGA_MAC_VER_17)) { + /* + * Wake up the PHY. + * Vendor specific (0x1f) and reserved (0x0e) MII registers. + */ mdio_write(ioaddr, 0x1f, 0x0000); - } - + mdio_write(ioaddr, 0x0e, 0x0000); + } + + tp->phy_auto_nego_reg = auto_nego; tp->phy_1000_ctrl_reg = giga_ctrl; - mdio_write(ioaddr, MII_BMCR, bmcr); - - if ((tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03)) { - if ((speed == SPEED_100) && (autoneg != AUTONEG_ENABLE)) { - mdio_write(ioaddr, 0x17, 0x2138); - mdio_write(ioaddr, 0x0e, 0x0260); - } else { - mdio_write(ioaddr, 0x17, 0x2108); - mdio_write(ioaddr, 0x0e, 0x0000); - } - } - + mdio_write(ioaddr, MII_ADVERTISE, auto_nego); + mdio_write(ioaddr, MII_CTRL1000, giga_ctrl); + mdio_write(ioaddr, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART); return 0; } @@ -1132,6 +1113,22 @@ "tx_underrun", }; +struct rtl8169_counters { + __le64 tx_packets; + __le64 rx_packets; + __le64 tx_errors; + __le32 rx_errors; + __le16 rx_missed; + __le16 align_errors; + __le32 tx_one_collision; + __le32 tx_multi_collision; + __le64 rx_unicast; + __le64 rx_broadcast; + __le32 rx_multicast; + __le16 tx_aborted; + __le16 tx_underun; +}; + static int rtl8169_get_sset_count(struct net_device *dev, int sset) { switch (sset) { @@ -1142,70 +1139,51 @@ } } -static void rtl8169_update_counters(struct net_device *dev) +static void rtl8169_get_ethtool_stats(struct net_device *dev, + struct ethtool_stats *stats, u64 *data) { struct rtl8169_private *tp = netdev_priv(dev); void __iomem *ioaddr = tp->mmio_addr; struct rtl8169_counters *counters; dma_addr_t paddr; u32 cmd; - int wait = 1000; - - /* - * Some chips are unable to dump tally counters when the receiver - * is disabled. - */ - if ((RTL_R8(ChipCmd) & CmdRxEnb) == 0) - return; + + ASSERT_RTNL(); counters = pci_alloc_consistent(tp->pci_dev, sizeof(*counters), &paddr); if (!counters) return; RTL_W32(CounterAddrHigh, (u64)paddr >> 32); - cmd = (u64)paddr & DMA_BIT_MASK(32); + cmd = (u64)paddr & DMA_32BIT_MASK; RTL_W32(CounterAddrLow, cmd); RTL_W32(CounterAddrLow, cmd | CounterDump); - while (wait--) { - if ((RTL_R32(CounterAddrLow) & CounterDump) == 0) { - /* copy updated counters */ - memcpy(&tp->counters, counters, sizeof(*counters)); + while (RTL_R32(CounterAddrLow) & CounterDump) { + if (msleep_interruptible(1)) break; - } - udelay(10); } RTL_W32(CounterAddrLow, 0); RTL_W32(CounterAddrHigh, 0); + data[0] = le64_to_cpu(counters->tx_packets); + data[1] = le64_to_cpu(counters->rx_packets); + data[2] = le64_to_cpu(counters->tx_errors); + data[3] = le32_to_cpu(counters->rx_errors); + data[4] = le16_to_cpu(counters->rx_missed); + data[5] = le16_to_cpu(counters->align_errors); + data[6] = le32_to_cpu(counters->tx_one_collision); + data[7] = le32_to_cpu(counters->tx_multi_collision); + data[8] = le64_to_cpu(counters->rx_unicast); + data[9] = le64_to_cpu(counters->rx_broadcast); + data[10] = le32_to_cpu(counters->rx_multicast); + data[11] = le16_to_cpu(counters->tx_aborted); + data[12] = le16_to_cpu(counters->tx_underun); + pci_free_consistent(tp->pci_dev, sizeof(*counters), counters, paddr); } -static void rtl8169_get_ethtool_stats(struct net_device *dev, - struct ethtool_stats *stats, u64 *data) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - ASSERT_RTNL(); - - rtl8169_update_counters(dev); - - data[0] = le64_to_cpu(tp->counters.tx_packets); - data[1] = le64_to_cpu(tp->counters.rx_packets); - data[2] = le64_to_cpu(tp->counters.tx_errors); - data[3] = le32_to_cpu(tp->counters.rx_errors); - data[4] = le16_to_cpu(tp->counters.rx_missed); - data[5] = le16_to_cpu(tp->counters.align_errors); - data[6] = le32_to_cpu(tp->counters.tx_one_collision); - data[7] = le32_to_cpu(tp->counters.tx_multi_collision); - data[8] = le64_to_cpu(tp->counters.rx_unicast); - data[9] = le64_to_cpu(tp->counters.rx_broadcast); - data[10] = le32_to_cpu(tp->counters.rx_multicast); - data[11] = le16_to_cpu(tp->counters.tx_aborted); - data[12] = le16_to_cpu(tp->counters.tx_underun); -} - static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data) { switch(stringset) { @@ -1311,8 +1289,7 @@ { 0xfc800000, 0x00800000, RTL_GIGA_MAC_VER_02 }, { 0xfc800000, 0x00000000, RTL_GIGA_MAC_VER_01 }, - /* Catch-all */ - { 0x00000000, 0x00000000, RTL_GIGA_MAC_NONE } + { 0x00000000, 0x00000000, RTL_GIGA_MAC_VER_01 } /* Catch-all */ }, *p = mac_info; u32 reg; @@ -1320,6 +1297,12 @@ while ((reg & p->mask) != p->val) p++; tp->mac_version = p->mac_version; + + if (p->mask == 0x00000000) { + struct pci_dev *pdev = tp->pci_dev; + + dev_info(&pdev->dev, "unknown MAC (%08x)\n", reg); + } } static void rtl8169_print_mac_version(struct rtl8169_private *tp) @@ -1863,11 +1846,9 @@ struct rtl8169_private *tp = netdev_priv(dev); struct mii_ioctl_data *data = if_mii(ifr); - return netif_running(dev) ? tp->do_ioctl(tp, data, cmd) : -ENODEV; -} - -static int rtl_xmii_ioctl(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd) -{ + if (!netif_running(dev)) + return -ENODEV; + switch (cmd) { case SIOCGMIIPHY: data->phy_id = 32; /* Internal PHY */ @@ -1886,11 +1867,6 @@ return -EOPNOTSUPP; } -static int rtl_tbi_ioctl(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd) -{ - return -EOPNOTSUPP; -} - static const struct rtl_cfg_info { void (*hw_start)(struct net_device *); unsigned int region; @@ -1898,7 +1874,6 @@ u16 intr_event; u16 napi_event; unsigned features; - u8 default_ver; } rtl_cfg_infos [] = { [RTL_CFG_0] = { .hw_start = rtl_hw_start_8169, @@ -1907,8 +1882,7 @@ .intr_event = SYSErr | LinkChg | RxOverflow | RxFIFOOver | TxErr | TxOK | RxOK | RxErr, .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_GMII, - .default_ver = RTL_GIGA_MAC_VER_01, + .features = RTL_FEATURE_GMII }, [RTL_CFG_1] = { .hw_start = rtl_hw_start_8168, @@ -1917,8 +1891,7 @@ .intr_event = SYSErr | LinkChg | RxOverflow | TxErr | TxOK | RxOK | RxErr, .napi_event = TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_GMII | RTL_FEATURE_MSI, - .default_ver = RTL_GIGA_MAC_VER_11, + .features = RTL_FEATURE_GMII | RTL_FEATURE_MSI }, [RTL_CFG_2] = { .hw_start = rtl_hw_start_8101, @@ -1927,8 +1900,7 @@ .intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout | RxFIFOOver | TxErr | TxOK | RxOK | RxErr, .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_MSI, - .default_ver = RTL_GIGA_MAC_VER_13, + .features = RTL_FEATURE_MSI } }; @@ -1960,26 +1932,6 @@ } } -static const struct net_device_ops rtl8169_netdev_ops = { - .ndo_open = rtl8169_open, - .ndo_stop = rtl8169_close, - .ndo_get_stats = rtl8169_get_stats, - .ndo_start_xmit = rtl8169_start_xmit, - .ndo_tx_timeout = rtl8169_tx_timeout, - .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = rtl8169_change_mtu, - .ndo_set_mac_address = rtl_set_mac_address, - .ndo_do_ioctl = rtl8169_ioctl, - .ndo_set_multicast_list = rtl_set_rx_mode, -#ifdef CONFIG_R8169_VLAN - .ndo_vlan_rx_register = rtl8169_vlan_rx_register, -#endif -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = rtl8169_netpoll, -#endif - -}; - static int __devinit rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -2006,7 +1958,6 @@ } SET_NETDEV_DEV(dev, &pdev->dev); - dev->netdev_ops = &rtl8169_netdev_ops; tp = netdev_priv(dev); tp->dev = dev; tp->pci_dev = pdev; @@ -2063,11 +2014,11 @@ tp->cp_cmd = PCIMulRW | RxChkSum; if ((sizeof(dma_addr_t) > 4) && - !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && use_dac) { + !pci_set_dma_mask(pdev, DMA_64BIT_MASK) && use_dac) { tp->cp_cmd |= PCIDAC; dev->features |= NETIF_F_HIGHDMA; } else { - rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); if (rc < 0) { if (netif_msg_probe(tp)) { dev_err(&pdev->dev, @@ -2077,6 +2028,8 @@ } } + pci_set_master(pdev); + /* ioremap MMIO region */ ioaddr = ioremap(pci_resource_start(pdev, region), R8169_REGS_SIZE); if (!ioaddr) { @@ -2104,20 +2057,9 @@ RTL_W16(IntrStatus, 0xffff); - pci_set_master(pdev); - /* Identify chip attached to board */ rtl8169_get_mac_version(tp, ioaddr); - /* Use appropriate default if unknown */ - if (tp->mac_version == RTL_GIGA_MAC_NONE) { - if (netif_msg_probe(tp)) { - dev_notice(&pdev->dev, - "unknown MAC, using family default\n"); - } - tp->mac_version = cfg->default_ver; - } - rtl8169_print_mac_version(tp); for (i = 0; i < ARRAY_SIZE(rtl_chip_info); i++) { @@ -2125,9 +2067,13 @@ break; } if (i == ARRAY_SIZE(rtl_chip_info)) { - dev_err(&pdev->dev, - "driver bug, MAC version not found in rtl_chip_info\n"); - goto err_out_msi_5; + /* Unknown chip: assume array element #0, original RTL-8169 */ + if (netif_msg_probe(tp)) { + dev_printk(KERN_DEBUG, &pdev->dev, + "unknown chip version, assuming %s\n", + rtl_chip_info[0].name); + } + i = 0; } tp->chipset = i; @@ -2148,7 +2094,6 @@ tp->phy_reset_enable = rtl8169_tbi_reset_enable; tp->phy_reset_pending = rtl8169_tbi_reset_pending; tp->link_ok = rtl8169_tbi_link_ok; - tp->do_ioctl = rtl_tbi_ioctl; tp->phy_1000_ctrl_reg = ADVERTISE_1000FULL; /* Implied by TBI */ } else { @@ -2157,7 +2102,8 @@ tp->phy_reset_enable = rtl8169_xmii_reset_enable; tp->phy_reset_pending = rtl8169_xmii_reset_pending; tp->link_ok = rtl8169_xmii_link_ok; - tp->do_ioctl = rtl_xmii_ioctl; + + dev->do_ioctl = rtl8169_ioctl; } spin_lock_init(&tp->lock); @@ -2169,15 +2115,28 @@ dev->dev_addr[i] = RTL_R8(MAC0 + i); memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); + dev->open = rtl8169_open; + dev->hard_start_xmit = rtl8169_start_xmit; + dev->get_stats = rtl8169_get_stats; SET_ETHTOOL_OPS(dev, &rtl8169_ethtool_ops); + dev->stop = rtl8169_close; + dev->tx_timeout = rtl8169_tx_timeout; + dev->set_multicast_list = rtl_set_rx_mode; dev->watchdog_timeo = RTL8169_TX_TIMEOUT; dev->irq = pdev->irq; dev->base_addr = (unsigned long) ioaddr; + dev->change_mtu = rtl8169_change_mtu; + dev->set_mac_address = rtl_set_mac_address; netif_napi_add(dev, &tp->napi, rtl8169_poll, R8169_NAPI_WEIGHT); #ifdef CONFIG_R8169_VLAN dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; + dev->vlan_rx_register = rtl8169_vlan_rx_register; +#endif + +#ifdef CONFIG_NET_POLL_CONTROLLER + dev->poll_controller = rtl8169_netpoll; #endif tp->intr_mask = 0xffff; @@ -2217,12 +2176,12 @@ rtl8169_init_phy(dev, tp); device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL); + if (tp->ecdev && ecdev_open(tp->ecdev)) { ecdev_withdraw(tp->ecdev); goto err_out_msi_5; } - out: return rc; @@ -2305,8 +2264,8 @@ goto err_release_ring_2; napi_enable(&tp->napi); - - } + } + rtl_hw_start(dev); rtl8169_request_timer(dev); @@ -2383,9 +2342,9 @@ * Switching from MMIO to I/O access fixes the issue as well. */ RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr) >> 32); - RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr) & DMA_BIT_MASK(32)); + RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr) & DMA_32BIT_MASK); RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr) >> 32); - RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr) & DMA_BIT_MASK(32)); + RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr) & DMA_32BIT_MASK); } static u16 rtl_rw_cpluscmd(void __iomem *ioaddr) @@ -2397,10 +2356,10 @@ return cmd; } -static void rtl_set_rx_max_size(void __iomem *ioaddr, unsigned int rx_buf_sz) +static void rtl_set_rx_max_size(void __iomem *ioaddr) { /* Low hurts. Let's disable the filtering. */ - RTL_W16(RxMaxSize, rx_buf_sz); + RTL_W16(RxMaxSize, 16383); } static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version) @@ -2433,8 +2392,6 @@ void __iomem *ioaddr = tp->mmio_addr; struct pci_dev *pdev = tp->pci_dev; - printk(KERN_INFO "%s\n", __func__); - if (tp->mac_version == RTL_GIGA_MAC_VER_05) { RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW); pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08); @@ -2449,7 +2406,7 @@ RTL_W8(EarlyTxThres, EarlyTxThld); - rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); + rtl_set_rx_max_size(ioaddr); if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || (tp->mac_version == RTL_GIGA_MAC_VER_02) || @@ -2711,7 +2668,7 @@ RTL_W8(EarlyTxThres, EarlyTxThld); - rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); + rtl_set_rx_max_size(ioaddr); tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1; @@ -2890,7 +2847,7 @@ RTL_W8(EarlyTxThres, EarlyTxThld); - rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); + rtl_set_rx_max_size(ioaddr); tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; @@ -3303,6 +3260,13 @@ opts1 |= FirstFrag; } else { len = skb->len; + + if (unlikely(len < ETH_ZLEN)) { + if (skb_padto(skb, ETH_ZLEN)) + goto err_update_stats; + len = ETH_ZLEN; + } + opts1 |= FirstFrag | LastFrag; tp->tx_skb[entry].skb = skb; } @@ -3319,6 +3283,8 @@ status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); txd->opts1 = cpu_to_le32(status); + dev->trans_start = jiffies; + tp->cur_tx += frags + 1; smp_wmb(); @@ -3341,6 +3307,7 @@ if (!tp->ecdev) netif_stop_queue(dev); ret = NETDEV_TX_BUSY; +err_update_stats: dev->stats.tx_dropped++; goto out; } @@ -3423,7 +3390,7 @@ if (status & LastFrag) { if (!tp->ecdev) - dev_kfree_skb(tx_skb->skb); + dev_kfree_skb_irq(tx_skb->skb); tx_skb->skb = NULL; } dirty_tx++; @@ -3580,6 +3547,7 @@ netif_receive_skb(skb); } + dev->last_rx = jiffies; dev->stats.rx_bytes += pkt_size; dev->stats.rx_packets++; } @@ -3626,64 +3594,54 @@ int handled = 0; int status; - /* loop handling interrupts until we have no new ones or - * we hit a invalid/hotplug case. - */ status = RTL_R16(IntrStatus); - while (status && status != 0xffff) { - handled = 1; - - /* Handle all of the error cases first. These will reset - * the chip, so just exit the loop. - */ - if (unlikely(!tp->ecdev && !netif_running(dev))) { - rtl8169_asic_down(ioaddr); - break; + + /* hotplug/major error/no more work/shared irq */ + if ((status == 0xffff) || !status) + goto out; + + handled = 1; + + if (unlikely(!tp->ecdev && !netif_running(dev))) { + rtl8169_asic_down(ioaddr); + goto out; + } + + status &= tp->intr_mask; + RTL_W16(IntrStatus, + (status & RxFIFOOver) ? (status | RxOverflow) : status); + + if (!(status & tp->intr_event)) + goto out; + + /* Work around for rx fifo overflow */ + if (unlikely(status & RxFIFOOver) && + (tp->mac_version == RTL_GIGA_MAC_VER_11)) { + netif_stop_queue(dev); + rtl8169_tx_timeout(dev); + goto out; + } + + if (unlikely(status & SYSErr)) { + rtl8169_pcierr_interrupt(dev); + goto out; + } + + if (status & LinkChg) + rtl8169_check_link_status(dev, tp, ioaddr); + + if (status & tp->napi_event) { + RTL_W16(IntrMask, tp->intr_event & ~tp->napi_event); + tp->intr_mask = ~tp->napi_event; + + if (likely(netif_rx_schedule_prep(dev, &tp->napi))) + __netif_rx_schedule(dev, &tp->napi); + else if (netif_msg_intr(tp)) { + printk(KERN_INFO "%s: interrupt %04x in poll\n", + dev->name, status); } - - /* Work around for rx fifo overflow */ - if (unlikely(status & RxFIFOOver) && - (tp->mac_version == RTL_GIGA_MAC_VER_11)) { - netif_stop_queue(dev); - rtl8169_tx_timeout(dev); - break; - } - - if (unlikely(status & SYSErr)) { - rtl8169_pcierr_interrupt(dev); - break; - } - - if (status & LinkChg) - rtl8169_check_link_status(dev, tp, ioaddr); - - /* We need to see the lastest version of tp->intr_mask to - * avoid ignoring an MSI interrupt and having to wait for - * another event which may never come. - */ - smp_rmb(); - if (status & tp->intr_mask & tp->napi_event) { - RTL_W16(IntrMask, tp->intr_event & ~tp->napi_event); - tp->intr_mask = ~tp->napi_event; - - if (likely(napi_schedule_prep(&tp->napi))) - __napi_schedule(&tp->napi); - else if (netif_msg_intr(tp)) { - printk(KERN_INFO "%s: interrupt %04x in poll\n", - dev->name, status); - } - } - - /* We only get a new MSI interrupt when all active irq - * sources on the chip have been acknowledged. So, ack - * everything we've seen and check if new sources have become - * active to avoid blocking all interrupts from the chip. - */ - RTL_W16(IntrStatus, - (status & RxFIFOOver) ? (status | RxOverflow) : status); - status = RTL_R16(IntrStatus); - } - + } +out: return IRQ_RETVAL(handled); } @@ -3713,16 +3671,14 @@ rtl8169_tx_interrupt(dev, tp, ioaddr); if (work_done < budget) { - napi_complete(napi); - - /* We need for force the visibility of tp->intr_mask - * for other CPUs, as we can loose an MSI interrupt - * and potentially wait for a retransmit timeout if we don't. - * The posted write to IntrMask is safe, as it will - * eventually make it to the chip and we won't loose anything - * until it does. + netif_rx_complete(dev, napi); + tp->intr_mask = 0xffff; + /* + * 20040426: the barrier is not strictly required but the + * behavior of the irq handler could be less predictable + * without it. Btw, the lack of flush for the posted pci + * write is safe - FR */ - tp->intr_mask = 0xffff; smp_wmb(); RTL_W16(IntrMask, tp->intr_event); } @@ -3753,8 +3709,8 @@ netif_stop_queue(dev); napi_disable(&tp->napi); - - } + } + core_down: if (!tp->ecdev) spin_lock_irq(&tp->lock); @@ -3799,9 +3755,6 @@ struct rtl8169_private *tp = netdev_priv(dev); struct pci_dev *pdev = tp->pci_dev; - /* update counters before going down */ - rtl8169_update_counters(dev); - rtl8169_down(dev); if (!tp->ecdev) @@ -3896,40 +3849,52 @@ return &dev->stats; } -static void rtl8169_net_suspend(struct net_device *dev) -{ +#ifdef CONFIG_PM + +static int rtl8169_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct net_device *dev = pci_get_drvdata(pdev); + struct rtl8169_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->mmio_addr; + + if (tp->ecdev) + return -EBUSY; + if (!netif_running(dev)) - return; + goto out_pci_suspend; netif_device_detach(dev); netif_stop_queue(dev); -} - -#ifdef CONFIG_PM - -static int rtl8169_suspend(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); + + spin_lock_irq(&tp->lock); + + rtl8169_asic_down(ioaddr); + + rtl8169_rx_missed(dev, ioaddr); + + spin_unlock_irq(&tp->lock); + +out_pci_suspend: + pci_save_state(pdev); + pci_enable_wake(pdev, pci_choose_state(pdev, state), + (tp->features & RTL_FEATURE_WOL) ? 1 : 0); + pci_set_power_state(pdev, pci_choose_state(pdev, state)); + + return 0; +} + +static int rtl8169_resume(struct pci_dev *pdev) +{ struct net_device *dev = pci_get_drvdata(pdev); struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->ecdev) - return -EBUSY; - - rtl8169_net_suspend(dev); - - return 0; -} - -static int rtl8169_resume(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - + if (tp->ecdev) return -EBUSY; + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + pci_enable_wake(pdev, PCI_D0, 0); + if (!netif_running(dev)) goto out; @@ -3940,59 +3905,23 @@ return 0; } -static struct dev_pm_ops rtl8169_pm_ops = { - .suspend = rtl8169_suspend, - .resume = rtl8169_resume, - .freeze = rtl8169_suspend, - .thaw = rtl8169_resume, - .poweroff = rtl8169_suspend, - .restore = rtl8169_resume, -}; - -#define RTL8169_PM_OPS (&rtl8169_pm_ops) - -#else /* !CONFIG_PM */ - -#define RTL8169_PM_OPS NULL - -#endif /* !CONFIG_PM */ - static void rtl_shutdown(struct pci_dev *pdev) { - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - rtl8169_net_suspend(dev); - - spin_lock_irq(&tp->lock); - - rtl8169_asic_down(ioaddr); - - spin_unlock_irq(&tp->lock); - - if (system_state == SYSTEM_POWER_OFF) { - /* WoL fails with some 8168 when the receiver is disabled. */ - if (tp->features & RTL_FEATURE_WOL) { - pci_clear_master(pdev); - - RTL_W8(ChipCmd, CmdRxEnb); - /* PCI commit */ - RTL_R8(ChipCmd); - } - - pci_wake_from_d3(pdev, true); - pci_set_power_state(pdev, PCI_D3hot); - } -} + rtl8169_suspend(pdev, PMSG_SUSPEND); +} + +#endif /* CONFIG_PM */ static struct pci_driver rtl8169_pci_driver = { .name = MODULENAME, .id_table = rtl8169_pci_tbl, .probe = rtl8169_init_one, .remove = __devexit_p(rtl8169_remove_one), +#ifdef CONFIG_PM + .suspend = rtl8169_suspend, + .resume = rtl8169_resume, .shutdown = rtl_shutdown, - .driver.pm = RTL8169_PM_OPS, +#endif }; static int __init rtl8169_init_module(void)