r8169: use hardware auto-padding.
[safe/jmp/linux-2.6] / drivers / net / r8169.c
index f0f842d..352da2a 100644 (file)
@@ -81,6 +81,10 @@ static const int multicast_filter_limit = 32;
 #define RTL8169_TX_TIMEOUT     (6*HZ)
 #define RTL8169_PHY_TIMEOUT    (10*HZ)
 
+#define RTL_EEPROM_SIG         0x8129
+#define RTL_EEPROM_SIG_ADDR    0x0000
+#define RTL_EEPROM_MAC_ADDR    0x0007
+
 /* write/read MMIO register */
 #define RTL_W8(reg, val8)      writeb ((val8), ioaddr + (reg))
 #define RTL_W16(reg, val16)    writew ((val16), ioaddr + (reg))
@@ -109,7 +113,12 @@ enum mac_version {
        RTL_GIGA_MAC_VER_17 = 0x10, // 8168Bf
        RTL_GIGA_MAC_VER_18 = 0x12, // 8168CP
        RTL_GIGA_MAC_VER_19 = 0x13, // 8168C
-       RTL_GIGA_MAC_VER_20 = 0x14  // 8168C
+       RTL_GIGA_MAC_VER_20 = 0x14, // 8168C
+       RTL_GIGA_MAC_VER_21 = 0x15, // 8168C
+       RTL_GIGA_MAC_VER_22 = 0x16, // 8168C
+       RTL_GIGA_MAC_VER_23 = 0x17, // 8168CP
+       RTL_GIGA_MAC_VER_24 = 0x18, // 8168CP
+       RTL_GIGA_MAC_VER_25 = 0x19  // 8168D
 };
 
 #define _R(NAME,MAC,MASK) \
@@ -139,7 +148,12 @@ static const struct {
        _R("RTL8101e",          RTL_GIGA_MAC_VER_16, 0xff7e1880), // PCI-E
        _R("RTL8168cp/8111cp",  RTL_GIGA_MAC_VER_18, 0xff7e1880), // PCI-E
        _R("RTL8168c/8111c",    RTL_GIGA_MAC_VER_19, 0xff7e1880), // PCI-E
-       _R("RTL8168c/8111c",    RTL_GIGA_MAC_VER_20, 0xff7e1880)  // PCI-E
+       _R("RTL8168c/8111c",    RTL_GIGA_MAC_VER_20, 0xff7e1880), // PCI-E
+       _R("RTL8168c/8111c",    RTL_GIGA_MAC_VER_21, 0xff7e1880), // PCI-E
+       _R("RTL8168c/8111c",    RTL_GIGA_MAC_VER_22, 0xff7e1880), // PCI-E
+       _R("RTL8168cp/8111cp",  RTL_GIGA_MAC_VER_23, 0xff7e1880), // PCI-E
+       _R("RTL8168cp/8111cp",  RTL_GIGA_MAC_VER_24, 0xff7e1880), // PCI-E
+       _R("RTL8168d/8111d",    RTL_GIGA_MAC_VER_25, 0xff7e1880)  // PCI-E
 };
 #undef _R
 
@@ -279,6 +293,11 @@ enum rtl_register_content {
        /* Cfg9346Bits */
        Cfg9346_Lock    = 0x00,
        Cfg9346_Unlock  = 0xc0,
+       Cfg9346_Program = 0x80,         /* Programming mode */
+       Cfg9346_EECS    = 0x08,         /* Chip select */
+       Cfg9346_EESK    = 0x04,         /* Serial data clock */
+       Cfg9346_EEDI    = 0x02,         /* Data input */
+       Cfg9346_EEDO    = 0x01,         /* Data output */
 
        /* rx_mode_bits */
        AcceptErr       = 0x20,
@@ -291,6 +310,7 @@ enum rtl_register_content {
        /* RxConfigBits */
        RxCfgFIFOShift  = 13,
        RxCfgDMAShift   =  8,
+       RxCfg9356SEL    =  6,           /* EEPROM type: 0 = 9346, 1 = 9356 */
 
        /* TxConfigBits */
        TxInterFrameGapShift = 24,
@@ -423,6 +443,22 @@ enum features {
        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 */
@@ -460,11 +496,13 @@ struct rtl8169_private {
        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;
 };
 
 MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
@@ -1085,22 +1123,6 @@ static const char rtl8169_gstrings[][ETH_GSTRING_LEN] = {
        "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) {
@@ -1111,16 +1133,21 @@ static int rtl8169_get_sset_count(struct net_device *dev, int sset)
        }
 }
 
-static void rtl8169_get_ethtool_stats(struct net_device *dev,
-                                     struct ethtool_stats *stats, u64 *data)
+static void rtl8169_update_counters(struct net_device *dev)
 {
        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;
 
-       ASSERT_RTNL();
+       /*
+        * Some chips are unable to dump tally counters when the receiver
+        * is disabled.
+        */
+       if ((RTL_R8(ChipCmd) & CmdRxEnb) == 0)
+               return;
 
        counters = pci_alloc_consistent(tp->pci_dev, sizeof(*counters), &paddr);
        if (!counters)
@@ -1131,31 +1158,45 @@ static void rtl8169_get_ethtool_stats(struct net_device *dev,
        RTL_W32(CounterAddrLow, cmd);
        RTL_W32(CounterAddrLow, cmd | CounterDump);
 
-       while (RTL_R32(CounterAddrLow) & CounterDump) {
-               if (msleep_interruptible(1))
+       while (wait--) {
+               if ((RTL_R32(CounterAddrLow) & CounterDump) == 0) {
+                       /* copy updated counters */
+                       memcpy(&tp->counters, counters, sizeof(*counters));
                        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) {
@@ -1216,11 +1257,19 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp,
                u32 val;
                int mac_version;
        } mac_info[] = {
-               /* 8168B family. */
-               { 0x7c800000, 0x3c800000,       RTL_GIGA_MAC_VER_18 },
+               /* 8168D family. */
+               { 0x7c800000, 0x28000000,       RTL_GIGA_MAC_VER_25 },
+
+               /* 8168C family. */
+               { 0x7cf00000, 0x3ca00000,       RTL_GIGA_MAC_VER_24 },
+               { 0x7cf00000, 0x3c900000,       RTL_GIGA_MAC_VER_23 },
+               { 0x7cf00000, 0x3c800000,       RTL_GIGA_MAC_VER_18 },
+               { 0x7c800000, 0x3c800000,       RTL_GIGA_MAC_VER_24 },
                { 0x7cf00000, 0x3c000000,       RTL_GIGA_MAC_VER_19 },
                { 0x7cf00000, 0x3c200000,       RTL_GIGA_MAC_VER_20 },
-               { 0x7c800000, 0x3c000000,       RTL_GIGA_MAC_VER_20 },
+               { 0x7cf00000, 0x3c300000,       RTL_GIGA_MAC_VER_21 },
+               { 0x7cf00000, 0x3c400000,       RTL_GIGA_MAC_VER_22 },
+               { 0x7c800000, 0x3c000000,       RTL_GIGA_MAC_VER_22 },
 
                /* 8168B family. */
                { 0x7cf00000, 0x38000000,       RTL_GIGA_MAC_VER_12 },
@@ -1374,7 +1423,7 @@ static void rtl8168bef_hw_phy_config(void __iomem *ioaddr)
        rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
 }
 
-static void rtl8168cp_hw_phy_config(void __iomem *ioaddr)
+static void rtl8168cp_1_hw_phy_config(void __iomem *ioaddr)
 {
        struct phy_reg phy_reg_init[] = {
                { 0x1f, 0x0000 },
@@ -1387,6 +1436,21 @@ static void rtl8168cp_hw_phy_config(void __iomem *ioaddr)
        rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
 }
 
+static void rtl8168cp_2_hw_phy_config(void __iomem *ioaddr)
+{
+       struct phy_reg phy_reg_init[] = {
+               { 0x1f, 0x0001 },
+               { 0x1d, 0x3d98 },
+               { 0x1f, 0x0000 }
+       };
+
+       mdio_write(ioaddr, 0x1f, 0x0000);
+       mdio_patch(ioaddr, 0x14, 1 << 5);
+       mdio_patch(ioaddr, 0x0d, 1 << 5);
+
+       rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+}
+
 static void rtl8168c_1_hw_phy_config(void __iomem *ioaddr)
 {
        struct phy_reg phy_reg_init[] = {
@@ -1444,6 +1508,103 @@ static void rtl8168c_2_hw_phy_config(void __iomem *ioaddr)
        mdio_write(ioaddr, 0x1f, 0x0000);
 }
 
+static void rtl8168c_3_hw_phy_config(void __iomem *ioaddr)
+{
+       struct phy_reg phy_reg_init[] = {
+               { 0x1f, 0x0001 },
+               { 0x12, 0x2300 },
+               { 0x1d, 0x3d98 },
+               { 0x1f, 0x0002 },
+               { 0x0c, 0x7eb8 },
+               { 0x06, 0x5461 },
+               { 0x1f, 0x0003 },
+               { 0x16, 0x0f0a },
+               { 0x1f, 0x0000 }
+       };
+
+       rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+
+       mdio_patch(ioaddr, 0x16, 1 << 0);
+       mdio_patch(ioaddr, 0x14, 1 << 5);
+       mdio_patch(ioaddr, 0x0d, 1 << 5);
+       mdio_write(ioaddr, 0x1f, 0x0000);
+}
+
+static void rtl8168c_4_hw_phy_config(void __iomem *ioaddr)
+{
+       rtl8168c_3_hw_phy_config(ioaddr);
+}
+
+static void rtl8168d_hw_phy_config(void __iomem *ioaddr)
+{
+       struct phy_reg phy_reg_init_0[] = {
+               { 0x1f, 0x0001 },
+               { 0x09, 0x2770 },
+               { 0x08, 0x04d0 },
+               { 0x0b, 0xad15 },
+               { 0x0c, 0x5bf0 },
+               { 0x1c, 0xf101 },
+               { 0x1f, 0x0003 },
+               { 0x14, 0x94d7 },
+               { 0x12, 0xf4d6 },
+               { 0x09, 0xca0f },
+               { 0x1f, 0x0002 },
+               { 0x0b, 0x0b10 },
+               { 0x0c, 0xd1f7 },
+               { 0x1f, 0x0002 },
+               { 0x06, 0x5461 },
+               { 0x1f, 0x0002 },
+               { 0x05, 0x6662 },
+               { 0x1f, 0x0000 },
+               { 0x14, 0x0060 },
+               { 0x1f, 0x0000 },
+               { 0x0d, 0xf8a0 },
+               { 0x1f, 0x0005 },
+               { 0x05, 0xffc2 }
+       };
+
+       rtl_phy_write(ioaddr, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0));
+
+       if (mdio_read(ioaddr, 0x06) == 0xc400) {
+               struct phy_reg phy_reg_init_1[] = {
+                       { 0x1f, 0x0005 },
+                       { 0x01, 0x0300 },
+                       { 0x1f, 0x0000 },
+                       { 0x11, 0x401c },
+                       { 0x16, 0x4100 },
+                       { 0x1f, 0x0005 },
+                       { 0x07, 0x0010 },
+                       { 0x05, 0x83dc },
+                       { 0x06, 0x087d },
+                       { 0x05, 0x8300 },
+                       { 0x06, 0x0101 },
+                       { 0x06, 0x05f8 },
+                       { 0x06, 0xf9fa },
+                       { 0x06, 0xfbef },
+                       { 0x06, 0x79e2 },
+                       { 0x06, 0x835f },
+                       { 0x06, 0xe0f8 },
+                       { 0x06, 0x9ae1 },
+                       { 0x06, 0xf89b },
+                       { 0x06, 0xef31 },
+                       { 0x06, 0x3b65 },
+                       { 0x06, 0xaa07 },
+                       { 0x06, 0x81e4 },
+                       { 0x06, 0xf89a },
+                       { 0x06, 0xe5f8 },
+                       { 0x06, 0x9baf },
+                       { 0x06, 0x06ae },
+                       { 0x05, 0x83dc },
+                       { 0x06, 0x8300 },
+               };
+
+               rtl_phy_write(ioaddr, phy_reg_init_1,
+                             ARRAY_SIZE(phy_reg_init_1));
+       }
+
+       mdio_write(ioaddr, 0x1f, 0x0000);
+}
+
 static void rtl8102e_hw_phy_config(void __iomem *ioaddr)
 {
        struct phy_reg phy_reg_init[] = {
@@ -1492,7 +1653,7 @@ static void rtl_hw_phy_config(struct net_device *dev)
                rtl8168bef_hw_phy_config(ioaddr);
                break;
        case RTL_GIGA_MAC_VER_18:
-               rtl8168cp_hw_phy_config(ioaddr);
+               rtl8168cp_1_hw_phy_config(ioaddr);
                break;
        case RTL_GIGA_MAC_VER_19:
                rtl8168c_1_hw_phy_config(ioaddr);
@@ -1500,6 +1661,20 @@ static void rtl_hw_phy_config(struct net_device *dev)
        case RTL_GIGA_MAC_VER_20:
                rtl8168c_2_hw_phy_config(ioaddr);
                break;
+       case RTL_GIGA_MAC_VER_21:
+               rtl8168c_3_hw_phy_config(ioaddr);
+               break;
+       case RTL_GIGA_MAC_VER_22:
+               rtl8168c_4_hw_phy_config(ioaddr);
+               break;
+       case RTL_GIGA_MAC_VER_23:
+       case RTL_GIGA_MAC_VER_24:
+               rtl8168cp_2_hw_phy_config(ioaddr);
+               break;
+       case RTL_GIGA_MAC_VER_25:
+               rtl8168d_hw_phy_config(ioaddr);
+               break;
+
        default:
                break;
        }
@@ -1681,9 +1856,11 @@ static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
        struct rtl8169_private *tp = netdev_priv(dev);
        struct mii_ioctl_data *data = if_mii(ifr);
 
-       if (!netif_running(dev))
-               return -ENODEV;
+       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)
+{
        switch (cmd) {
        case SIOCGMIIPHY:
                data->phy_id = 32; /* Internal PHY */
@@ -1702,6 +1879,11 @@ static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
        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;
@@ -1767,72 +1949,126 @@ static void rtl_disable_msi(struct pci_dev *pdev, struct rtl8169_private *tp)
        }
 }
 
-static int rtl_eeprom_read(struct pci_dev *pdev, int cap, int addr, __le32 *val)
+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
+
+};
+
+/* Delay between EEPROM clock transitions. Force out buffered PCI writes. */
+#define RTL_EEPROM_DELAY()     RTL_R8(Cfg9346)
+#define RTL_EEPROM_READ_CMD    6
+
+/* read 16bit word stored in EEPROM. EEPROM is addressed by words. */
+static u16 rtl_eeprom_read(void __iomem *ioaddr, int addr)
 {
-       int ret, count = 100;
-       u16 status = 0;
-       u32 value;
+       u16 result = 0;
+       int cmd, cmd_len, i;
 
-       ret = pci_write_config_word(pdev, cap + PCI_VPD_ADDR, addr);
-       if (ret < 0)
-               return ret;
+       /* check for EEPROM address size (in bits) */
+       if (RTL_R32(RxConfig) & (1 << RxCfg9356SEL)) {
+               /* EEPROM is 93C56 */
+               cmd_len = 3 + 8; /* 3 bits for command id and 8 for address */
+               cmd = (RTL_EEPROM_READ_CMD << 8) | (addr & 0xff);
+       } else {
+               /* EEPROM is 93C46 */
+               cmd_len = 3 + 6; /* 3 bits for command id and 6 for address */
+               cmd = (RTL_EEPROM_READ_CMD << 6) | (addr & 0x3f);
+       }
 
-       do {
-               udelay(10);
-               ret = pci_read_config_word(pdev, cap + PCI_VPD_ADDR, &status);
-               if (ret < 0)
-                       return ret;
-       } while (!(status & PCI_VPD_ADDR_F) && --count);
+       /* enter programming mode */
+       RTL_W8(Cfg9346, Cfg9346_Program | Cfg9346_EECS);
+       RTL_EEPROM_DELAY();
 
-       if (!(status & PCI_VPD_ADDR_F))
-               return -ETIMEDOUT;
+       /* write command and requested address */
+       while (cmd_len--) {
+               u8 x = Cfg9346_Program | Cfg9346_EECS;
 
-       ret = pci_read_config_dword(pdev, cap + PCI_VPD_DATA, &value);
-       if (ret < 0)
-               return ret;
+               x |= (cmd & (1 << cmd_len)) ? Cfg9346_EEDI : 0;
 
-       *val = cpu_to_le32(value);
+               /* write a bit */
+               RTL_W8(Cfg9346, x);
+               RTL_EEPROM_DELAY();
 
-       return 0;
+               /* raise clock */
+               RTL_W8(Cfg9346, x | Cfg9346_EESK);
+               RTL_EEPROM_DELAY();
+       }
+
+       /* lower clock */
+       RTL_W8(Cfg9346, Cfg9346_Program | Cfg9346_EECS);
+       RTL_EEPROM_DELAY();
+
+       /* read back 16bit value */
+       for (i = 16; i > 0; i--) {
+               /* raise clock */
+               RTL_W8(Cfg9346, Cfg9346_Program | Cfg9346_EECS | Cfg9346_EESK);
+               RTL_EEPROM_DELAY();
+
+               result <<= 1;
+               result |= (RTL_R8(Cfg9346) & Cfg9346_EEDO) ? 1 : 0;
+
+               /* lower clock */
+               RTL_W8(Cfg9346, Cfg9346_Program | Cfg9346_EECS);
+               RTL_EEPROM_DELAY();
+       }
+
+       RTL_W8(Cfg9346, Cfg9346_Program);
+       /* leave programming mode */
+       RTL_W8(Cfg9346, Cfg9346_Lock);
+
+       return result;
 }
 
 static void rtl_init_mac_address(struct rtl8169_private *tp,
                                 void __iomem *ioaddr)
 {
        struct pci_dev *pdev = tp->pci_dev;
-       u8 cfg1;
-       int vpd_cap;
+       u16 x;
        u8 mac[8];
-       DECLARE_MAC_BUF(buf);
-
-       cfg1 = RTL_R8(Config1);
-       if (!(cfg1  & VPD)) {
-               dprintk("VPD access not enabled, enabling\n");
-               RTL_W8(Cfg9346, Cfg9346_Unlock);
-               RTL_W8(Config1, cfg1 | VPD);
-               RTL_W8(Cfg9346, Cfg9346_Lock);
-       }
 
-       vpd_cap = pci_find_capability(pdev, PCI_CAP_ID_VPD);
-       if (!vpd_cap)
-               return;
+       /* read EEPROM signature */
+       x = rtl_eeprom_read(ioaddr, RTL_EEPROM_SIG_ADDR);
 
-       /* MAC address is stored in EEPROM at offset 0x0e
-        * Realtek says: "The VPD address does not have to be a DWORD-aligned
-        * address as defined in the PCI 2.2 Specifications, but the VPD data
-        * is always consecutive 4-byte data starting from the VPD address
-        * specified."
-        */
-       if (rtl_eeprom_read(pdev, vpd_cap, 0x000e, (__le32*)&mac[0]) < 0 ||
-           rtl_eeprom_read(pdev, vpd_cap, 0x0012, (__le32*)&mac[4]) < 0) {
-               dprintk("Reading MAC address from EEPROM failed\n");
+       if (x != RTL_EEPROM_SIG) {
+               dev_info(&pdev->dev, "Missing EEPROM signature: %04x\n", x);
                return;
        }
 
-       dprintk("MAC address found in EEPROM: %s\n", print_mac(buf, mac));
+       /* read MAC address */
+       x = rtl_eeprom_read(ioaddr, RTL_EEPROM_MAC_ADDR);
+       mac[0] = x & 0xff;
+       mac[1] = x >> 8;
+       x = rtl_eeprom_read(ioaddr, RTL_EEPROM_MAC_ADDR + 1);
+       mac[2] = x & 0xff;
+       mac[3] = x >> 8;
+       x = rtl_eeprom_read(ioaddr, RTL_EEPROM_MAC_ADDR + 2);
+       mac[4] = x & 0xff;
+       mac[5] = x >> 8;
+
+       if (netif_msg_probe(tp)) {
+               DECLARE_MAC_BUF(buf);
 
-       /* Write MAC address */
-       rtl_rar_set(tp, mac);
+               dev_info(&pdev->dev, "MAC address found in EEPROM: %s\n",
+                        print_mac(buf, mac));
+       }
+
+       if (is_valid_ether_addr(mac))
+               rtl_rar_set(tp, mac);
 }
 
 static int __devinit
@@ -1861,6 +2097,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        }
 
        SET_NETDEV_DEV(dev, &pdev->dev);
+       dev->netdev_ops = &rtl8169_netdev_ops;
        tp = netdev_priv(dev);
        tp->dev = dev;
        tp->pci_dev = pdev;
@@ -1996,6 +2233,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                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 {
@@ -2004,12 +2242,13 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                tp->phy_reset_enable = rtl8169_xmii_reset_enable;
                tp->phy_reset_pending = rtl8169_xmii_reset_pending;
                tp->link_ok = rtl8169_xmii_link_ok;
-
-               dev->do_ioctl = rtl8169_ioctl;
+               tp->do_ioctl = rtl_xmii_ioctl;
        }
 
        spin_lock_init(&tp->lock);
 
+       tp->mmio_addr = ioaddr;
+
        rtl_init_mac_address(tp, ioaddr);
 
        /* Get MAC address */
@@ -2017,32 +2256,18 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                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;
-       tp->mmio_addr = ioaddr;
        tp->align = cfg->align;
        tp->hw_start = cfg->hw_start;
        tp->intr_event = cfg->intr_event;
@@ -2442,7 +2667,7 @@ static void __rtl_hw_start_8168cp(void __iomem *ioaddr, struct pci_dev *pdev)
        RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
 }
 
-static void rtl_hw_start_8168cp(void __iomem *ioaddr, struct pci_dev *pdev)
+static void rtl_hw_start_8168cp_1(void __iomem *ioaddr, struct pci_dev *pdev)
 {
        static struct ephy_info e_info_8168cp[] = {
                { 0x01, 0,      0x0001 },
@@ -2459,6 +2684,33 @@ static void rtl_hw_start_8168cp(void __iomem *ioaddr, struct pci_dev *pdev)
        __rtl_hw_start_8168cp(ioaddr, pdev);
 }
 
+static void rtl_hw_start_8168cp_2(void __iomem *ioaddr, struct pci_dev *pdev)
+{
+       rtl_csi_access_enable(ioaddr);
+
+       RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
+
+       rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
+
+       RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
+}
+
+static void rtl_hw_start_8168cp_3(void __iomem *ioaddr, struct pci_dev *pdev)
+{
+       rtl_csi_access_enable(ioaddr);
+
+       RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
+
+       /* Magic. */
+       RTL_W8(DBG_REG, 0x20);
+
+       RTL_W8(EarlyTxThres, EarlyTxThld);
+
+       rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
+
+       RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
+}
+
 static void rtl_hw_start_8168c_1(void __iomem *ioaddr, struct pci_dev *pdev)
 {
        static struct ephy_info e_info_8168c_1[] = {
@@ -2490,6 +2742,31 @@ static void rtl_hw_start_8168c_2(void __iomem *ioaddr, struct pci_dev *pdev)
        __rtl_hw_start_8168cp(ioaddr, pdev);
 }
 
+static void rtl_hw_start_8168c_3(void __iomem *ioaddr, struct pci_dev *pdev)
+{
+       rtl_hw_start_8168c_2(ioaddr, pdev);
+}
+
+static void rtl_hw_start_8168c_4(void __iomem *ioaddr, struct pci_dev *pdev)
+{
+       rtl_csi_access_enable(ioaddr);
+
+       __rtl_hw_start_8168cp(ioaddr, pdev);
+}
+
+static void rtl_hw_start_8168d(void __iomem *ioaddr, struct pci_dev *pdev)
+{
+       rtl_csi_access_enable(ioaddr);
+
+       rtl_disable_clock_request(pdev);
+
+       RTL_W8(EarlyTxThres, EarlyTxThld);
+
+       rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
+
+       RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
+}
+
 static void rtl_hw_start_8168(struct net_device *dev)
 {
        struct rtl8169_private *tp = netdev_priv(dev);
@@ -2534,7 +2811,7 @@ static void rtl_hw_start_8168(struct net_device *dev)
        break;
 
        case RTL_GIGA_MAC_VER_18:
-               rtl_hw_start_8168cp(ioaddr, pdev);
+               rtl_hw_start_8168cp_1(ioaddr, pdev);
        break;
 
        case RTL_GIGA_MAC_VER_19:
@@ -2545,6 +2822,26 @@ static void rtl_hw_start_8168(struct net_device *dev)
                rtl_hw_start_8168c_2(ioaddr, pdev);
        break;
 
+       case RTL_GIGA_MAC_VER_21:
+               rtl_hw_start_8168c_3(ioaddr, pdev);
+       break;
+
+       case RTL_GIGA_MAC_VER_22:
+               rtl_hw_start_8168c_4(ioaddr, pdev);
+       break;
+
+       case RTL_GIGA_MAC_VER_23:
+               rtl_hw_start_8168cp_2(ioaddr, pdev);
+       break;
+
+       case RTL_GIGA_MAC_VER_24:
+               rtl_hw_start_8168cp_3(ioaddr, pdev);
+       break;
+
+       case RTL_GIGA_MAC_VER_25:
+               rtl_hw_start_8168d(ioaddr, pdev);
+       break;
+
        default:
                printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n",
                        dev->name, tp->mac_version);
@@ -3066,13 +3363,6 @@ static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev)
                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;
        }
@@ -3110,7 +3400,6 @@ out:
 err_stop:
        netif_stop_queue(dev);
        ret = NETDEV_TX_BUSY;
-err_update_stats:
        dev->stats.tx_dropped++;
        goto out;
 }
@@ -3333,7 +3622,6 @@ static int rtl8169_rx_interrupt(struct net_device *dev,
                        if (rtl8169_rx_vlan_skb(tp, desc, skb) < 0)
                                netif_receive_skb(skb);
 
-                       dev->last_rx = jiffies;
                        dev->stats.rx_bytes += pkt_size;
                        dev->stats.rx_packets++;
                }
@@ -3415,8 +3703,8 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)
                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);
+               if (likely(netif_rx_schedule_prep(&tp->napi)))
+                       __netif_rx_schedule(&tp->napi);
                else if (netif_msg_intr(tp)) {
                        printk(KERN_INFO "%s: interrupt %04x in poll\n",
                               dev->name, status);
@@ -3437,7 +3725,7 @@ static int rtl8169_poll(struct napi_struct *napi, int budget)
        rtl8169_tx_interrupt(dev, tp, ioaddr);
 
        if (work_done < budget) {
-               netif_rx_complete(dev, napi);
+               netif_rx_complete(napi);
                tp->intr_mask = 0xffff;
                /*
                 * 20040426: the barrier is not strictly required but the
@@ -3516,6 +3804,9 @@ static int rtl8169_close(struct net_device *dev)
        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);
 
        free_irq(dev->irq, dev);
@@ -3658,6 +3949,11 @@ out:
        return 0;
 }
 
+static void rtl_shutdown(struct pci_dev *pdev)
+{
+       rtl8169_suspend(pdev, PMSG_SUSPEND);
+}
+
 #endif /* CONFIG_PM */
 
 static struct pci_driver rtl8169_pci_driver = {
@@ -3668,6 +3964,7 @@ static struct pci_driver rtl8169_pci_driver = {
 #ifdef CONFIG_PM
        .suspend        = rtl8169_suspend,
        .resume         = rtl8169_resume,
+       .shutdown       = rtl_shutdown,
 #endif
 };