diff -ruN r8169-6.012.00/src/r8169_n.c r8169-6.012.00-vr5/src/r8169_n.c
--- r8169-6.012.00/src/r8169_n.c	2010-01-19 06:41:17.000000000 +0300
+++ r8169-6.012.00-vr5/src/r8169_n.c	2011-01-01 04:18:02.000000000 +0300
@@ -1035,9 +1035,12 @@
 	u16	tx_underun;
 };
 
-static int rtl8169_get_stats_count(struct net_device *dev)
+static int rtl8169_get_sset_count(struct net_device *dev, int stringset)
 {
-	return ARRAY_SIZE(rtl8169_gstrings);
+	if (stringset == ETH_SS_STATS )
+		return ARRAY_SIZE(rtl8169_gstrings);
+
+	return -EINVAL;
 }
 
 static void rtl8169_get_ethtool_stats(struct net_device *dev,
@@ -1148,7 +1151,7 @@
 	.get_wol		= rtl8169_get_wol,
 	.set_wol		= rtl8169_set_wol,
 	.get_strings		= rtl8169_get_strings,
-	.get_stats_count	= rtl8169_get_stats_count,
+	.get_sset_count		= rtl8169_get_sset_count,
 	.get_ethtool_stats	= rtl8169_get_ethtool_stats,
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) 
 #ifdef ETHTOOL_GPERMADDR
@@ -1642,666 +1645,6 @@
 	rtl8169_set_speed(dev, autoneg, speed, duplex);
 }
 
-#ifdef ETHTOOL_OPS_COMPAT
-static int ethtool_get_settings(struct net_device *dev, void *useraddr)
-{
-	struct ethtool_cmd cmd = { ETHTOOL_GSET };
-	int err;
-
-	if (!ethtool_ops->get_settings)
-		return -EOPNOTSUPP;
-
-	err = ethtool_ops->get_settings(dev, &cmd);
-	if (err < 0)
-		return err;
-
-	if (copy_to_user(useraddr, &cmd, sizeof(cmd)))
-		return -EFAULT;
-	return 0;
-}
-
-static int ethtool_set_settings(struct net_device *dev, void *useraddr)
-{
-	struct ethtool_cmd cmd;
-
-	if (!ethtool_ops->set_settings)
-		return -EOPNOTSUPP;
-
-	if (copy_from_user(&cmd, useraddr, sizeof(cmd)))
-		return -EFAULT;
-
-	return ethtool_ops->set_settings(dev, &cmd);
-}
-
-static int ethtool_get_drvinfo(struct net_device *dev, void *useraddr)
-{
-	struct ethtool_drvinfo info;
-	struct ethtool_ops *ops = ethtool_ops;
-
-	if (!ops->get_drvinfo)
-		return -EOPNOTSUPP;
-
-	memset(&info, 0, sizeof(info));
-	info.cmd = ETHTOOL_GDRVINFO;
-	ops->get_drvinfo(dev, &info);
-
-	if (ops->self_test_count)
-		info.testinfo_len = ops->self_test_count(dev);
-	if (ops->get_stats_count)
-		info.n_stats = ops->get_stats_count(dev);
-	if (ops->get_regs_len)
-		info.regdump_len = ops->get_regs_len(dev);
-	if (ops->get_eeprom_len)
-		info.eedump_len = ops->get_eeprom_len(dev);
-
-	if (copy_to_user(useraddr, &info, sizeof(info)))
-		return -EFAULT;
-	return 0;
-}
-
-static int ethtool_get_regs(struct net_device *dev, char *useraddr)
-{
-	struct ethtool_regs regs;
-	struct ethtool_ops *ops = ethtool_ops;
-	void *regbuf;
-	int reglen, ret;
-
-	if (!ops->get_regs || !ops->get_regs_len)
-		return -EOPNOTSUPP;
-
-	if (copy_from_user(&regs, useraddr, sizeof(regs)))
-		return -EFAULT;
-
-	reglen = ops->get_regs_len(dev);
-	if (regs.len > reglen)
-		regs.len = reglen;
-
-	regbuf = kmalloc(reglen, GFP_USER);
-	if (!regbuf)
-		return -ENOMEM;
-
-	ops->get_regs(dev, &regs, regbuf);
-
-	ret = -EFAULT;
-	if (copy_to_user(useraddr, &regs, sizeof(regs)))
-		goto out;
-	useraddr += offsetof(struct ethtool_regs, data);
-	if (copy_to_user(useraddr, regbuf, reglen))
-		goto out;
-	ret = 0;
-
-out:
-	kfree(regbuf);
-	return ret;
-}
-
-static int ethtool_get_wol(struct net_device *dev, char *useraddr)
-{
-	struct ethtool_wolinfo wol = { ETHTOOL_GWOL };
-
-	if (!ethtool_ops->get_wol)
-		return -EOPNOTSUPP;
-
-	ethtool_ops->get_wol(dev, &wol);
-
-	if (copy_to_user(useraddr, &wol, sizeof(wol)))
-		return -EFAULT;
-	return 0;
-}
-
-static int ethtool_set_wol(struct net_device *dev, char *useraddr)
-{
-	struct ethtool_wolinfo wol;
-
-	if (!ethtool_ops->set_wol)
-		return -EOPNOTSUPP;
-
-	if (copy_from_user(&wol, useraddr, sizeof(wol)))
-		return -EFAULT;
-
-	return ethtool_ops->set_wol(dev, &wol);
-}
-
-static int ethtool_get_msglevel(struct net_device *dev, char *useraddr)
-{
-	struct ethtool_value edata = { ETHTOOL_GMSGLVL };
-
-	if (!ethtool_ops->get_msglevel)
-		return -EOPNOTSUPP;
-
-	edata.data = ethtool_ops->get_msglevel(dev);
-
-	if (copy_to_user(useraddr, &edata, sizeof(edata)))
-		return -EFAULT;
-	return 0;
-}
-
-static int ethtool_set_msglevel(struct net_device *dev, char *useraddr)
-{
-	struct ethtool_value edata;
-
-	if (!ethtool_ops->set_msglevel)
-		return -EOPNOTSUPP;
-
-	if (copy_from_user(&edata, useraddr, sizeof(edata)))
-		return -EFAULT;
-
-	ethtool_ops->set_msglevel(dev, edata.data);
-	return 0;
-}
-
-static int ethtool_nway_reset(struct net_device *dev)
-{
-	if (!ethtool_ops->nway_reset)
-		return -EOPNOTSUPP;
-
-	return ethtool_ops->nway_reset(dev);
-}
-
-static int ethtool_get_link(struct net_device *dev, void *useraddr)
-{
-	struct ethtool_value edata = { ETHTOOL_GLINK };
-
-	if (!ethtool_ops->get_link)
-		return -EOPNOTSUPP;
-
-	edata.data = ethtool_ops->get_link(dev);
-
-	if (copy_to_user(useraddr, &edata, sizeof(edata)))
-		return -EFAULT;
-	return 0;
-}
-
-static int ethtool_get_eeprom(struct net_device *dev, void *useraddr)
-{
-	struct ethtool_eeprom eeprom;
-	struct ethtool_ops *ops = ethtool_ops;
-	u8 *data;
-	int ret;
-
-	if (!ops->get_eeprom || !ops->get_eeprom_len)
-		return -EOPNOTSUPP;
-
-	if (copy_from_user(&eeprom, useraddr, sizeof(eeprom)))
-		return -EFAULT;
-
-	/* Check for wrap and zero */
-	if (eeprom.offset + eeprom.len <= eeprom.offset)
-		return -EINVAL;
-
-	/* Check for exceeding total eeprom len */
-	if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev))
-		return -EINVAL;
-
-	data = kmalloc(eeprom.len, GFP_USER);
-	if (!data)
-		return -ENOMEM;
-
-	ret = -EFAULT;
-	if (copy_from_user(data, useraddr + sizeof(eeprom), eeprom.len))
-		goto out;
-
-	ret = ops->get_eeprom(dev, &eeprom, data);
-	if (ret)
-		goto out;
-
-	ret = -EFAULT;
-	if (copy_to_user(useraddr, &eeprom, sizeof(eeprom)))
-		goto out;
-	if (copy_to_user(useraddr + sizeof(eeprom), data, eeprom.len))
-		goto out;
-	ret = 0;
-
-out:
-	kfree(data);
-	return ret;
-}
-
-static int ethtool_set_eeprom(struct net_device *dev, void *useraddr)
-{
-	struct ethtool_eeprom eeprom;
-	struct ethtool_ops *ops = ethtool_ops;
-	u8 *data;
-	int ret;
-
-	if (!ops->set_eeprom || !ops->get_eeprom_len)
-		return -EOPNOTSUPP;
-
-	if (copy_from_user(&eeprom, useraddr, sizeof(eeprom)))
-		return -EFAULT;
-
-	/* Check for wrap and zero */
-	if (eeprom.offset + eeprom.len <= eeprom.offset)
-		return -EINVAL;
-
-	/* Check for exceeding total eeprom len */
-	if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev))
-		return -EINVAL;
-
-	data = kmalloc(eeprom.len, GFP_USER);
-	if (!data)
-		return -ENOMEM;
-
-	ret = -EFAULT;
-	if (copy_from_user(data, useraddr + sizeof(eeprom), eeprom.len))
-		goto out;
-
-	ret = ops->set_eeprom(dev, &eeprom, data);
-	if (ret)
-		goto out;
-
-	if (copy_to_user(useraddr + sizeof(eeprom), data, eeprom.len))
-		ret = -EFAULT;
-
-out:
-	kfree(data);
-	return ret;
-}
-
-static int ethtool_get_coalesce(struct net_device *dev, void *useraddr)
-{
-	struct ethtool_coalesce coalesce = { ETHTOOL_GCOALESCE };
-
-	if (!ethtool_ops->get_coalesce)
-		return -EOPNOTSUPP;
-
-	ethtool_ops->get_coalesce(dev, &coalesce);
-
-	if (copy_to_user(useraddr, &coalesce, sizeof(coalesce)))
-		return -EFAULT;
-	return 0;
-}
-
-static int ethtool_set_coalesce(struct net_device *dev, void *useraddr)
-{
-	struct ethtool_coalesce coalesce;
-
-	if (!ethtool_ops->get_coalesce)
-		return -EOPNOTSUPP;
-
-	if (copy_from_user(&coalesce, useraddr, sizeof(coalesce)))
-		return -EFAULT;
-
-	return ethtool_ops->set_coalesce(dev, &coalesce);
-}
-
-static int ethtool_get_ringparam(struct net_device *dev, void *useraddr)
-{
-	struct ethtool_ringparam ringparam = { ETHTOOL_GRINGPARAM };
-
-	if (!ethtool_ops->get_ringparam)
-		return -EOPNOTSUPP;
-
-	ethtool_ops->get_ringparam(dev, &ringparam);
-
-	if (copy_to_user(useraddr, &ringparam, sizeof(ringparam)))
-		return -EFAULT;
-	return 0;
-}
-
-static int ethtool_set_ringparam(struct net_device *dev, void *useraddr)
-{
-	struct ethtool_ringparam ringparam;
-
-	if (!ethtool_ops->get_ringparam)
-		return -EOPNOTSUPP;
-
-	if (copy_from_user(&ringparam, useraddr, sizeof(ringparam)))
-		return -EFAULT;
-
-	return ethtool_ops->set_ringparam(dev, &ringparam);
-}
-
-static int ethtool_get_pauseparam(struct net_device *dev, void *useraddr)
-{
-	struct ethtool_pauseparam pauseparam = { ETHTOOL_GPAUSEPARAM };
-
-	if (!ethtool_ops->get_pauseparam)
-		return -EOPNOTSUPP;
-
-	ethtool_ops->get_pauseparam(dev, &pauseparam);
-
-	if (copy_to_user(useraddr, &pauseparam, sizeof(pauseparam)))
-		return -EFAULT;
-	return 0;
-}
-
-static int ethtool_set_pauseparam(struct net_device *dev, void *useraddr)
-{
-	struct ethtool_pauseparam pauseparam;
-
-	if (!ethtool_ops->get_pauseparam)
-		return -EOPNOTSUPP;
-
-	if (copy_from_user(&pauseparam, useraddr, sizeof(pauseparam)))
-		return -EFAULT;
-
-	return ethtool_ops->set_pauseparam(dev, &pauseparam);
-}
-
-static int ethtool_get_rx_csum(struct net_device *dev, char *useraddr)
-{
-	struct ethtool_value edata = { ETHTOOL_GRXCSUM };
-
-	if (!ethtool_ops->get_rx_csum)
-		return -EOPNOTSUPP;
-
-	edata.data = ethtool_ops->get_rx_csum(dev);
-
-	if (copy_to_user(useraddr, &edata, sizeof(edata)))
-		return -EFAULT;
-	return 0;
-}
-
-static int ethtool_set_rx_csum(struct net_device *dev, char *useraddr)
-{
-	struct ethtool_value edata;
-
-	if (!ethtool_ops->set_rx_csum)
-		return -EOPNOTSUPP;
-
-	if (copy_from_user(&edata, useraddr, sizeof(edata)))
-		return -EFAULT;
-
-	ethtool_ops->set_rx_csum(dev, edata.data);
-	return 0;
-}
-
-static int ethtool_get_tx_csum(struct net_device *dev, char *useraddr)
-{
-	struct ethtool_value edata = { ETHTOOL_GTXCSUM };
-
-	if (!ethtool_ops->get_tx_csum)
-		return -EOPNOTSUPP;
-
-	edata.data = ethtool_ops->get_tx_csum(dev);
-
-	if (copy_to_user(useraddr, &edata, sizeof(edata)))
-		return -EFAULT;
-	return 0;
-}
-
-static int ethtool_set_tx_csum(struct net_device *dev, char *useraddr)
-{
-	struct ethtool_value edata;
-
-	if (!ethtool_ops->set_tx_csum)
-		return -EOPNOTSUPP;
-
-	if (copy_from_user(&edata, useraddr, sizeof(edata)))
-		return -EFAULT;
-
-	return ethtool_ops->set_tx_csum(dev, edata.data);
-}
-
-static int ethtool_get_sg(struct net_device *dev, char *useraddr)
-{
-	struct ethtool_value edata = { ETHTOOL_GSG };
-
-	if (!ethtool_ops->get_sg)
-		return -EOPNOTSUPP;
-
-	edata.data = ethtool_ops->get_sg(dev);
-
-	if (copy_to_user(useraddr, &edata, sizeof(edata)))
-		return -EFAULT;
-	return 0;
-}
-
-static int ethtool_set_sg(struct net_device *dev, char *useraddr)
-{
-	struct ethtool_value edata;
-
-	if (!ethtool_ops->set_sg)
-		return -EOPNOTSUPP;
-
-	if (copy_from_user(&edata, useraddr, sizeof(edata)))
-		return -EFAULT;
-
-	return ethtool_ops->set_sg(dev, edata.data);
-}
-
-static int ethtool_get_tso(struct net_device *dev, char *useraddr)
-{
-	struct ethtool_value edata = { ETHTOOL_GTSO };
-
-	if (!ethtool_ops->get_tso)
-		return -EOPNOTSUPP;
-
-	edata.data = ethtool_ops->get_tso(dev);
-
-	if (copy_to_user(useraddr, &edata, sizeof(edata)))
-		return -EFAULT;
-	return 0;
-}
-
-static int ethtool_set_tso(struct net_device *dev, char *useraddr)
-{
-	struct ethtool_value edata;
-
-	if (!ethtool_ops->set_tso)
-		return -EOPNOTSUPP;
-
-	if (copy_from_user(&edata, useraddr, sizeof(edata)))
-		return -EFAULT;
-
-	return ethtool_ops->set_tso(dev, edata.data);
-}
-
-static int ethtool_self_test(struct net_device *dev, char *useraddr)
-{
-	struct ethtool_test test;
-	struct ethtool_ops *ops = ethtool_ops;
-	u64 *data;
-	int ret;
-
-	if (!ops->self_test || !ops->self_test_count)
-		return -EOPNOTSUPP;
-
-	if (copy_from_user(&test, useraddr, sizeof(test)))
-		return -EFAULT;
-
-	test.len = ops->self_test_count(dev);
-	data = kmalloc(test.len * sizeof(u64), GFP_USER);
-	if (!data)
-		return -ENOMEM;
-
-	ops->self_test(dev, &test, data);
-
-	ret = -EFAULT;
-	if (copy_to_user(useraddr, &test, sizeof(test)))
-		goto out;
-	useraddr += sizeof(test);
-	if (copy_to_user(useraddr, data, test.len * sizeof(u64)))
-		goto out;
-	ret = 0;
-
-out:
-	kfree(data);
-	return ret;
-}
-
-static int ethtool_get_strings(struct net_device *dev, void *useraddr)
-{
-	struct ethtool_gstrings gstrings;
-	struct ethtool_ops *ops = ethtool_ops;
-	u8 *data;
-	int ret;
-
-	if (!ops->get_strings)
-		return -EOPNOTSUPP;
-
-	if (copy_from_user(&gstrings, useraddr, sizeof(gstrings)))
-		return -EFAULT;
-
-	switch (gstrings.string_set) {
-	case ETH_SS_TEST:
-		if (!ops->self_test_count)
-			return -EOPNOTSUPP;
-		gstrings.len = ops->self_test_count(dev);
-		break;
-	case ETH_SS_STATS:
-		if (!ops->get_stats_count)
-			return -EOPNOTSUPP;
-		gstrings.len = ops->get_stats_count(dev);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	data = kmalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER);
-	if (!data)
-		return -ENOMEM;
-
-	ops->get_strings(dev, gstrings.string_set, data);
-
-	ret = -EFAULT;
-	if (copy_to_user(useraddr, &gstrings, sizeof(gstrings)))
-		goto out;
-	useraddr += sizeof(gstrings);
-	if (copy_to_user(useraddr, data, gstrings.len * ETH_GSTRING_LEN))
-		goto out;
-	ret = 0;
-
-out:
-	kfree(data);
-	return ret;
-}
-
-static int ethtool_phys_id(struct net_device *dev, void *useraddr)
-{
-	struct ethtool_value id;
-
-	if (!ethtool_ops->phys_id)
-		return -EOPNOTSUPP;
-
-	if (copy_from_user(&id, useraddr, sizeof(id)))
-		return -EFAULT;
-
-	return ethtool_ops->phys_id(dev, id.data);
-}
-
-static int ethtool_get_stats(struct net_device *dev, void *useraddr)
-{
-	struct ethtool_stats stats;
-	struct ethtool_ops *ops = ethtool_ops;
-	u64 *data;
-	int ret;
-
-	if (!ops->get_ethtool_stats || !ops->get_stats_count)
-		return -EOPNOTSUPP;
-
-	if (copy_from_user(&stats, useraddr, sizeof(stats)))
-		return -EFAULT;
-
-	stats.n_stats = ops->get_stats_count(dev);
-	data = kmalloc(stats.n_stats * sizeof(u64), GFP_USER);
-	if (!data)
-		return -ENOMEM;
-
-	ops->get_ethtool_stats(dev, &stats, data);
-
-	ret = -EFAULT;
-	if (copy_to_user(useraddr, &stats, sizeof(stats)))
-		goto out;
-	useraddr += sizeof(stats);
-	if (copy_to_user(useraddr, data, stats.n_stats * sizeof(u64)))
-		goto out;
-	ret = 0;
-
-out:
-	kfree(data);
-	return ret;
-}
-
-static int ethtool_ioctl(struct ifreq *ifr)
-{
-	struct net_device *dev = __dev_get_by_name(ifr->ifr_name);
-	void *useraddr = (void *) ifr->ifr_data;
-	u32 ethcmd;
-
-	/*
-	 * XXX: This can be pushed down into the ethtool_* handlers that
-	 * need it.  Keep existing behaviour for the moment.
-	 */
-	if (!capable(CAP_NET_ADMIN))
-		return -EPERM;
-
-	if (!dev || !netif_device_present(dev))
-		return -ENODEV;
-
-	if (copy_from_user(&ethcmd, useraddr, sizeof (ethcmd)))
-		return -EFAULT;
-
-	switch (ethcmd) {
-	case ETHTOOL_GSET:
-		return ethtool_get_settings(dev, useraddr);
-	case ETHTOOL_SSET:
-		return ethtool_set_settings(dev, useraddr);
-	case ETHTOOL_GDRVINFO:
-		return ethtool_get_drvinfo(dev, useraddr);
-	case ETHTOOL_GREGS:
-		return ethtool_get_regs(dev, useraddr);
-	case ETHTOOL_GWOL:
-		return ethtool_get_wol(dev, useraddr);
-	case ETHTOOL_SWOL:
-		return ethtool_set_wol(dev, useraddr);
-	case ETHTOOL_GMSGLVL:
-		return ethtool_get_msglevel(dev, useraddr);
-	case ETHTOOL_SMSGLVL:
-		return ethtool_set_msglevel(dev, useraddr);
-	case ETHTOOL_NWAY_RST:
-		return ethtool_nway_reset(dev);
-	case ETHTOOL_GLINK:
-		return ethtool_get_link(dev, useraddr);
-	case ETHTOOL_GEEPROM:
-		return ethtool_get_eeprom(dev, useraddr);
-	case ETHTOOL_SEEPROM:
-		return ethtool_set_eeprom(dev, useraddr);
-	case ETHTOOL_GCOALESCE:
-		return ethtool_get_coalesce(dev, useraddr);
-	case ETHTOOL_SCOALESCE:
-		return ethtool_set_coalesce(dev, useraddr);
-	case ETHTOOL_GRINGPARAM:
-		return ethtool_get_ringparam(dev, useraddr);
-	case ETHTOOL_SRINGPARAM:
-		return ethtool_set_ringparam(dev, useraddr);
-	case ETHTOOL_GPAUSEPARAM:
-		return ethtool_get_pauseparam(dev, useraddr);
-	case ETHTOOL_SPAUSEPARAM:
-		return ethtool_set_pauseparam(dev, useraddr);
-	case ETHTOOL_GRXCSUM:
-		return ethtool_get_rx_csum(dev, useraddr);
-	case ETHTOOL_SRXCSUM:
-		return ethtool_set_rx_csum(dev, useraddr);
-	case ETHTOOL_GTXCSUM:
-		return ethtool_get_tx_csum(dev, useraddr);
-	case ETHTOOL_STXCSUM:
-		return ethtool_set_tx_csum(dev, useraddr);
-	case ETHTOOL_GSG:
-		return ethtool_get_sg(dev, useraddr);
-	case ETHTOOL_SSG:
-		return ethtool_set_sg(dev, useraddr);
-	case ETHTOOL_GTSO:
-		return ethtool_get_tso(dev, useraddr);
-	case ETHTOOL_STSO:
-		return ethtool_set_tso(dev, useraddr);
-	case ETHTOOL_TEST:
-		return ethtool_self_test(dev, useraddr);
-	case ETHTOOL_GSTRINGS:
-		return ethtool_get_strings(dev, useraddr);
-	case ETHTOOL_PHYS_ID:
-		return ethtool_phys_id(dev, useraddr);
-	case ETHTOOL_GSTATS:
-		return ethtool_get_stats(dev, useraddr);
-	default:
-		return -EOPNOTSUPP;
-	}
-
-	return -EOPNOTSUPP;
-}
-#endif //ETHTOOL_OPS_COMPAT
-
 static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
@@ -3648,31 +2991,28 @@
 {
 	struct net_device *dev = (struct net_device *) dev_instance;
 	struct rtl8169_private *tp = netdev_priv(dev);
-	int boguscnt = max_interrupt_work;
 	void __iomem *ioaddr = tp->mmio_addr;
 	int status;
 	int handled = IRQ_NONE;
 
-	do {
-		status = RTL_R16(IntrStatus);
-
-		/* hotplug/major error/no more work/shared irq */
-		if ((status == 0xFFFF) || !status)
-			break;
-
+	status = RTL_R16(IntrStatus);
+	while (status && status != 0xffff) {
 		handled = IRQ_HANDLED;
 
 		if (unlikely(!netif_running(dev))) {
 			rtl8169_asic_down(ioaddr);
-			goto out;
+			break;
 		}
 
-		status &= tp->intr_mask;
-		RTL_W16(IntrStatus,
-			(status & RxFIFOOver) ? (status | RxOverflow) : status);
-
-		if (!(status & rtl8169_intr_mask))
+#if 0
+		/* 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;
+		}
+#endif
 
 		if (unlikely(status & SYSErr)) {
 			rtl8169_pcierr_interrupt(dev);
@@ -3682,8 +3022,8 @@
 		if (status & LinkChg)
 			rtl8169_check_link_status(dev, tp, ioaddr);
 
-#ifdef CONFIG_R8169_NAPI
-		if (status & rtl8169_napi_event) {
+		rtl_rmb();
+		if (status & tp->intr_mask & rtl8169_napi_event) {
 			RTL_W16(IntrMask, rtl8169_intr_mask & ~rtl8169_napi_event);
 			tp->intr_mask = ~rtl8169_napi_event;
 
@@ -3694,31 +3034,12 @@
 				       dev->name, status);
 			}
 		}
-		break;
-#else
-		/* Rx interrupt */
-		if (status & (RxOK | RxOverflow | RxFIFOOver)) {
-			rtl8169_rx_interrupt(dev, tp, tp->mmio_addr, ~(u32)0);
-		}
 
-		/* Tx interrupt */
-		if (status & (TxOK | TxErr)) {
-			rtl8169_tx_interrupt(dev, tp, ioaddr);
-		}
-#endif
-
-		boguscnt--;
-	} while (boguscnt > 0);
-
-	if (boguscnt <= 0) {
-		if (netif_msg_intr(tp) && net_ratelimit()) {
-			printk(KERN_WARNING
-			       "%s: Too much work at interrupt!\n", dev->name);
-		}
-		/* Clear all interrupt sources. */
-		RTL_W16(IntrStatus, 0xffff);
+                RTL_W16(IntrStatus,
+			(status & RxFIFOOver) ? (status | RxOverflow) : status);
+		status = RTL_R16(IntrStatus);
 	}
-out:
+
 	return IRQ_RETVAL(handled);;
 }
 
@@ -3848,7 +3169,7 @@
 	void __iomem *ioaddr = tp->mmio_addr;
 	unsigned long flags;
 	u32 mc_filter[2];	/* Multicast hash filter */
-	int i, rx_mode;
+	int rx_mode;
 	u32 tmp = 0;
 
 	if (dev->flags & IFF_PROMISC) {
@@ -3862,20 +3183,19 @@
 		    AcceptBroadcast | AcceptMulticast | AcceptMyPhys |
 		    AcceptAllPhys;
 		mc_filter[1] = mc_filter[0] = 0xffffffff;
-	} else if ((dev->mc_count > multicast_filter_limit)
+	} else if ((netdev_mc_count(dev) > multicast_filter_limit)
 		   || (dev->flags & IFF_ALLMULTI)) {
 		/* Too many to filter perfectly -- accept all multicasts. */
 
 		rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
 		mc_filter[1] = mc_filter[0] = 0xffffffff;
 	} else {
-		struct dev_mc_list *mclist;
+		struct netdev_hw_addr *ha;
 
 		rx_mode = AcceptBroadcast | AcceptMyPhys;
 		mc_filter[1] = mc_filter[0] = 0;
-		for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
-		     i++, mclist = mclist->next) {
-			int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26;
+		netdev_for_each_mc_addr(ha, dev) {
+			int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26;
 			mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
 			rx_mode |= AcceptMulticast;
 		}
