From d437c22e8928841a17c4c003feb7a4bb4b13c608 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Mon, 26 Nov 2012 15:49:36 +0100 Subject: [PATCH] linux: update RTL8168 patch Signed-off-by: Stephan Raue --- ...h => linux-3.6.7-920-r8168_8.034.00.patch} | 10269 +++------------- 1 file changed, 1643 insertions(+), 8626 deletions(-) rename packages/linux/patches/{linux-3.6.7-920-add_rtl8168.patch => linux-3.6.7-920-r8168_8.034.00.patch} (75%) diff --git a/packages/linux/patches/linux-3.6.7-920-add_rtl8168.patch b/packages/linux/patches/linux-3.6.7-920-r8168_8.034.00.patch similarity index 75% rename from packages/linux/patches/linux-3.6.7-920-add_rtl8168.patch rename to packages/linux/patches/linux-3.6.7-920-r8168_8.034.00.patch index 17eb676896..cd9b79a811 100644 --- a/packages/linux/patches/linux-3.6.7-920-add_rtl8168.patch +++ b/packages/linux/patches/linux-3.6.7-920-r8168_8.034.00.patch @@ -1,7 +1,7 @@ -diff -rupN a/drivers/net/ethernet/realtek/Kconfig b/drivers/net/ethernet/realtek/Kconfig ---- a/drivers/net/ethernet/realtek/Kconfig 2012-10-22 15:38:20.939012106 +0300 -+++ b/drivers/net/ethernet/realtek/Kconfig 2012-10-25 11:47:00.606571613 +0300 -@@ -102,6 +102,27 @@ config 8139_OLD_RX_RESET +diff -Naur linux-3.4.19-old/drivers/net/ethernet/realtek/Kconfig linux-3.4.19-new/drivers/net/ethernet/realtek/Kconfig +--- linux-3.4.19-old/drivers/net/ethernet/realtek/Kconfig 2012-11-22 22:29:39.000000000 -0800 ++++ linux-3.4.19-new/drivers/net/ethernet/realtek/Kconfig 2012-11-22 22:30:06.000000000 -0800 +@@ -102,6 +102,27 @@ experience problems, you can enable this option to restore the old RX-reset behavior. If unsure, say N. @@ -13,33 +13,41 @@ diff -rupN a/drivers/net/ethernet/realtek/Kconfig b/drivers/net/ethernet/realtek + select NET_CORE + select MII + ---help--- -+ Say Y here if you have a Realtek 8168 Gigabit Ethernet adapter. ++ Say Y here if you have a Realtek 8168 PCI Gigabit Ethernet adapter. + + To compile this driver as a module, choose M here: the module + will be called r8168. This is recommended. + +config R8168_NAPI + bool "Realtek 8168 NAPI support" -+ depends on R8168 ++ depends on R8168 + +config R8168_VLAN + bool "Realtek 8168 VLAN support" -+ depends on R8168 ++ depends on R8168 + config R8169 tristate "Realtek 8169 gigabit ethernet support" depends on PCI -diff -rupN a/drivers/net/ethernet/realtek/Makefile b/drivers/net/ethernet/realtek/Makefile ---- a/drivers/net/ethernet/realtek/Makefile 2012-10-22 15:38:20.943012225 +0300 -+++ b/drivers/net/ethernet/realtek/Makefile 2012-10-25 11:47:00.606571613 +0300 -@@ -6,3 +6,4 @@ obj-$(CONFIG_8139CP) += 8139cp.o +diff -Naur linux-3.4.19-old/drivers/net/ethernet/realtek/Makefile linux-3.4.19-new/drivers/net/ethernet/realtek/Makefile +--- linux-3.4.19-old/drivers/net/ethernet/realtek/Makefile 2012-11-22 22:29:39.000000000 -0800 ++++ linux-3.4.19-new/drivers/net/ethernet/realtek/Makefile 2012-11-22 22:30:06.000000000 -0800 +@@ -5,4 +5,5 @@ + obj-$(CONFIG_8139CP) += 8139cp.o obj-$(CONFIG_8139TOO) += 8139too.o obj-$(CONFIG_ATP) += atp.o ++obj-$(CONFIG_R8168) += r8168/ obj-$(CONFIG_R8169) += r8169.o -+obj-$(CONFIG_R8168) += r8168_n.o r8168_asf.o rtl_eeprom.o rtltool.o -diff -rupN a/drivers/net/ethernet/realtek/r8168_asf.c b/drivers/net/ethernet/realtek/r8168_asf.c ---- a/drivers/net/ethernet/realtek/r8168_asf.c 1970-01-01 03:00:00.000000000 +0300 -+++ b/drivers/net/ethernet/realtek/r8168_asf.c 2012-10-25 11:47:40.983859578 +0300 +diff -Naur linux-3.4.19-old/drivers/net/ethernet/realtek/r8168/Makefile linux-3.4.19-new/drivers/net/ethernet/realtek/r8168/Makefile +--- linux-3.4.19-old/drivers/net/ethernet/realtek/r8168/Makefile 1969-12-31 16:00:00.000000000 -0800 ++++ linux-3.4.19-new/drivers/net/ethernet/realtek/r8168/Makefile 2012-11-22 22:30:06.000000000 -0800 +@@ -0,0 +1,3 @@ ++obj-$(CONFIG_R8168) += r8168.o ++ ++r8168-objs := r8168_n.o r8168_asf.o rtl_eeprom.o rtltool.o +diff -Naur linux-3.4.19-old/drivers/net/ethernet/realtek/r8168/r8168_asf.c linux-3.4.19-new/drivers/net/ethernet/realtek/r8168/r8168_asf.c +--- linux-3.4.19-old/drivers/net/ethernet/realtek/r8168/r8168_asf.c 1969-12-31 16:00:00.000000000 -0800 ++++ linux-3.4.19-new/drivers/net/ethernet/realtek/r8168/r8168_asf.c 2012-07-19 01:24:28.000000000 -0700 @@ -0,0 +1,420 @@ +/* +################################################################################ @@ -461,9 +469,9 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_asf.c b/drivers/net/ethernet/rea + for (i = UUID_LEN - 1, j = 0; i >= 0 ; i--, j++) + rtl8168_eri_write(ioaddr, UUID + i, RW_ONE_BYTE, data[j], ERIAR_ASF); +} -diff -rupN a/drivers/net/ethernet/realtek/r8168_asf.h b/drivers/net/ethernet/realtek/r8168_asf.h ---- a/drivers/net/ethernet/realtek/r8168_asf.h 1970-01-01 03:00:00.000000000 +0300 -+++ b/drivers/net/ethernet/realtek/r8168_asf.h 2012-10-25 11:47:40.983859577 +0300 +diff -Naur linux-3.4.19-old/drivers/net/ethernet/realtek/r8168/r8168_asf.h linux-3.4.19-new/drivers/net/ethernet/realtek/r8168/r8168_asf.h +--- linux-3.4.19-old/drivers/net/ethernet/realtek/r8168/r8168_asf.h 1969-12-31 16:00:00.000000000 -0800 ++++ linux-3.4.19-new/drivers/net/ethernet/realtek/r8168/r8168_asf.h 2012-07-19 01:24:28.000000000 -0700 @@ -0,0 +1,295 @@ +/* +################################################################################ @@ -760,1306 +768,1313 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_asf.h b/drivers/net/ethernet/rea +void rtl8168_asf_rw_iana(void __iomem *ioaddr, int arg, unsigned int *data); +void rtl8168_asf_rw_uuid(void __iomem *ioaddr, int arg, unsigned int *data); +void rtl8168_asf_rw_systemid(void __iomem *ioaddr, int arg, unsigned int *data); -diff -rupN a/drivers/net/ethernet/realtek/r8168.h b/drivers/net/ethernet/realtek/r8168.h ---- a/drivers/net/ethernet/realtek/r8168.h 1970-01-01 03:00:00.000000000 +0300 -+++ b/drivers/net/ethernet/realtek/r8168.h 2012-10-25 11:47:40.991860929 +0300 -@@ -0,0 +1,1292 @@ -+/* -+################################################################################ -+# -+# r8168 is the Linux device driver released for RealTek RTL8168B/8111B, -+# RTL8168C/8111C, RTL8168CP/8111CP, RTL8168D/8111D, and RTL8168DP/8111DP, and -+# RTK8168E/8111E Gigabit Ethernet controllers with PCI-Express interface. -+# -+# Copyright(c) 2012 Realtek Semiconductor Corp. All rights reserved. -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms of the GNU General Public License as published by the Free -+# Software Foundation; either version 2 of the License, or (at your option) -+# any later version. -+# -+# This program is distributed in the hope that it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, see . -+# -+# Author: -+# Realtek NIC software team -+# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -+# -+################################################################################ -+*/ -+ -+/* -+ * This product is covered by one or more of the following patents: -+ * US5,307,459, US5,434,872, US5,732,094, US6,570,884, US6,115,776, and US6,327,625. -+ */ -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) -+#define CHECKSUM_PARTIAL CHECKSUM_HW -+#endif -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -+ #define irqreturn_t void -+ #define IRQ_HANDLED 1 -+ #define IRQ_NONE 0 -+ #define IRQ_RETVAL(x) -+#endif -+ -+#ifndef HAVE_FREE_NETDEV -+#define free_netdev(x) kfree(x) -+#endif -+ -+#ifndef SET_NETDEV_DEV -+#define SET_NETDEV_DEV(net, pdev) -+#endif -+ -+#ifndef SET_MODULE_OWNER -+#define SET_MODULE_OWNER(dev) -+#endif -+ -+#ifndef SA_SHIRQ -+#define SA_SHIRQ IRQF_SHARED -+#endif -+ -+#ifndef NETIF_F_GSO -+#define gso_size tso_size -+#define gso_segs tso_segs -+#endif -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) -+ #ifdef CONFIG_NET_POLL_CONTROLLER -+ #define RTL_NET_POLL_CONTROLLER dev->poll_controller=rtl8168_netpoll -+ #else -+ #define RTL_NET_POLL_CONTROLLER -+ #endif -+ -+ #ifdef CONFIG_R8168_VLAN -+ #define RTL_SET_VLAN dev->vlan_rx_register=rtl8168_vlan_rx_register -+ #else -+ #define RTL_SET_VLAN -+ #endif -+ -+ #define RTL_NET_DEVICE_OPS(ops) dev->open=rtl8168_open; \ -+ dev->hard_start_xmit=rtl8168_start_xmit; \ -+ dev->get_stats=rtl8168_get_stats; \ -+ dev->stop=rtl8168_close; \ -+ dev->tx_timeout=rtl8168_tx_timeout; \ -+ dev->set_multicast_list=rtl8168_set_rx_mode; \ -+ dev->change_mtu=rtl8168_change_mtu; \ -+ dev->set_mac_address=rtl8168_set_mac_address; \ -+ dev->do_ioctl=rtl8168_do_ioctl; \ -+ RTL_NET_POLL_CONTROLLER; \ -+ RTL_SET_VLAN; -+#else -+ #define RTL_NET_DEVICE_OPS(ops) dev->netdev_ops=&ops -+#endif -+ -+//Due to the hardware design of RTL8111B, the low 32 bit address of receive -+//buffer must be 8-byte alignment. -+#ifndef NET_IP_ALIGN -+#define NET_IP_ALIGN 2 -+#endif -+#define RTK_RX_ALIGN 8 -+ -+#ifdef CONFIG_R8168_NAPI -+#define NAPI_SUFFIX "-NAPI" -+#else -+#define NAPI_SUFFIX "" -+#endif -+ -+#define RTL8168_VERSION "8.032.00" NAPI_SUFFIX -+#define MODULENAME "r8168" -+#define PFX MODULENAME ": " -+ -+#define GPL_CLAIM "\ -+r8168 Copyright (C) 2012 Realtek NIC software team \n \ -+This program comes with ABSOLUTELY NO WARRANTY; for details, please see . \n \ -+This is free software, and you are welcome to redistribute it under certain conditions; see . \n" -+ -+#ifdef RTL8168_DEBUG -+#define assert(expr) \ -+ if(!(expr)) { \ -+ printk( "Assertion failed! %s,%s,%s,line=%d\n", \ -+ #expr,__FILE__,__FUNCTION__,__LINE__); \ -+ } -+#define dprintk(fmt, args...) do { printk(PFX fmt, ## args); } while (0) -+#else -+#define assert(expr) do {} while (0) -+#define dprintk(fmt, args...) do {} while (0) -+#endif /* RTL8168_DEBUG */ -+ -+#define R8168_MSG_DEFAULT \ -+ (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN) -+ -+#define TX_BUFFS_AVAIL(tp) \ -+ (tp->dirty_tx + NUM_TX_DESC - tp->cur_tx - 1) -+ -+#ifdef CONFIG_R8168_NAPI -+#define rtl8168_rx_skb netif_receive_skb -+#define rtl8168_rx_hwaccel_skb vlan_hwaccel_receive_skb -+#define rtl8168_rx_quota(count, quota) min(count, quota) -+#else -+#define rtl8168_rx_skb netif_rx -+#define rtl8168_rx_hwaccel_skb vlan_hwaccel_rx -+#define rtl8168_rx_quota(count, quota) count -+#endif -+ -+/* MAC address length */ -+#ifndef MAC_ADDR_LEN -+#define MAC_ADDR_LEN 6 -+#endif -+ -+#ifndef MAC_PROTOCOL_LEN -+#define MAC_PROTOCOL_LEN 2 -+#endif -+ -+#define Reserved2_data 7 -+#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ -+#define TX_DMA_BURST_unlimited 7 -+#define TX_DMA_BURST_1024 6 -+#define TX_DMA_BURST_512 5 -+#define TX_DMA_BURST_256 4 -+#define TX_DMA_BURST_128 3 -+#define TX_DMA_BURST_64 2 -+#define TX_DMA_BURST_32 1 -+#define TX_DMA_BURST_16 0 -+#define Reserved1_data 0x3F -+#define RxPacketMaxSize 0x3FE8 /* 16K - 1 - ETH_HLEN - VLAN - CRC... */ -+#define Jumbo_Frame_2k (2 * 1024) -+#define Jumbo_Frame_3k (3 * 1024) -+#define Jumbo_Frame_4k (4 * 1024) -+#define Jumbo_Frame_5k (5 * 1024) -+#define Jumbo_Frame_6k (6 * 1024) -+#define Jumbo_Frame_7k (7 * 1024) -+#define Jumbo_Frame_8k (8 * 1024) -+#define Jumbo_Frame_9k (9 * 1024) -+#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ -+#define RxEarly_off (1 << 11) -+ -+#define R8168_REGS_SIZE 256 -+#define R8168_NAPI_WEIGHT 64 -+ -+#define RX_BUF_SIZE 0x05F3 /* 0x05F3 = 1522bye + 1 */ -+#define R8168_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc)) -+#define R8168_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc)) -+ -+#define RTL8168_TX_TIMEOUT (6 * HZ) -+#define RTL8168_LINK_TIMEOUT (1 * HZ) -+#define RTL8168_ESD_TIMEOUT (2 * HZ) -+ -+#define NUM_TX_DESC 1024 /* Number of Tx descriptor registers */ -+#define NUM_RX_DESC 1024 /* Number of Rx descriptor registers */ -+ -+#define NODE_ADDRESS_SIZE 6 -+ -+/* write/read MMIO register */ -+#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) -+#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg)) -+#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg)) -+#define RTL_R8(reg) readb (ioaddr + (reg)) -+#define RTL_R16(reg) readw (ioaddr + (reg)) -+#define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg))) -+ -+#ifndef DMA_64BIT_MASK -+#define DMA_64BIT_MASK 0xffffffffffffffffULL -+#endif -+ -+#ifndef DMA_32BIT_MASK -+#define DMA_32BIT_MASK 0x00000000ffffffffULL -+#endif -+ -+#ifndef NETDEV_TX_OK -+#define NETDEV_TX_OK 0 /* driver took care of packet */ -+#endif -+ -+#ifndef NETDEV_TX_BUSY -+#define NETDEV_TX_BUSY 1 /* driver tx path was busy*/ -+#endif -+ -+#ifndef NETDEV_TX_LOCKED -+#define NETDEV_TX_LOCKED -1 /* driver tx lock was already taken */ -+#endif -+ -+#ifndef ADVERTISED_Pause -+#define ADVERTISED_Pause (1 << 13) -+#endif -+ -+#ifndef ADVERTISED_Asym_Pause -+#define ADVERTISED_Asym_Pause (1 << 14) -+#endif -+ -+#ifndef ADVERTISE_PAUSE_CAP -+#define ADVERTISE_PAUSE_CAP 0x400 -+#endif -+ -+#ifndef ADVERTISE_PAUSE_ASYM -+#define ADVERTISE_PAUSE_ASYM 0x800 -+#endif -+ -+#ifndef MII_CTRL1000 -+#define MII_CTRL1000 0x09 -+#endif -+ -+#ifndef ADVERTISE_1000FULL -+#define ADVERTISE_1000FULL 0x200 -+#endif -+ -+#ifndef ADVERTISE_1000HALF -+#define ADVERTISE_1000HALF 0x100 -+#endif -+ -+/*****************************************************************************/ -+ -+//#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3) -+#if (( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,27) ) || \ -+ (( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) ) && \ -+ ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3) ))) -+/* copied from linux kernel 2.6.20 include/linux/netdev.h */ -+#define NETDEV_ALIGN 32 -+#define NETDEV_ALIGN_CONST (NETDEV_ALIGN - 1) -+ -+static inline void *netdev_priv(struct net_device *dev) -+{ -+ return (char *)dev + ((sizeof(struct net_device) -+ + NETDEV_ALIGN_CONST) -+ & ~NETDEV_ALIGN_CONST); -+} -+#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3) -+ -+/*****************************************************************************/ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) -+ #define RTLDEV tp -+#else -+ #define RTLDEV dev -+#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) -+/*****************************************************************************/ -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) -+ typedef struct net_device *napi_ptr; -+ typedef int *napi_budget; -+ -+ #define napi dev -+ #define RTL_NAPI_CONFIG(ndev, priv, function, weig) ndev->poll=function; \ -+ ndev->weight=weig; -+ #define RTL_NAPI_QUOTA(budget, ndev) min(*budget, ndev->quota) -+ #define RTL_GET_PRIV(stuct_ptr, priv_struct) netdev_priv(stuct_ptr) -+ #define RTL_GET_NETDEV(priv_ptr) -+ #define RTL_RX_QUOTA(ndev, budget) ndev->quota -+ #define RTL_NAPI_QUOTA_UPDATE(ndev, work_done, budget) *budget -= work_done; \ -+ ndev->quota -= work_done; -+ #define RTL_NETIF_RX_COMPLETE(dev, napi) netif_rx_complete(dev) -+ #define RTL_NETIF_RX_SCHEDULE_PREP(dev, napi) netif_rx_schedule_prep(dev) -+ #define __RTL_NETIF_RX_SCHEDULE(dev, napi) __netif_rx_schedule(dev) -+ #define RTL_NAPI_RETURN_VALUE work_done >= work_to_do -+ #define RTL_NAPI_ENABLE(dev, napi) netif_poll_enable(dev) -+ #define RTL_NAPI_DISABLE(dev, napi) netif_poll_disable(dev) -+ #define DMA_BIT_MASK(value) ((1ULL << value) - 1) -+#else -+ typedef struct napi_struct *napi_ptr; -+ typedef int napi_budget; -+ -+ #define RTL_NAPI_CONFIG(ndev, priv, function, weight) netif_napi_add(ndev, &priv->napi, function, weight) -+ #define RTL_NAPI_QUOTA(budget, ndev) min(budget, budget) -+ #define RTL_GET_PRIV(stuct_ptr, priv_struct) container_of(stuct_ptr, priv_struct, stuct_ptr) -+ #define RTL_GET_NETDEV(priv_ptr) struct net_device *dev = priv_ptr->dev; -+ #define RTL_RX_QUOTA(ndev, budget) budget -+ #define RTL_NAPI_QUOTA_UPDATE(ndev, work_done, budget) -+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) -+ #define RTL_NETIF_RX_COMPLETE(dev, napi) netif_rx_complete(dev, napi) -+ #define RTL_NETIF_RX_SCHEDULE_PREP(dev, napi) netif_rx_schedule_prep(dev, napi) -+ #define __RTL_NETIF_RX_SCHEDULE(dev, napi) __netif_rx_schedule(dev, napi) -+ #endif -+ #if LINUX_VERSION_CODE == KERNEL_VERSION(2,6,29) -+ #define RTL_NETIF_RX_COMPLETE(dev, napi) netif_rx_complete(napi) -+ #define RTL_NETIF_RX_SCHEDULE_PREP(dev, napi) netif_rx_schedule_prep(napi) -+ #define __RTL_NETIF_RX_SCHEDULE(dev, napi) __netif_rx_schedule(napi) -+ #endif -+ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) -+ #define RTL_NETIF_RX_COMPLETE(dev, napi) napi_complete(napi) -+ #define RTL_NETIF_RX_SCHEDULE_PREP(dev, napi) napi_schedule_prep(napi) -+ #define __RTL_NETIF_RX_SCHEDULE(dev, napi) __napi_schedule(napi) -+ #endif -+ #define RTL_NAPI_RETURN_VALUE work_done -+ #define RTL_NAPI_ENABLE(dev, napi) napi_enable(napi) -+ #define RTL_NAPI_DISABLE(dev, napi) napi_disable(napi) -+#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) -+ -+/*****************************************************************************/ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) -+#ifdef __CHECKER__ -+#define __iomem __attribute__((noderef, address_space(2))) -+extern void __chk_io_ptr(void __iomem *); -+#define __bitwise __attribute__((bitwise)) -+#else -+#define __iomem -+#define __chk_io_ptr(x) (void)0 -+#define __bitwise -+#endif -+#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) -+ -+/*****************************************************************************/ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) -+#ifdef __CHECKER__ -+#define __force __attribute__((force)) -+#else -+#define __force -+#endif -+#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) -+ -+#ifndef module_param -+#define module_param(v,t,p) MODULE_PARM(v, "i"); -+#endif -+ -+#ifndef PCI_DEVICE -+#define PCI_DEVICE(vend,dev) \ -+ .vendor = (vend), .device = (dev), \ -+ .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID -+#endif -+ -+/*****************************************************************************/ -+/* 2.5.28 => 2.4.23 */ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,5,28) ) -+ -+static inline void _kc_synchronize_irq(void) -+{ -+ synchronize_irq(); -+} -+#undef synchronize_irq -+#define synchronize_irq(X) _kc_synchronize_irq() -+ -+#include -+#define work_struct tq_struct -+#undef INIT_WORK -+#define INIT_WORK(a,b,c) INIT_TQUEUE(a,(void (*)(void *))b,c) -+#undef container_of -+#define container_of list_entry -+#define schedule_work schedule_task -+#define flush_scheduled_work flush_scheduled_tasks -+#endif /* 2.5.28 => 2.4.17 */ -+ -+/*****************************************************************************/ -+/* 2.6.4 => 2.6.0 */ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,4) ) -+#define MODULE_VERSION(_version) MODULE_INFO(version, _version) -+#endif /* 2.6.4 => 2.6.0 */ -+/*****************************************************************************/ -+/* 2.6.0 => 2.5.28 */ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) ) -+#define MODULE_INFO(version, _version) -+#ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT -+#define CONFIG_E1000_DISABLE_PACKET_SPLIT 1 -+#endif -+ -+#define pci_set_consistent_dma_mask(dev,mask) 1 -+ -+#undef dev_put -+#define dev_put(dev) __dev_put(dev) -+ -+#ifndef skb_fill_page_desc -+#define skb_fill_page_desc _kc_skb_fill_page_desc -+extern void _kc_skb_fill_page_desc(struct sk_buff *skb, int i, struct page *page, int off, int size); -+#endif -+ -+#ifndef pci_dma_mapping_error -+#define pci_dma_mapping_error _kc_pci_dma_mapping_error -+static inline int _kc_pci_dma_mapping_error(dma_addr_t dma_addr) -+{ -+ return dma_addr == 0; -+} -+#endif -+ -+#undef ALIGN -+#define ALIGN(x,a) (((x)+(a)-1)&~((a)-1)) -+ -+#endif /* 2.6.0 => 2.5.28 */ -+ -+/*****************************************************************************/ -+/* 2.4.22 => 2.4.17 */ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,22) ) -+#define pci_name(x) ((x)->slot_name) -+#endif /* 2.4.22 => 2.4.17 */ -+ -+/*****************************************************************************/ -+/* 2.6.5 => 2.6.0 */ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5) ) -+#define pci_dma_sync_single_for_cpu pci_dma_sync_single -+#define pci_dma_sync_single_for_device pci_dma_sync_single_for_cpu -+#endif /* 2.6.5 => 2.6.0 */ -+ -+/*****************************************************************************/ -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -+/* -+ * initialize a work-struct's func and data pointers: -+ */ -+#define PREPARE_WORK(_work, _func, _data) \ -+ do { \ -+ (_work)->func = _func; \ -+ (_work)->data = _data; \ -+ } while (0) -+ -+#endif -+/*****************************************************************************/ -+/* 2.6.4 => 2.6.0 */ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,25) || \ -+ ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) && \ -+ LINUX_VERSION_CODE < KERNEL_VERSION(2,6,4) ) ) -+#define ETHTOOL_OPS_COMPAT -+#endif /* 2.6.4 => 2.6.0 */ -+ -+/*****************************************************************************/ -+/* Installations with ethtool version without eeprom, adapter id, or statistics -+ * support */ -+ -+#ifndef ETH_GSTRING_LEN -+#define ETH_GSTRING_LEN 32 -+#endif -+ -+#ifndef ETHTOOL_GSTATS -+#define ETHTOOL_GSTATS 0x1d -+#undef ethtool_drvinfo -+#define ethtool_drvinfo k_ethtool_drvinfo -+struct k_ethtool_drvinfo { -+ u32 cmd; -+ char driver[32]; -+ char version[32]; -+ char fw_version[32]; -+ char bus_info[32]; -+ char reserved1[32]; -+ char reserved2[16]; -+ u32 n_stats; -+ u32 testinfo_len; -+ u32 eedump_len; -+ u32 regdump_len; -+}; -+ -+struct ethtool_stats { -+ u32 cmd; -+ u32 n_stats; -+ u64 data[0]; -+}; -+#endif /* ETHTOOL_GSTATS */ -+ -+#ifndef ETHTOOL_PHYS_ID -+#define ETHTOOL_PHYS_ID 0x1c -+#endif /* ETHTOOL_PHYS_ID */ -+ -+#ifndef ETHTOOL_GSTRINGS -+#define ETHTOOL_GSTRINGS 0x1b -+enum ethtool_stringset { -+ ETH_SS_TEST = 0, -+ ETH_SS_STATS, -+}; -+struct ethtool_gstrings { -+ u32 cmd; /* ETHTOOL_GSTRINGS */ -+ u32 string_set; /* string set id e.c. ETH_SS_TEST, etc*/ -+ u32 len; /* number of strings in the string set */ -+ u8 data[0]; -+}; -+#endif /* ETHTOOL_GSTRINGS */ -+ -+#ifndef ETHTOOL_TEST -+#define ETHTOOL_TEST 0x1a -+enum ethtool_test_flags { -+ ETH_TEST_FL_OFFLINE = (1 << 0), -+ ETH_TEST_FL_FAILED = (1 << 1), -+}; -+struct ethtool_test { -+ u32 cmd; -+ u32 flags; -+ u32 reserved; -+ u32 len; -+ u64 data[0]; -+}; -+#endif /* ETHTOOL_TEST */ -+ -+#ifndef ETHTOOL_GEEPROM -+#define ETHTOOL_GEEPROM 0xb -+#undef ETHTOOL_GREGS -+struct ethtool_eeprom { -+ u32 cmd; -+ u32 magic; -+ u32 offset; -+ u32 len; -+ u8 data[0]; -+}; -+ -+struct ethtool_value { -+ u32 cmd; -+ u32 data; -+}; -+#endif /* ETHTOOL_GEEPROM */ -+ -+#ifndef ETHTOOL_GLINK -+#define ETHTOOL_GLINK 0xa -+#endif /* ETHTOOL_GLINK */ -+ -+#ifndef ETHTOOL_GREGS -+#define ETHTOOL_GREGS 0x00000004 /* Get NIC registers */ -+#define ethtool_regs _kc_ethtool_regs -+/* for passing big chunks of data */ -+struct _kc_ethtool_regs { -+ u32 cmd; -+ u32 version; /* driver-specific, indicates different chips/revs */ -+ u32 len; /* bytes */ -+ u8 data[0]; -+}; -+#endif /* ETHTOOL_GREGS */ -+ -+#ifndef ETHTOOL_GMSGLVL -+#define ETHTOOL_GMSGLVL 0x00000007 /* Get driver message level */ -+#endif -+#ifndef ETHTOOL_SMSGLVL -+#define ETHTOOL_SMSGLVL 0x00000008 /* Set driver msg level, priv. */ -+#endif -+#ifndef ETHTOOL_NWAY_RST -+#define ETHTOOL_NWAY_RST 0x00000009 /* Restart autonegotiation, priv */ -+#endif -+#ifndef ETHTOOL_GLINK -+#define ETHTOOL_GLINK 0x0000000a /* Get link status */ -+#endif -+#ifndef ETHTOOL_GEEPROM -+#define ETHTOOL_GEEPROM 0x0000000b /* Get EEPROM data */ -+#endif -+#ifndef ETHTOOL_SEEPROM -+#define ETHTOOL_SEEPROM 0x0000000c /* Set EEPROM data */ -+#endif -+#ifndef ETHTOOL_GCOALESCE -+#define ETHTOOL_GCOALESCE 0x0000000e /* Get coalesce config */ -+/* for configuring coalescing parameters of chip */ -+#define ethtool_coalesce _kc_ethtool_coalesce -+struct _kc_ethtool_coalesce { -+ u32 cmd; /* ETHTOOL_{G,S}COALESCE */ -+ -+ /* How many usecs to delay an RX interrupt after -+ * a packet arrives. If 0, only rx_max_coalesced_frames -+ * is used. -+ */ -+ u32 rx_coalesce_usecs; -+ -+ /* How many packets to delay an RX interrupt after -+ * a packet arrives. If 0, only rx_coalesce_usecs is -+ * used. It is illegal to set both usecs and max frames -+ * to zero as this would cause RX interrupts to never be -+ * generated. -+ */ -+ u32 rx_max_coalesced_frames; -+ -+ /* Same as above two parameters, except that these values -+ * apply while an IRQ is being serviced by the host. Not -+ * all cards support this feature and the values are ignored -+ * in that case. -+ */ -+ u32 rx_coalesce_usecs_irq; -+ u32 rx_max_coalesced_frames_irq; -+ -+ /* How many usecs to delay a TX interrupt after -+ * a packet is sent. If 0, only tx_max_coalesced_frames -+ * is used. -+ */ -+ u32 tx_coalesce_usecs; -+ -+ /* How many packets to delay a TX interrupt after -+ * a packet is sent. If 0, only tx_coalesce_usecs is -+ * used. It is illegal to set both usecs and max frames -+ * to zero as this would cause TX interrupts to never be -+ * generated. -+ */ -+ u32 tx_max_coalesced_frames; -+ -+ /* Same as above two parameters, except that these values -+ * apply while an IRQ is being serviced by the host. Not -+ * all cards support this feature and the values are ignored -+ * in that case. -+ */ -+ u32 tx_coalesce_usecs_irq; -+ u32 tx_max_coalesced_frames_irq; -+ -+ /* How many usecs to delay in-memory statistics -+ * block updates. Some drivers do not have an in-memory -+ * statistic block, and in such cases this value is ignored. -+ * This value must not be zero. -+ */ -+ u32 stats_block_coalesce_usecs; -+ -+ /* Adaptive RX/TX coalescing is an algorithm implemented by -+ * some drivers to improve latency under low packet rates and -+ * improve throughput under high packet rates. Some drivers -+ * only implement one of RX or TX adaptive coalescing. Anything -+ * not implemented by the driver causes these values to be -+ * silently ignored. -+ */ -+ u32 use_adaptive_rx_coalesce; -+ u32 use_adaptive_tx_coalesce; -+ -+ /* When the packet rate (measured in packets per second) -+ * is below pkt_rate_low, the {rx,tx}_*_low parameters are -+ * used. -+ */ -+ u32 pkt_rate_low; -+ u32 rx_coalesce_usecs_low; -+ u32 rx_max_coalesced_frames_low; -+ u32 tx_coalesce_usecs_low; -+ u32 tx_max_coalesced_frames_low; -+ -+ /* When the packet rate is below pkt_rate_high but above -+ * pkt_rate_low (both measured in packets per second) the -+ * normal {rx,tx}_* coalescing parameters are used. -+ */ -+ -+ /* When the packet rate is (measured in packets per second) -+ * is above pkt_rate_high, the {rx,tx}_*_high parameters are -+ * used. -+ */ -+ u32 pkt_rate_high; -+ u32 rx_coalesce_usecs_high; -+ u32 rx_max_coalesced_frames_high; -+ u32 tx_coalesce_usecs_high; -+ u32 tx_max_coalesced_frames_high; -+ -+ /* How often to do adaptive coalescing packet rate sampling, -+ * measured in seconds. Must not be zero. -+ */ -+ u32 rate_sample_interval; -+}; -+#endif /* ETHTOOL_GCOALESCE */ -+ -+#ifndef ETHTOOL_SCOALESCE -+#define ETHTOOL_SCOALESCE 0x0000000f /* Set coalesce config. */ -+#endif -+#ifndef ETHTOOL_GRINGPARAM -+#define ETHTOOL_GRINGPARAM 0x00000010 /* Get ring parameters */ -+/* for configuring RX/TX ring parameters */ -+#define ethtool_ringparam _kc_ethtool_ringparam -+struct _kc_ethtool_ringparam { -+ u32 cmd; /* ETHTOOL_{G,S}RINGPARAM */ -+ -+ /* Read only attributes. These indicate the maximum number -+ * of pending RX/TX ring entries the driver will allow the -+ * user to set. -+ */ -+ u32 rx_max_pending; -+ u32 rx_mini_max_pending; -+ u32 rx_jumbo_max_pending; -+ u32 tx_max_pending; -+ -+ /* Values changeable by the user. The valid values are -+ * in the range 1 to the "*_max_pending" counterpart above. -+ */ -+ u32 rx_pending; -+ u32 rx_mini_pending; -+ u32 rx_jumbo_pending; -+ u32 tx_pending; -+}; -+#endif /* ETHTOOL_GRINGPARAM */ -+ -+#ifndef ETHTOOL_SRINGPARAM -+#define ETHTOOL_SRINGPARAM 0x00000011 /* Set ring parameters, priv. */ -+#endif -+#ifndef ETHTOOL_GPAUSEPARAM -+#define ETHTOOL_GPAUSEPARAM 0x00000012 /* Get pause parameters */ -+/* for configuring link flow control parameters */ -+#define ethtool_pauseparam _kc_ethtool_pauseparam -+struct _kc_ethtool_pauseparam { -+ u32 cmd; /* ETHTOOL_{G,S}PAUSEPARAM */ -+ -+ /* If the link is being auto-negotiated (via ethtool_cmd.autoneg -+ * being true) the user may set 'autonet' here non-zero to have the -+ * pause parameters be auto-negotiated too. In such a case, the -+ * {rx,tx}_pause values below determine what capabilities are -+ * advertised. -+ * -+ * If 'autoneg' is zero or the link is not being auto-negotiated, -+ * then {rx,tx}_pause force the driver to use/not-use pause -+ * flow control. -+ */ -+ u32 autoneg; -+ u32 rx_pause; -+ u32 tx_pause; -+}; -+#endif /* ETHTOOL_GPAUSEPARAM */ -+ -+#ifndef ETHTOOL_SPAUSEPARAM -+#define ETHTOOL_SPAUSEPARAM 0x00000013 /* Set pause parameters. */ -+#endif -+#ifndef ETHTOOL_GRXCSUM -+#define ETHTOOL_GRXCSUM 0x00000014 /* Get RX hw csum enable (ethtool_value) */ -+#endif -+#ifndef ETHTOOL_SRXCSUM -+#define ETHTOOL_SRXCSUM 0x00000015 /* Set RX hw csum enable (ethtool_value) */ -+#endif -+#ifndef ETHTOOL_GTXCSUM -+#define ETHTOOL_GTXCSUM 0x00000016 /* Get TX hw csum enable (ethtool_value) */ -+#endif -+#ifndef ETHTOOL_STXCSUM -+#define ETHTOOL_STXCSUM 0x00000017 /* Set TX hw csum enable (ethtool_value) */ -+#endif -+#ifndef ETHTOOL_GSG -+#define ETHTOOL_GSG 0x00000018 /* Get scatter-gather enable -+ * (ethtool_value) */ -+#endif -+#ifndef ETHTOOL_SSG -+#define ETHTOOL_SSG 0x00000019 /* Set scatter-gather enable -+ * (ethtool_value). */ -+#endif -+#ifndef ETHTOOL_TEST -+#define ETHTOOL_TEST 0x0000001a /* execute NIC self-test, priv. */ -+#endif -+#ifndef ETHTOOL_GSTRINGS -+#define ETHTOOL_GSTRINGS 0x0000001b /* get specified string set */ -+#endif -+#ifndef ETHTOOL_PHYS_ID -+#define ETHTOOL_PHYS_ID 0x0000001c /* identify the NIC */ -+#endif -+#ifndef ETHTOOL_GSTATS -+#define ETHTOOL_GSTATS 0x0000001d /* get NIC-specific statistics */ -+#endif -+#ifndef ETHTOOL_GTSO -+#define ETHTOOL_GTSO 0x0000001e /* Get TSO enable (ethtool_value) */ -+#endif -+#ifndef ETHTOOL_STSO -+#define ETHTOOL_STSO 0x0000001f /* Set TSO enable (ethtool_value) */ -+#endif -+ -+#ifndef ETHTOOL_BUSINFO_LEN -+#define ETHTOOL_BUSINFO_LEN 32 -+#endif -+ -+/*****************************************************************************/ -+ -+enum RTL8168_DSM_STATE { -+ DSM_MAC_INIT = 1, -+ DSM_NIC_GOTO_D3 = 2, -+ DSM_IF_DOWN = 3, -+ DSM_NIC_RESUME_D3 = 4, -+ DSM_IF_UP = 5, -+}; -+ -+enum RTL8168_registers { -+ MAC0 = 0x00, /* Ethernet hardware address. */ -+ MAC4 = 0x04, -+ MAR0 = 0x08, /* Multicast filter. */ -+ CounterAddrLow = 0x10, -+ CounterAddrHigh = 0x14, -+ CustomLED = 0x18, -+ TxDescStartAddrLow = 0x20, -+ TxDescStartAddrHigh = 0x24, -+ TxHDescStartAddrLow = 0x28, -+ TxHDescStartAddrHigh = 0x2c, -+ FLASH = 0x30, -+ ERSR = 0x36, -+ ChipCmd = 0x37, -+ TxPoll = 0x38, -+ IntrMask = 0x3C, -+ IntrStatus = 0x3E, -+ TxConfig = 0x40, -+ RxConfig = 0x44, -+ TCTR = 0x48, -+ Cfg9346 = 0x50, -+ Config0 = 0x51, -+ Config1 = 0x52, -+ Config2 = 0x53, -+ Config3 = 0x54, -+ Config4 = 0x55, -+ Config5 = 0x56, -+ TDFNR = 0x57, -+ TimeIntr = 0x58, -+ PHYAR = 0x60, -+ CSIDR = 0x64, -+ CSIAR = 0x68, -+ PHYstatus = 0x6C, -+ MACDBG = 0x6D, -+ GPIO = 0x6E, -+ PMCH = 0x6F, -+ ERIDR = 0x70, -+ ERIAR = 0x74, -+ EPHY_RXER_NUM = 0x7C, -+ EPHYAR = 0x80, -+ OCPDR = 0xB0, -+ MACOCP = 0xB0, -+ OCPAR = 0xB4, -+ PHYOCP = 0xB8, -+ DBG_reg = 0xD1, -+ MCUCmd_reg = 0xD3, -+ RxMaxSize = 0xDA, -+ EFUSEAR = 0xDC, -+ CPlusCmd = 0xE0, -+ IntrMitigate = 0xE2, -+ RxDescAddrLow = 0xE4, -+ RxDescAddrHigh = 0xE8, -+ MTPS = 0xEC, -+ FuncEvent = 0xF0, -+ FuncEventMask = 0xF4, -+ FuncPresetState = 0xF8, -+ FuncForceEvent = 0xFC, -+}; -+ -+enum RTL8168_register_content { -+ /* InterruptStatusBits */ -+ SYSErr = 0x8000, -+ PCSTimeout = 0x4000, -+ SWInt = 0x0100, -+ TxDescUnavail = 0x0080, -+ RxFIFOOver = 0x0040, -+ LinkChg = 0x0020, -+ RxDescUnavail = 0x0010, -+ TxErr = 0x0008, -+ TxOK = 0x0004, -+ RxErr = 0x0002, -+ RxOK = 0x0001, -+ -+ /* RxStatusDesc */ -+ RxRWT = (1 << 22), -+ RxRES = (1 << 21), -+ RxRUNT = (1 << 20), -+ RxCRC = (1 << 19), -+ -+ /* ChipCmdBits */ -+ StopReq = 0x80, -+ CmdReset = 0x10, -+ CmdRxEnb = 0x08, -+ CmdTxEnb = 0x04, -+ RxBufEmpty = 0x01, -+ -+ /* Cfg9346Bits */ -+ Cfg9346_Lock = 0x00, -+ Cfg9346_Unlock = 0xC0, -+ Cfg9346_EEDO = (1 << 0), -+ Cfg9346_EEDI = (1 << 1), -+ Cfg9346_EESK = (1 << 2), -+ Cfg9346_EECS = (1 << 3), -+ Cfg9346_EEM0 = (1 << 6), -+ Cfg9346_EEM1 = (1 << 7), -+ -+ /* rx_mode_bits */ -+ AcceptErr = 0x20, -+ AcceptRunt = 0x10, -+ AcceptBroadcast = 0x08, -+ AcceptMulticast = 0x04, -+ AcceptMyPhys = 0x02, -+ AcceptAllPhys = 0x01, -+ -+ /* Transmit Priority Polling*/ -+ HPQ = 0x80, -+ NPQ = 0x40, -+ FSWInt = 0x01, -+ -+ /* RxConfigBits */ -+ Reserved2_shift = 13, -+ RxCfgDMAShift = 8, -+ RxCfg_128_int_en = (1 << 15), -+ RxCfg_fet_multi_en = (1 << 14), -+ RxCfg_half_refetch = (1 << 13), -+ RxCfg_9356SEL = (1 << 6), -+ -+ /* TxConfigBits */ -+ TxInterFrameGapShift = 24, -+ TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ -+ TxMACLoopBack = (1 << 17), /* MAC loopback */ -+ -+ /* Config1 register p.24 */ -+ LEDS1 = (1 << 7), -+ LEDS0 = (1 << 6), -+ Speed_down = (1 << 4), -+ MEMMAP = (1 << 3), -+ IOMAP = (1 << 2), -+ VPD = (1 << 1), -+ PMEnable = (1 << 0), /* Power Management Enable */ -+ -+ /* Config3 register */ -+ MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */ -+ LinkUp = (1 << 4), /* This bit is reserved in RTL8168B.*/ -+ /* Wake up when the cable connection is re-established */ -+ ECRCEN = (1 << 3), /* This bit is reserved in RTL8168B*/ -+ Jumbo_En0 = (1 << 2), /* This bit is reserved in RTL8168B*/ -+ RDY_TO_L23 = (1 << 1), /* This bit is reserved in RTL8168B*/ -+ Beacon_en = (1 << 0), /* This bit is reserved in RTL8168B*/ -+ -+ /* Config4 register */ -+ Jumbo_En1 = (1 << 1), /* This bit is reserved in RTL8168B*/ -+ -+ /* Config5 register */ -+ BWF = (1 << 6), /* Accept Broadcast wakeup frame */ -+ MWF = (1 << 5), /* Accept Multicast wakeup frame */ -+ UWF = (1 << 4), /* Accept Unicast wakeup frame */ -+ LanWake = (1 << 1), /* LanWake enable/disable */ -+ PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */ -+ -+ /* CPlusCmd */ -+ EnableBist = (1 << 15), -+ Macdbgo_oe = (1 << 14), -+ Normal_mode = (1 << 13), -+ Force_halfdup = (1 << 12), -+ Force_rxflow_en = (1 << 11), -+ Force_txflow_en = (1 << 10), -+ Cxpl_dbg_sel = (1 << 9),//This bit is reserved in RTL8168B -+ ASF = (1 << 8),//This bit is reserved in RTL8168C -+ PktCntrDisable = (1 << 7), -+ RxVlan = (1 << 6), -+ RxChkSum = (1 << 5), -+ Macdbgo_sel = 0x001C, -+ INTT_0 = 0x0000, -+ INTT_1 = 0x0001, -+ INTT_2 = 0x0002, -+ INTT_3 = 0x0003, -+ -+ /* rtl8168_PHYstatus */ -+ TxFlowCtrl = 0x40, -+ RxFlowCtrl = 0x20, -+ _1000bpsF = 0x10, -+ _100bps = 0x08, -+ _10bps = 0x04, -+ LinkStatus = 0x02, -+ FullDup = 0x01, -+ -+ /* DBG_reg */ -+ Fix_Nak_1 = (1 << 4), -+ Fix_Nak_2 = (1 << 3), -+ DBGPIN_E2 = (1 << 0), -+ -+ /* DumpCounterCommand */ -+ CounterDump = 0x8, -+ -+ /* PHY access */ -+ PHYAR_Flag = 0x80000000, -+ PHYAR_Write = 0x80000000, -+ PHYAR_Read = 0x00000000, -+ PHYAR_Reg_Mask = 0x1f, -+ PHYAR_Reg_shift = 16, -+ PHYAR_Data_Mask = 0xffff, -+ -+ /* EPHY access */ -+ EPHYAR_Flag = 0x80000000, -+ EPHYAR_Write = 0x80000000, -+ EPHYAR_Read = 0x00000000, -+ EPHYAR_Reg_Mask = 0x1f, -+ EPHYAR_Reg_shift = 16, -+ EPHYAR_Data_Mask = 0xffff, -+ -+ /* CSI access */ -+ CSIAR_Flag = 0x80000000, -+ CSIAR_Write = 0x80000000, -+ CSIAR_Read = 0x00000000, -+ CSIAR_ByteEn = 0x0f, -+ CSIAR_ByteEn_shift = 12, -+ CSIAR_Addr_Mask = 0x0fff, -+ -+ /* ERI access */ -+ ERIAR_Flag = 0x80000000, -+ ERIAR_Write = 0x80000000, -+ ERIAR_Read = 0x00000000, -+ ERIAR_Addr_Align = 4, /* ERI access register address must be 4 byte alignment */ -+ ERIAR_ExGMAC = 0, -+ ERIAR_MSIX = 1, -+ ERIAR_ASF = 2, -+ ERIAR_OOB = 2, -+ ERIAR_Type_shift = 16, -+ ERIAR_ByteEn = 0x0f, -+ ERIAR_ByteEn_shift = 12, -+ -+ /* OCP GPHY access */ -+ OCPDR_Write = 0x80000000, -+ OCPDR_Read = 0x00000000, -+ OCPDR_Reg_Mask = 0xFF, -+ OCPDR_Data_Mask = 0xFFFF, -+ OCPDR_GPHY_Reg_shift = 16, -+ OCPAR_Flag = 0x80000000, -+ OCPAR_GPHY_Write = 0x8000F060, -+ OCPAR_GPHY_Read = 0x0000F060, -+ OCPR_Write = 0x80000000, -+ OCPR_Read = 0x00000000, -+ OCPR_Addr_Reg_shift = 16, -+ OCPR_Flag = 0x80000000, -+ -+ /* MCU Command */ -+ Now_is_oob = (1 << 7), -+ Txfifo_empty = (1 << 5), -+ Rxfifo_empty = (1 << 4), -+ -+ /* E-FUSE access */ -+ EFUSE_WRITE = 0x80000000, -+ EFUSE_WRITE_OK = 0x00000000, -+ EFUSE_READ = 0x00000000, -+ EFUSE_READ_OK = 0x80000000, -+ EFUSE_Reg_Mask = 0x03FF, -+ EFUSE_Reg_Shift = 8, -+ EFUSE_Check_Cnt = 300, -+ EFUSE_READ_FAIL = 0xFF, -+ EFUSE_Data_Mask = 0x000000FF, -+ -+ /* GPIO */ -+ GPIO_en = (1 << 0), -+ -+}; -+ -+enum _DescStatusBit { -+ DescOwn = (1 << 31), /* Descriptor is owned by NIC */ -+ RingEnd = (1 << 30), /* End of descriptor ring */ -+ FirstFrag = (1 << 29), /* First segment of a packet */ -+ LastFrag = (1 << 28), /* Final segment of a packet */ -+ -+ /* Tx private */ -+ /*------ offset 0 of tx descriptor ------*/ -+ LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */ -+ MSSShift = 16, /* MSS value position */ -+ MSSMask = 0x7ffU, /* MSS value + LargeSend bit: 12 bits */ -+ TxIPCS = (1 << 18), /* Calculate IP checksum */ -+ TxUDPCS = (1 << 17), /* Calculate UDP/IP checksum */ -+ TxTCPCS = (1 << 16), /* Calculate TCP/IP checksum */ -+ TxVlanTag = (1 << 17), /* Add VLAN tag */ -+ -+ /*@@@@@@ offset 4 of tx descriptor => bits for RTL8168C/CP only begin @@@@@@*/ -+ TxUDPCS_C = (1 << 31), /* Calculate UDP/IP checksum */ -+ TxTCPCS_C = (1 << 30), /* Calculate TCP/IP checksum */ -+ TxIPCS_C = (1 << 29), /* Calculate IP checksum */ -+ /*@@@@@@ offset 4 of tx descriptor => bits for RTL8168C/CP only end @@@@@@*/ -+ -+ -+ /* Rx private */ -+ /*------ offset 0 of rx descriptor ------*/ -+ PID1 = (1 << 18), /* Protocol ID bit 1/2 */ -+ PID0 = (1 << 17), /* Protocol ID bit 2/2 */ -+ -+#define RxProtoUDP (PID1) -+#define RxProtoTCP (PID0) -+#define RxProtoIP (PID1 | PID0) -+#define RxProtoMask RxProtoIP -+ -+ RxIPF = (1 << 16), /* IP checksum failed */ -+ RxUDPF = (1 << 15), /* UDP/IP checksum failed */ -+ RxTCPF = (1 << 14), /* TCP/IP checksum failed */ -+ RxVlanTag = (1 << 16), /* VLAN tag available */ -+ -+ /*@@@@@@ offset 0 of rx descriptor => bits for RTL8168C/CP only begin @@@@@@*/ -+ RxUDPT = (1 << 18), -+ RxTCPT = (1 << 17), -+ /*@@@@@@ offset 0 of rx descriptor => bits for RTL8168C/CP only end @@@@@@*/ -+ -+ /*@@@@@@ offset 4 of rx descriptor => bits for RTL8168C/CP only begin @@@@@@*/ -+ RxV6F = (1 << 31), -+ RxV4F = (1 << 30), -+ /*@@@@@@ offset 4 of rx descriptor => bits for RTL8168C/CP only end @@@@@@*/ -+}; -+ -+enum features { -+// RTL_FEATURE_WOL = (1 << 0), -+ RTL_FEATURE_MSI = (1 << 1), -+}; -+ -+enum wol_capability { -+ WOL_DISABLED = 0, -+ WOL_ENABLED = 1 -+}; -+ -+enum bits { -+ BIT_0 = (1 << 0), -+ BIT_1 = (1 << 1), -+ BIT_2 = (1 << 2), -+ BIT_3 = (1 << 3), -+ BIT_4 = (1 << 4), -+ BIT_5 = (1 << 5), -+ BIT_6 = (1 << 6), -+ BIT_7 = (1 << 7), -+ BIT_8 = (1 << 8), -+ BIT_9 = (1 << 9), -+ BIT_10 = (1 << 10), -+ BIT_11 = (1 << 11), -+ BIT_12 = (1 << 12), -+ BIT_13 = (1 << 13), -+ BIT_14 = (1 << 14), -+ BIT_15 = (1 << 15), -+ BIT_16 = (1 << 16), -+ BIT_17 = (1 << 17), -+ BIT_18 = (1 << 18), -+ BIT_19 = (1 << 19), -+ BIT_20 = (1 << 20), -+ BIT_21 = (1 << 21), -+ BIT_22 = (1 << 22), -+ BIT_23 = (1 << 23), -+ BIT_24 = (1 << 24), -+ BIT_25 = (1 << 25), -+ BIT_26 = (1 << 26), -+ BIT_27 = (1 << 27), -+ BIT_28 = (1 << 28), -+ BIT_29 = (1 << 29), -+ BIT_30 = (1 << 30), -+ BIT_31 = (1 << 31) -+}; -+ -+enum effuse { -+ EFUSE_SUPPORT = 1, -+ EFUSE_NOT_SUPPORT = 0, -+}; -+#define RsvdMask 0x3fffc000 -+ -+struct TxDesc { -+ u32 opts1; -+ u32 opts2; -+ u64 addr; -+}; -+ -+struct RxDesc { -+ u32 opts1; -+ u32 opts2; -+ u64 addr; -+}; -+ -+struct ring_info { -+ struct sk_buff *skb; -+ u32 len; -+ u8 __pad[sizeof(void *) - sizeof(u32)]; -+}; -+ -+struct pci_resource { -+ u8 cmd; -+ u8 cls; -+ u16 io_base_h; -+ u16 io_base_l; -+ u16 mem_base_h; -+ u16 mem_base_l; -+ u8 ilr; -+ u16 resv_0x20_h; -+ u16 resv_0x20_l; -+ u16 resv_0x24_h; -+ u16 resv_0x24_l; -+}; -+ -+struct rtl8168_private { -+ void __iomem *mmio_addr; /* memory map physical address */ -+ struct pci_dev *pci_dev; /* Index of PCI device */ -+ struct net_device *dev; -+#ifdef CONFIG_R8168_NAPI -+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) -+ struct napi_struct napi; -+ #endif -+#endif -+ struct net_device_stats stats; /* statistics of net device */ -+ spinlock_t lock; /* spin lock flag */ -+ spinlock_t phy_lock; /* spin lock flag for GPHY */ -+ u32 msg_enable; -+ u32 tx_tcp_csum_cmd; -+ u32 tx_udp_csum_cmd; -+ u32 tx_ip_csum_cmd; -+ int max_jumbo_frame_size; -+ int chipset; -+ u32 mcfg; -+ u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ -+ u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ -+ u32 dirty_rx; -+ u32 dirty_tx; -+ struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */ -+ struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ -+ dma_addr_t TxPhyAddr; -+ dma_addr_t RxPhyAddr; -+ struct sk_buff *Rx_skbuff[NUM_RX_DESC]; /* Rx data buffers */ -+ struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */ -+ unsigned rx_buf_sz; -+ int rx_fifo_overflow; -+ struct timer_list esd_timer; -+ struct timer_list link_timer; -+ int old_link_status; -+ struct pci_resource pci_cfg_space; -+ unsigned int esd_flag; -+ unsigned int pci_cfg_is_read; -+ unsigned int rtl8168_rx_config; -+ u16 cp_cmd; -+ u16 intr_mask; -+ int phy_auto_nego_reg; -+ int phy_1000_ctrl_reg; -+ u8 org_mac_addr[NODE_ADDRESS_SIZE]; -+#ifdef CONFIG_R8168_VLAN -+ struct vlan_group *vlgrp; -+#endif -+ u8 wol_enabled; -+ u8 efuse; -+ u8 eeprom_type; -+ u8 autoneg; -+ u8 duplex; -+ u16 speed; -+ u16 eeprom_len; -+ u16 cur_page; -+ -+ int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex); -+ void (*get_settings)(struct net_device *, struct ethtool_cmd *); -+ void (*phy_reset_enable)(struct net_device *); -+ unsigned int (*phy_reset_pending)(struct net_device *); -+ unsigned int (*link_ok)(struct net_device *); -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -+ struct work_struct task; -+#else -+ struct delayed_work task; -+#endif -+ unsigned features; -+}; -+ -+enum eetype { -+ EEPROM_TYPE_NONE=0, -+ EEPROM_TYPE_93C46, -+ EEPROM_TYPE_93C56, -+ EEPROM_TWSI -+}; -+ -+enum mcfg { -+ CFG_METHOD_1=0, -+ CFG_METHOD_2, -+ CFG_METHOD_3, -+ CFG_METHOD_4, -+ CFG_METHOD_5, -+ CFG_METHOD_6, -+ CFG_METHOD_7, -+ CFG_METHOD_8, -+ CFG_METHOD_9 , -+ CFG_METHOD_10, -+ CFG_METHOD_11, -+ CFG_METHOD_12, -+ CFG_METHOD_13, -+ CFG_METHOD_14, -+ CFG_METHOD_15, -+ CFG_METHOD_16, -+ CFG_METHOD_17, -+ CFG_METHOD_18, -+ CFG_METHOD_19, -+ CFG_METHOD_20, -+ CFG_METHOD_21, -+ CFG_METHOD_22, -+ CFG_METHOD_23, -+ CFG_METHOD_MAX, -+ CFG_METHOD_DEFAULT = 0xFF -+}; -+ -+#define OOB_CMD_RESET 0x00 -+#define OOB_CMD_DRIVER_START 0x05 -+#define OOB_CMD_DRIVER_STOP 0x06 -+#define OOB_CMD_SET_IPMAC 0x41 -+ -+void mdio_write(struct rtl8168_private *tp, u32 RegAddr, u32 value); -+void rtl8168_ephy_write(void __iomem *ioaddr, int RegAddr, int value); -+void OCP_write(struct rtl8168_private *tp, u8 mask, u16 Reg, u32 data); -+void OOB_notify(struct rtl8168_private *tp, u8 cmd); -+void rtl8168_init_ring_indexes(struct rtl8168_private *tp); -+int rtl8168_eri_write(void __iomem *ioaddr, int addr, int len, u32 value, int type); -+void OOB_mutex_lock(struct rtl8168_private *tp); -+u32 mdio_read(struct rtl8168_private *tp, u32 RegAddr); -+u32 OCP_read(struct rtl8168_private *tp, u8 mask, u16 Reg); -+u32 rtl8168_eri_read(void __iomem *ioaddr, int addr, int len, int type); -+u16 rtl8168_ephy_read(void __iomem *ioaddr, int RegAddr); -+void OOB_mutex_unlock(struct rtl8168_private *tp); -+ -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34) -+#define netdev_mc_count(dev) ((dev)->mc_count) -+#define netdev_mc_empty(dev) (netdev_mc_count(dev) == 0) -+#define netdev_for_each_mc_addr(mclist, dev) \ -+ for (mclist = dev->mc_list; mclist; mclist = mclist->next) -+#endif -diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realtek/r8168_n.c ---- a/drivers/net/ethernet/realtek/r8168_n.c 1970-01-01 03:00:00.000000000 +0300 -+++ b/drivers/net/ethernet/realtek/r8168_n.c 2012-10-25 11:47:41.007862919 +0300 -@@ -0,0 +1,17463 @@ +diff -Naur linux-3.4.19-old/drivers/net/ethernet/realtek/r8168/r8168.h linux-3.4.19-new/drivers/net/ethernet/realtek/r8168/r8168.h +--- linux-3.4.19-old/drivers/net/ethernet/realtek/r8168/r8168.h 1969-12-31 16:00:00.000000000 -0800 ++++ linux-3.4.19-new/drivers/net/ethernet/realtek/r8168/r8168.h 2012-10-24 23:43:18.000000000 -0700 +@@ -0,0 +1,1299 @@ ++/* ++################################################################################ ++# ++# r8168 is the Linux device driver released for RealTek RTL8168B/8111B, ++# RTL8168C/8111C, RTL8168CP/8111CP, RTL8168D/8111D, and RTL8168DP/8111DP, and ++# RTK8168E/8111E Gigabit Ethernet controllers with PCI-Express interface. ++# ++# Copyright(c) 2012 Realtek Semiconductor Corp. All rights reserved. ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms of the GNU General Public License as published by the Free ++# Software Foundation; either version 2 of the License, or (at your option) ++# any later version. ++# ++# This program is distributed in the hope that it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++# more details. ++# ++# You should have received a copy of the GNU General Public License along with ++# this program; if not, see . ++# ++# Author: ++# Realtek NIC software team ++# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan ++# ++################################################################################ ++*/ ++ ++/* ++ * This product is covered by one or more of the following patents: ++ * US5,307,459, US5,434,872, US5,732,094, US6,570,884, US6,115,776, and US6,327,625. ++ */ ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) ++#define CHECKSUM_PARTIAL CHECKSUM_HW ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) ++ #define irqreturn_t void ++ #define IRQ_HANDLED 1 ++ #define IRQ_NONE 0 ++ #define IRQ_RETVAL(x) ++#endif ++ ++#ifndef HAVE_FREE_NETDEV ++#define free_netdev(x) kfree(x) ++#endif ++ ++#ifndef SET_NETDEV_DEV ++#define SET_NETDEV_DEV(net, pdev) ++#endif ++ ++#ifndef SET_MODULE_OWNER ++#define SET_MODULE_OWNER(dev) ++#endif ++ ++#ifndef SA_SHIRQ ++#define SA_SHIRQ IRQF_SHARED ++#endif ++ ++#ifndef NETIF_F_GSO ++#define gso_size tso_size ++#define gso_segs tso_segs ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) ++ #ifdef CONFIG_NET_POLL_CONTROLLER ++ #define RTL_NET_POLL_CONTROLLER dev->poll_controller=rtl8168_netpoll ++ #else ++ #define RTL_NET_POLL_CONTROLLER ++ #endif ++ ++ #ifdef CONFIG_R8168_VLAN ++ #define RTL_SET_VLAN dev->vlan_rx_register=rtl8168_vlan_rx_register ++ #else ++ #define RTL_SET_VLAN ++ #endif ++ ++ #define RTL_NET_DEVICE_OPS(ops) dev->open=rtl8168_open; \ ++ dev->hard_start_xmit=rtl8168_start_xmit; \ ++ dev->get_stats=rtl8168_get_stats; \ ++ dev->stop=rtl8168_close; \ ++ dev->tx_timeout=rtl8168_tx_timeout; \ ++ dev->set_multicast_list=rtl8168_set_rx_mode; \ ++ dev->change_mtu=rtl8168_change_mtu; \ ++ dev->set_mac_address=rtl8168_set_mac_address; \ ++ dev->do_ioctl=rtl8168_do_ioctl; \ ++ RTL_NET_POLL_CONTROLLER; \ ++ RTL_SET_VLAN; ++#else ++ #define RTL_NET_DEVICE_OPS(ops) dev->netdev_ops=&ops ++#endif ++ ++//Due to the hardware design of RTL8111B, the low 32 bit address of receive ++//buffer must be 8-byte alignment. ++#ifndef NET_IP_ALIGN ++#define NET_IP_ALIGN 2 ++#endif ++#define RTK_RX_ALIGN 8 ++ ++#ifdef CONFIG_R8168_NAPI ++#define NAPI_SUFFIX "-NAPI" ++#else ++#define NAPI_SUFFIX "" ++#endif ++ ++#define RTL8168_VERSION "8.034.00" NAPI_SUFFIX ++#define MODULENAME "r8168" ++#define PFX MODULENAME ": " ++ ++#define GPL_CLAIM "\ ++r8168 Copyright (C) 2012 Realtek NIC software team \n \ ++This program comes with ABSOLUTELY NO WARRANTY; for details, please see . \n \ ++This is free software, and you are welcome to redistribute it under certain conditions; see . \n" ++ ++#ifdef RTL8168_DEBUG ++#define assert(expr) \ ++ if(!(expr)) { \ ++ printk( "Assertion failed! %s,%s,%s,line=%d\n", \ ++ #expr,__FILE__,__FUNCTION__,__LINE__); \ ++ } ++#define dprintk(fmt, args...) do { printk(PFX fmt, ## args); } while (0) ++#else ++#define assert(expr) do {} while (0) ++#define dprintk(fmt, args...) do {} while (0) ++#endif /* RTL8168_DEBUG */ ++ ++#define R8168_MSG_DEFAULT \ ++ (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN) ++ ++#define TX_BUFFS_AVAIL(tp) \ ++ (tp->dirty_tx + NUM_TX_DESC - tp->cur_tx - 1) ++ ++#ifdef CONFIG_R8168_NAPI ++#define rtl8168_rx_skb netif_receive_skb ++#define rtl8168_rx_hwaccel_skb vlan_hwaccel_receive_skb ++#define rtl8168_rx_quota(count, quota) min(count, quota) ++#else ++#define rtl8168_rx_skb netif_rx ++#define rtl8168_rx_hwaccel_skb vlan_hwaccel_rx ++#define rtl8168_rx_quota(count, quota) count ++#endif ++ ++/* MAC address length */ ++#ifndef MAC_ADDR_LEN ++#define MAC_ADDR_LEN 6 ++#endif ++ ++#ifndef MAC_PROTOCOL_LEN ++#define MAC_PROTOCOL_LEN 2 ++#endif ++ ++#define Reserved2_data 7 ++#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ ++#define TX_DMA_BURST_unlimited 7 ++#define TX_DMA_BURST_1024 6 ++#define TX_DMA_BURST_512 5 ++#define TX_DMA_BURST_256 4 ++#define TX_DMA_BURST_128 3 ++#define TX_DMA_BURST_64 2 ++#define TX_DMA_BURST_32 1 ++#define TX_DMA_BURST_16 0 ++#define Reserved1_data 0x3F ++#define RxPacketMaxSize 0x3FE8 /* 16K - 1 - ETH_HLEN - VLAN - CRC... */ ++#define Jumbo_Frame_2k (2 * 1024) ++#define Jumbo_Frame_3k (3 * 1024) ++#define Jumbo_Frame_4k (4 * 1024) ++#define Jumbo_Frame_5k (5 * 1024) ++#define Jumbo_Frame_6k (6 * 1024) ++#define Jumbo_Frame_7k (7 * 1024) ++#define Jumbo_Frame_8k (8 * 1024) ++#define Jumbo_Frame_9k (9 * 1024) ++#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ ++#define RxEarly_off (1 << 11) ++ ++#define R8168_REGS_SIZE 256 ++#define R8168_NAPI_WEIGHT 64 ++ ++#define RX_BUF_SIZE 0x05F3 /* 0x05F3 = 1522bye + 1 */ ++#define R8168_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc)) ++#define R8168_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc)) ++ ++#define RTL8168_TX_TIMEOUT (6 * HZ) ++#define RTL8168_LINK_TIMEOUT (1 * HZ) ++#define RTL8168_ESD_TIMEOUT (2 * HZ) ++ ++#define NUM_TX_DESC 1024 /* Number of Tx descriptor registers */ ++#define NUM_RX_DESC 1024 /* Number of Rx descriptor registers */ ++ ++#define NODE_ADDRESS_SIZE 6 ++ ++/* write/read MMIO register */ ++#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) ++#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg)) ++#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg)) ++#define RTL_R8(reg) readb (ioaddr + (reg)) ++#define RTL_R16(reg) readw (ioaddr + (reg)) ++#define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg))) ++ ++#ifndef DMA_64BIT_MASK ++#define DMA_64BIT_MASK 0xffffffffffffffffULL ++#endif ++ ++#ifndef DMA_32BIT_MASK ++#define DMA_32BIT_MASK 0x00000000ffffffffULL ++#endif ++ ++#ifndef NETDEV_TX_OK ++#define NETDEV_TX_OK 0 /* driver took care of packet */ ++#endif ++ ++#ifndef NETDEV_TX_BUSY ++#define NETDEV_TX_BUSY 1 /* driver tx path was busy*/ ++#endif ++ ++#ifndef NETDEV_TX_LOCKED ++#define NETDEV_TX_LOCKED -1 /* driver tx lock was already taken */ ++#endif ++ ++#ifndef ADVERTISED_Pause ++#define ADVERTISED_Pause (1 << 13) ++#endif ++ ++#ifndef ADVERTISED_Asym_Pause ++#define ADVERTISED_Asym_Pause (1 << 14) ++#endif ++ ++#ifndef ADVERTISE_PAUSE_CAP ++#define ADVERTISE_PAUSE_CAP 0x400 ++#endif ++ ++#ifndef ADVERTISE_PAUSE_ASYM ++#define ADVERTISE_PAUSE_ASYM 0x800 ++#endif ++ ++#ifndef MII_CTRL1000 ++#define MII_CTRL1000 0x09 ++#endif ++ ++#ifndef ADVERTISE_1000FULL ++#define ADVERTISE_1000FULL 0x200 ++#endif ++ ++#ifndef ADVERTISE_1000HALF ++#define ADVERTISE_1000HALF 0x100 ++#endif ++ ++/*****************************************************************************/ ++ ++//#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3) ++#if (( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,27) ) || \ ++ (( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) ) && \ ++ ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3) ))) ++/* copied from linux kernel 2.6.20 include/linux/netdev.h */ ++#define NETDEV_ALIGN 32 ++#define NETDEV_ALIGN_CONST (NETDEV_ALIGN - 1) ++ ++static inline void *netdev_priv(struct net_device *dev) ++{ ++ return (char *)dev + ((sizeof(struct net_device) ++ + NETDEV_ALIGN_CONST) ++ & ~NETDEV_ALIGN_CONST); ++} ++#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3) ++ ++/*****************************************************************************/ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) ++ #define RTLDEV tp ++#else ++ #define RTLDEV dev ++#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) ++/*****************************************************************************/ ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) ++ typedef struct net_device *napi_ptr; ++ typedef int *napi_budget; ++ ++ #define napi dev ++ #define RTL_NAPI_CONFIG(ndev, priv, function, weig) ndev->poll=function; \ ++ ndev->weight=weig; ++ #define RTL_NAPI_QUOTA(budget, ndev) min(*budget, ndev->quota) ++ #define RTL_GET_PRIV(stuct_ptr, priv_struct) netdev_priv(stuct_ptr) ++ #define RTL_GET_NETDEV(priv_ptr) ++ #define RTL_RX_QUOTA(ndev, budget) ndev->quota ++ #define RTL_NAPI_QUOTA_UPDATE(ndev, work_done, budget) *budget -= work_done; \ ++ ndev->quota -= work_done; ++ #define RTL_NETIF_RX_COMPLETE(dev, napi) netif_rx_complete(dev) ++ #define RTL_NETIF_RX_SCHEDULE_PREP(dev, napi) netif_rx_schedule_prep(dev) ++ #define __RTL_NETIF_RX_SCHEDULE(dev, napi) __netif_rx_schedule(dev) ++ #define RTL_NAPI_RETURN_VALUE work_done >= work_to_do ++ #define RTL_NAPI_ENABLE(dev, napi) netif_poll_enable(dev) ++ #define RTL_NAPI_DISABLE(dev, napi) netif_poll_disable(dev) ++ #define DMA_BIT_MASK(value) ((1ULL << value) - 1) ++#else ++ typedef struct napi_struct *napi_ptr; ++ typedef int napi_budget; ++ ++ #define RTL_NAPI_CONFIG(ndev, priv, function, weight) netif_napi_add(ndev, &priv->napi, function, weight) ++ #define RTL_NAPI_QUOTA(budget, ndev) min(budget, budget) ++ #define RTL_GET_PRIV(stuct_ptr, priv_struct) container_of(stuct_ptr, priv_struct, stuct_ptr) ++ #define RTL_GET_NETDEV(priv_ptr) struct net_device *dev = priv_ptr->dev; ++ #define RTL_RX_QUOTA(ndev, budget) budget ++ #define RTL_NAPI_QUOTA_UPDATE(ndev, work_done, budget) ++ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) ++ #define RTL_NETIF_RX_COMPLETE(dev, napi) netif_rx_complete(dev, napi) ++ #define RTL_NETIF_RX_SCHEDULE_PREP(dev, napi) netif_rx_schedule_prep(dev, napi) ++ #define __RTL_NETIF_RX_SCHEDULE(dev, napi) __netif_rx_schedule(dev, napi) ++ #endif ++ #if LINUX_VERSION_CODE == KERNEL_VERSION(2,6,29) ++ #define RTL_NETIF_RX_COMPLETE(dev, napi) netif_rx_complete(napi) ++ #define RTL_NETIF_RX_SCHEDULE_PREP(dev, napi) netif_rx_schedule_prep(napi) ++ #define __RTL_NETIF_RX_SCHEDULE(dev, napi) __netif_rx_schedule(napi) ++ #endif ++ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) ++ #define RTL_NETIF_RX_COMPLETE(dev, napi) napi_complete(napi) ++ #define RTL_NETIF_RX_SCHEDULE_PREP(dev, napi) napi_schedule_prep(napi) ++ #define __RTL_NETIF_RX_SCHEDULE(dev, napi) __napi_schedule(napi) ++ #endif ++ #define RTL_NAPI_RETURN_VALUE work_done ++ #define RTL_NAPI_ENABLE(dev, napi) napi_enable(napi) ++ #define RTL_NAPI_DISABLE(dev, napi) napi_disable(napi) ++#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) ++ ++/*****************************************************************************/ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) ++#ifdef __CHECKER__ ++#define __iomem __attribute__((noderef, address_space(2))) ++extern void __chk_io_ptr(void __iomem *); ++#define __bitwise __attribute__((bitwise)) ++#else ++#define __iomem ++#define __chk_io_ptr(x) (void)0 ++#define __bitwise ++#endif ++#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) ++ ++/*****************************************************************************/ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) ++#ifdef __CHECKER__ ++#define __force __attribute__((force)) ++#else ++#define __force ++#endif ++#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) ++ ++#ifndef module_param ++#define module_param(v,t,p) MODULE_PARM(v, "i"); ++#endif ++ ++#ifndef PCI_DEVICE ++#define PCI_DEVICE(vend,dev) \ ++ .vendor = (vend), .device = (dev), \ ++ .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID ++#endif ++ ++/*****************************************************************************/ ++/* 2.5.28 => 2.4.23 */ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,5,28) ) ++ ++static inline void _kc_synchronize_irq(void) ++{ ++ synchronize_irq(); ++} ++#undef synchronize_irq ++#define synchronize_irq(X) _kc_synchronize_irq() ++ ++#include ++#define work_struct tq_struct ++#undef INIT_WORK ++#define INIT_WORK(a,b,c) INIT_TQUEUE(a,(void (*)(void *))b,c) ++#undef container_of ++#define container_of list_entry ++#define schedule_work schedule_task ++#define flush_scheduled_work flush_scheduled_tasks ++#endif /* 2.5.28 => 2.4.17 */ ++ ++/*****************************************************************************/ ++/* 2.6.4 => 2.6.0 */ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,4) ) ++#define MODULE_VERSION(_version) MODULE_INFO(version, _version) ++#endif /* 2.6.4 => 2.6.0 */ ++/*****************************************************************************/ ++/* 2.6.0 => 2.5.28 */ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) ) ++#define MODULE_INFO(version, _version) ++#ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT ++#define CONFIG_E1000_DISABLE_PACKET_SPLIT 1 ++#endif ++ ++#define pci_set_consistent_dma_mask(dev,mask) 1 ++ ++#undef dev_put ++#define dev_put(dev) __dev_put(dev) ++ ++#ifndef skb_fill_page_desc ++#define skb_fill_page_desc _kc_skb_fill_page_desc ++extern void _kc_skb_fill_page_desc(struct sk_buff *skb, int i, struct page *page, int off, int size); ++#endif ++ ++#ifndef pci_dma_mapping_error ++#define pci_dma_mapping_error _kc_pci_dma_mapping_error ++static inline int _kc_pci_dma_mapping_error(dma_addr_t dma_addr) ++{ ++ return dma_addr == 0; ++} ++#endif ++ ++#undef ALIGN ++#define ALIGN(x,a) (((x)+(a)-1)&~((a)-1)) ++ ++#endif /* 2.6.0 => 2.5.28 */ ++ ++/*****************************************************************************/ ++/* 2.4.22 => 2.4.17 */ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,22) ) ++#define pci_name(x) ((x)->slot_name) ++#endif /* 2.4.22 => 2.4.17 */ ++ ++/*****************************************************************************/ ++/* 2.6.5 => 2.6.0 */ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5) ) ++#define pci_dma_sync_single_for_cpu pci_dma_sync_single ++#define pci_dma_sync_single_for_device pci_dma_sync_single_for_cpu ++#endif /* 2.6.5 => 2.6.0 */ ++ ++/*****************************************************************************/ ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) ++/* ++ * initialize a work-struct's func and data pointers: ++ */ ++#define PREPARE_WORK(_work, _func, _data) \ ++ do { \ ++ (_work)->func = _func; \ ++ (_work)->data = _data; \ ++ } while (0) ++ ++#endif ++/*****************************************************************************/ ++/* 2.6.4 => 2.6.0 */ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,25) || \ ++ ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) && \ ++ LINUX_VERSION_CODE < KERNEL_VERSION(2,6,4) ) ) ++#define ETHTOOL_OPS_COMPAT ++#endif /* 2.6.4 => 2.6.0 */ ++ ++/*****************************************************************************/ ++/* Installations with ethtool version without eeprom, adapter id, or statistics ++ * support */ ++ ++#ifndef ETH_GSTRING_LEN ++#define ETH_GSTRING_LEN 32 ++#endif ++ ++#ifndef ETHTOOL_GSTATS ++#define ETHTOOL_GSTATS 0x1d ++#undef ethtool_drvinfo ++#define ethtool_drvinfo k_ethtool_drvinfo ++struct k_ethtool_drvinfo { ++ u32 cmd; ++ char driver[32]; ++ char version[32]; ++ char fw_version[32]; ++ char bus_info[32]; ++ char reserved1[32]; ++ char reserved2[16]; ++ u32 n_stats; ++ u32 testinfo_len; ++ u32 eedump_len; ++ u32 regdump_len; ++}; ++ ++struct ethtool_stats { ++ u32 cmd; ++ u32 n_stats; ++ u64 data[0]; ++}; ++#endif /* ETHTOOL_GSTATS */ ++ ++#ifndef ETHTOOL_PHYS_ID ++#define ETHTOOL_PHYS_ID 0x1c ++#endif /* ETHTOOL_PHYS_ID */ ++ ++#ifndef ETHTOOL_GSTRINGS ++#define ETHTOOL_GSTRINGS 0x1b ++enum ethtool_stringset { ++ ETH_SS_TEST = 0, ++ ETH_SS_STATS, ++}; ++struct ethtool_gstrings { ++ u32 cmd; /* ETHTOOL_GSTRINGS */ ++ u32 string_set; /* string set id e.c. ETH_SS_TEST, etc*/ ++ u32 len; /* number of strings in the string set */ ++ u8 data[0]; ++}; ++#endif /* ETHTOOL_GSTRINGS */ ++ ++#ifndef ETHTOOL_TEST ++#define ETHTOOL_TEST 0x1a ++enum ethtool_test_flags { ++ ETH_TEST_FL_OFFLINE = (1 << 0), ++ ETH_TEST_FL_FAILED = (1 << 1), ++}; ++struct ethtool_test { ++ u32 cmd; ++ u32 flags; ++ u32 reserved; ++ u32 len; ++ u64 data[0]; ++}; ++#endif /* ETHTOOL_TEST */ ++ ++#ifndef ETHTOOL_GEEPROM ++#define ETHTOOL_GEEPROM 0xb ++#undef ETHTOOL_GREGS ++struct ethtool_eeprom { ++ u32 cmd; ++ u32 magic; ++ u32 offset; ++ u32 len; ++ u8 data[0]; ++}; ++ ++struct ethtool_value { ++ u32 cmd; ++ u32 data; ++}; ++#endif /* ETHTOOL_GEEPROM */ ++ ++#ifndef ETHTOOL_GLINK ++#define ETHTOOL_GLINK 0xa ++#endif /* ETHTOOL_GLINK */ ++ ++#ifndef ETHTOOL_GREGS ++#define ETHTOOL_GREGS 0x00000004 /* Get NIC registers */ ++#define ethtool_regs _kc_ethtool_regs ++/* for passing big chunks of data */ ++struct _kc_ethtool_regs { ++ u32 cmd; ++ u32 version; /* driver-specific, indicates different chips/revs */ ++ u32 len; /* bytes */ ++ u8 data[0]; ++}; ++#endif /* ETHTOOL_GREGS */ ++ ++#ifndef ETHTOOL_GMSGLVL ++#define ETHTOOL_GMSGLVL 0x00000007 /* Get driver message level */ ++#endif ++#ifndef ETHTOOL_SMSGLVL ++#define ETHTOOL_SMSGLVL 0x00000008 /* Set driver msg level, priv. */ ++#endif ++#ifndef ETHTOOL_NWAY_RST ++#define ETHTOOL_NWAY_RST 0x00000009 /* Restart autonegotiation, priv */ ++#endif ++#ifndef ETHTOOL_GLINK ++#define ETHTOOL_GLINK 0x0000000a /* Get link status */ ++#endif ++#ifndef ETHTOOL_GEEPROM ++#define ETHTOOL_GEEPROM 0x0000000b /* Get EEPROM data */ ++#endif ++#ifndef ETHTOOL_SEEPROM ++#define ETHTOOL_SEEPROM 0x0000000c /* Set EEPROM data */ ++#endif ++#ifndef ETHTOOL_GCOALESCE ++#define ETHTOOL_GCOALESCE 0x0000000e /* Get coalesce config */ ++/* for configuring coalescing parameters of chip */ ++#define ethtool_coalesce _kc_ethtool_coalesce ++struct _kc_ethtool_coalesce { ++ u32 cmd; /* ETHTOOL_{G,S}COALESCE */ ++ ++ /* How many usecs to delay an RX interrupt after ++ * a packet arrives. If 0, only rx_max_coalesced_frames ++ * is used. ++ */ ++ u32 rx_coalesce_usecs; ++ ++ /* How many packets to delay an RX interrupt after ++ * a packet arrives. If 0, only rx_coalesce_usecs is ++ * used. It is illegal to set both usecs and max frames ++ * to zero as this would cause RX interrupts to never be ++ * generated. ++ */ ++ u32 rx_max_coalesced_frames; ++ ++ /* Same as above two parameters, except that these values ++ * apply while an IRQ is being serviced by the host. Not ++ * all cards support this feature and the values are ignored ++ * in that case. ++ */ ++ u32 rx_coalesce_usecs_irq; ++ u32 rx_max_coalesced_frames_irq; ++ ++ /* How many usecs to delay a TX interrupt after ++ * a packet is sent. If 0, only tx_max_coalesced_frames ++ * is used. ++ */ ++ u32 tx_coalesce_usecs; ++ ++ /* How many packets to delay a TX interrupt after ++ * a packet is sent. If 0, only tx_coalesce_usecs is ++ * used. It is illegal to set both usecs and max frames ++ * to zero as this would cause TX interrupts to never be ++ * generated. ++ */ ++ u32 tx_max_coalesced_frames; ++ ++ /* Same as above two parameters, except that these values ++ * apply while an IRQ is being serviced by the host. Not ++ * all cards support this feature and the values are ignored ++ * in that case. ++ */ ++ u32 tx_coalesce_usecs_irq; ++ u32 tx_max_coalesced_frames_irq; ++ ++ /* How many usecs to delay in-memory statistics ++ * block updates. Some drivers do not have an in-memory ++ * statistic block, and in such cases this value is ignored. ++ * This value must not be zero. ++ */ ++ u32 stats_block_coalesce_usecs; ++ ++ /* Adaptive RX/TX coalescing is an algorithm implemented by ++ * some drivers to improve latency under low packet rates and ++ * improve throughput under high packet rates. Some drivers ++ * only implement one of RX or TX adaptive coalescing. Anything ++ * not implemented by the driver causes these values to be ++ * silently ignored. ++ */ ++ u32 use_adaptive_rx_coalesce; ++ u32 use_adaptive_tx_coalesce; ++ ++ /* When the packet rate (measured in packets per second) ++ * is below pkt_rate_low, the {rx,tx}_*_low parameters are ++ * used. ++ */ ++ u32 pkt_rate_low; ++ u32 rx_coalesce_usecs_low; ++ u32 rx_max_coalesced_frames_low; ++ u32 tx_coalesce_usecs_low; ++ u32 tx_max_coalesced_frames_low; ++ ++ /* When the packet rate is below pkt_rate_high but above ++ * pkt_rate_low (both measured in packets per second) the ++ * normal {rx,tx}_* coalescing parameters are used. ++ */ ++ ++ /* When the packet rate is (measured in packets per second) ++ * is above pkt_rate_high, the {rx,tx}_*_high parameters are ++ * used. ++ */ ++ u32 pkt_rate_high; ++ u32 rx_coalesce_usecs_high; ++ u32 rx_max_coalesced_frames_high; ++ u32 tx_coalesce_usecs_high; ++ u32 tx_max_coalesced_frames_high; ++ ++ /* How often to do adaptive coalescing packet rate sampling, ++ * measured in seconds. Must not be zero. ++ */ ++ u32 rate_sample_interval; ++}; ++#endif /* ETHTOOL_GCOALESCE */ ++ ++#ifndef ETHTOOL_SCOALESCE ++#define ETHTOOL_SCOALESCE 0x0000000f /* Set coalesce config. */ ++#endif ++#ifndef ETHTOOL_GRINGPARAM ++#define ETHTOOL_GRINGPARAM 0x00000010 /* Get ring parameters */ ++/* for configuring RX/TX ring parameters */ ++#define ethtool_ringparam _kc_ethtool_ringparam ++struct _kc_ethtool_ringparam { ++ u32 cmd; /* ETHTOOL_{G,S}RINGPARAM */ ++ ++ /* Read only attributes. These indicate the maximum number ++ * of pending RX/TX ring entries the driver will allow the ++ * user to set. ++ */ ++ u32 rx_max_pending; ++ u32 rx_mini_max_pending; ++ u32 rx_jumbo_max_pending; ++ u32 tx_max_pending; ++ ++ /* Values changeable by the user. The valid values are ++ * in the range 1 to the "*_max_pending" counterpart above. ++ */ ++ u32 rx_pending; ++ u32 rx_mini_pending; ++ u32 rx_jumbo_pending; ++ u32 tx_pending; ++}; ++#endif /* ETHTOOL_GRINGPARAM */ ++ ++#ifndef ETHTOOL_SRINGPARAM ++#define ETHTOOL_SRINGPARAM 0x00000011 /* Set ring parameters, priv. */ ++#endif ++#ifndef ETHTOOL_GPAUSEPARAM ++#define ETHTOOL_GPAUSEPARAM 0x00000012 /* Get pause parameters */ ++/* for configuring link flow control parameters */ ++#define ethtool_pauseparam _kc_ethtool_pauseparam ++struct _kc_ethtool_pauseparam { ++ u32 cmd; /* ETHTOOL_{G,S}PAUSEPARAM */ ++ ++ /* If the link is being auto-negotiated (via ethtool_cmd.autoneg ++ * being true) the user may set 'autonet' here non-zero to have the ++ * pause parameters be auto-negotiated too. In such a case, the ++ * {rx,tx}_pause values below determine what capabilities are ++ * advertised. ++ * ++ * If 'autoneg' is zero or the link is not being auto-negotiated, ++ * then {rx,tx}_pause force the driver to use/not-use pause ++ * flow control. ++ */ ++ u32 autoneg; ++ u32 rx_pause; ++ u32 tx_pause; ++}; ++#endif /* ETHTOOL_GPAUSEPARAM */ ++ ++#ifndef ETHTOOL_SPAUSEPARAM ++#define ETHTOOL_SPAUSEPARAM 0x00000013 /* Set pause parameters. */ ++#endif ++#ifndef ETHTOOL_GRXCSUM ++#define ETHTOOL_GRXCSUM 0x00000014 /* Get RX hw csum enable (ethtool_value) */ ++#endif ++#ifndef ETHTOOL_SRXCSUM ++#define ETHTOOL_SRXCSUM 0x00000015 /* Set RX hw csum enable (ethtool_value) */ ++#endif ++#ifndef ETHTOOL_GTXCSUM ++#define ETHTOOL_GTXCSUM 0x00000016 /* Get TX hw csum enable (ethtool_value) */ ++#endif ++#ifndef ETHTOOL_STXCSUM ++#define ETHTOOL_STXCSUM 0x00000017 /* Set TX hw csum enable (ethtool_value) */ ++#endif ++#ifndef ETHTOOL_GSG ++#define ETHTOOL_GSG 0x00000018 /* Get scatter-gather enable ++ * (ethtool_value) */ ++#endif ++#ifndef ETHTOOL_SSG ++#define ETHTOOL_SSG 0x00000019 /* Set scatter-gather enable ++ * (ethtool_value). */ ++#endif ++#ifndef ETHTOOL_TEST ++#define ETHTOOL_TEST 0x0000001a /* execute NIC self-test, priv. */ ++#endif ++#ifndef ETHTOOL_GSTRINGS ++#define ETHTOOL_GSTRINGS 0x0000001b /* get specified string set */ ++#endif ++#ifndef ETHTOOL_PHYS_ID ++#define ETHTOOL_PHYS_ID 0x0000001c /* identify the NIC */ ++#endif ++#ifndef ETHTOOL_GSTATS ++#define ETHTOOL_GSTATS 0x0000001d /* get NIC-specific statistics */ ++#endif ++#ifndef ETHTOOL_GTSO ++#define ETHTOOL_GTSO 0x0000001e /* Get TSO enable (ethtool_value) */ ++#endif ++#ifndef ETHTOOL_STSO ++#define ETHTOOL_STSO 0x0000001f /* Set TSO enable (ethtool_value) */ ++#endif ++ ++#ifndef ETHTOOL_BUSINFO_LEN ++#define ETHTOOL_BUSINFO_LEN 32 ++#endif ++ ++/*****************************************************************************/ ++ ++enum RTL8168_DSM_STATE { ++ DSM_MAC_INIT = 1, ++ DSM_NIC_GOTO_D3 = 2, ++ DSM_IF_DOWN = 3, ++ DSM_NIC_RESUME_D3 = 4, ++ DSM_IF_UP = 5, ++}; ++ ++enum RTL8168_registers { ++ MAC0 = 0x00, /* Ethernet hardware address. */ ++ MAC4 = 0x04, ++ MAR0 = 0x08, /* Multicast filter. */ ++ CounterAddrLow = 0x10, ++ CounterAddrHigh = 0x14, ++ CustomLED = 0x18, ++ TxDescStartAddrLow = 0x20, ++ TxDescStartAddrHigh = 0x24, ++ TxHDescStartAddrLow = 0x28, ++ TxHDescStartAddrHigh = 0x2c, ++ FLASH = 0x30, ++ ERSR = 0x36, ++ ChipCmd = 0x37, ++ TxPoll = 0x38, ++ IntrMask = 0x3C, ++ IntrStatus = 0x3E, ++ TxConfig = 0x40, ++ RxConfig = 0x44, ++ TCTR = 0x48, ++ Cfg9346 = 0x50, ++ Config0 = 0x51, ++ Config1 = 0x52, ++ Config2 = 0x53, ++ Config3 = 0x54, ++ Config4 = 0x55, ++ Config5 = 0x56, ++ TDFNR = 0x57, ++ TimeIntr = 0x58, ++ PHYAR = 0x60, ++ CSIDR = 0x64, ++ CSIAR = 0x68, ++ PHYstatus = 0x6C, ++ MACDBG = 0x6D, ++ GPIO = 0x6E, ++ PMCH = 0x6F, ++ ERIDR = 0x70, ++ ERIAR = 0x74, ++ EPHY_RXER_NUM = 0x7C, ++ EPHYAR = 0x80, ++ OCPDR = 0xB0, ++ MACOCP = 0xB0, ++ OCPAR = 0xB4, ++ PHYOCP = 0xB8, ++ DBG_reg = 0xD1, ++ MCUCmd_reg = 0xD3, ++ RxMaxSize = 0xDA, ++ EFUSEAR = 0xDC, ++ CPlusCmd = 0xE0, ++ IntrMitigate = 0xE2, ++ RxDescAddrLow = 0xE4, ++ RxDescAddrHigh = 0xE8, ++ MTPS = 0xEC, ++ FuncEvent = 0xF0, ++ FuncEventMask = 0xF4, ++ FuncPresetState = 0xF8, ++ FuncForceEvent = 0xFC, ++}; ++ ++enum RTL8168_register_content { ++ /* InterruptStatusBits */ ++ SYSErr = 0x8000, ++ PCSTimeout = 0x4000, ++ SWInt = 0x0100, ++ TxDescUnavail = 0x0080, ++ RxFIFOOver = 0x0040, ++ LinkChg = 0x0020, ++ RxDescUnavail = 0x0010, ++ TxErr = 0x0008, ++ TxOK = 0x0004, ++ RxErr = 0x0002, ++ RxOK = 0x0001, ++ ++ /* RxStatusDesc */ ++ RxRWT = (1 << 22), ++ RxRES = (1 << 21), ++ RxRUNT = (1 << 20), ++ RxCRC = (1 << 19), ++ ++ /* ChipCmdBits */ ++ StopReq = 0x80, ++ CmdReset = 0x10, ++ CmdRxEnb = 0x08, ++ CmdTxEnb = 0x04, ++ RxBufEmpty = 0x01, ++ ++ /* Cfg9346Bits */ ++ Cfg9346_Lock = 0x00, ++ Cfg9346_Unlock = 0xC0, ++ Cfg9346_EEDO = (1 << 0), ++ Cfg9346_EEDI = (1 << 1), ++ Cfg9346_EESK = (1 << 2), ++ Cfg9346_EECS = (1 << 3), ++ Cfg9346_EEM0 = (1 << 6), ++ Cfg9346_EEM1 = (1 << 7), ++ ++ /* rx_mode_bits */ ++ AcceptErr = 0x20, ++ AcceptRunt = 0x10, ++ AcceptBroadcast = 0x08, ++ AcceptMulticast = 0x04, ++ AcceptMyPhys = 0x02, ++ AcceptAllPhys = 0x01, ++ ++ /* Transmit Priority Polling*/ ++ HPQ = 0x80, ++ NPQ = 0x40, ++ FSWInt = 0x01, ++ ++ /* RxConfigBits */ ++ Reserved2_shift = 13, ++ RxCfgDMAShift = 8, ++ RxCfg_128_int_en = (1 << 15), ++ RxCfg_fet_multi_en = (1 << 14), ++ RxCfg_half_refetch = (1 << 13), ++ RxCfg_9356SEL = (1 << 6), ++ ++ /* TxConfigBits */ ++ TxInterFrameGapShift = 24, ++ TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ ++ TxMACLoopBack = (1 << 17), /* MAC loopback */ ++ ++ /* Config1 register p.24 */ ++ LEDS1 = (1 << 7), ++ LEDS0 = (1 << 6), ++ Speed_down = (1 << 4), ++ MEMMAP = (1 << 3), ++ IOMAP = (1 << 2), ++ VPD = (1 << 1), ++ PMEnable = (1 << 0), /* Power Management Enable */ ++ ++ /* Config3 register */ ++ MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */ ++ LinkUp = (1 << 4), /* This bit is reserved in RTL8168B.*/ ++ /* Wake up when the cable connection is re-established */ ++ ECRCEN = (1 << 3), /* This bit is reserved in RTL8168B*/ ++ Jumbo_En0 = (1 << 2), /* This bit is reserved in RTL8168B*/ ++ RDY_TO_L23 = (1 << 1), /* This bit is reserved in RTL8168B*/ ++ Beacon_en = (1 << 0), /* This bit is reserved in RTL8168B*/ ++ ++ /* Config4 register */ ++ Jumbo_En1 = (1 << 1), /* This bit is reserved in RTL8168B*/ ++ ++ /* Config5 register */ ++ BWF = (1 << 6), /* Accept Broadcast wakeup frame */ ++ MWF = (1 << 5), /* Accept Multicast wakeup frame */ ++ UWF = (1 << 4), /* Accept Unicast wakeup frame */ ++ LanWake = (1 << 1), /* LanWake enable/disable */ ++ PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */ ++ ++ /* CPlusCmd */ ++ EnableBist = (1 << 15), ++ Macdbgo_oe = (1 << 14), ++ Normal_mode = (1 << 13), ++ Force_halfdup = (1 << 12), ++ Force_rxflow_en = (1 << 11), ++ Force_txflow_en = (1 << 10), ++ Cxpl_dbg_sel = (1 << 9),//This bit is reserved in RTL8168B ++ ASF = (1 << 8),//This bit is reserved in RTL8168C ++ PktCntrDisable = (1 << 7), ++ RxVlan = (1 << 6), ++ RxChkSum = (1 << 5), ++ Macdbgo_sel = 0x001C, ++ INTT_0 = 0x0000, ++ INTT_1 = 0x0001, ++ INTT_2 = 0x0002, ++ INTT_3 = 0x0003, ++ ++ /* rtl8168_PHYstatus */ ++ TxFlowCtrl = 0x40, ++ RxFlowCtrl = 0x20, ++ _1000bpsF = 0x10, ++ _100bps = 0x08, ++ _10bps = 0x04, ++ LinkStatus = 0x02, ++ FullDup = 0x01, ++ ++ /* DBG_reg */ ++ Fix_Nak_1 = (1 << 4), ++ Fix_Nak_2 = (1 << 3), ++ DBGPIN_E2 = (1 << 0), ++ ++ /* DumpCounterCommand */ ++ CounterDump = 0x8, ++ ++ /* PHY access */ ++ PHYAR_Flag = 0x80000000, ++ PHYAR_Write = 0x80000000, ++ PHYAR_Read = 0x00000000, ++ PHYAR_Reg_Mask = 0x1f, ++ PHYAR_Reg_shift = 16, ++ PHYAR_Data_Mask = 0xffff, ++ ++ /* EPHY access */ ++ EPHYAR_Flag = 0x80000000, ++ EPHYAR_Write = 0x80000000, ++ EPHYAR_Read = 0x00000000, ++ EPHYAR_Reg_Mask = 0x1f, ++ EPHYAR_Reg_shift = 16, ++ EPHYAR_Data_Mask = 0xffff, ++ ++ /* CSI access */ ++ CSIAR_Flag = 0x80000000, ++ CSIAR_Write = 0x80000000, ++ CSIAR_Read = 0x00000000, ++ CSIAR_ByteEn = 0x0f, ++ CSIAR_ByteEn_shift = 12, ++ CSIAR_Addr_Mask = 0x0fff, ++ ++ /* ERI access */ ++ ERIAR_Flag = 0x80000000, ++ ERIAR_Write = 0x80000000, ++ ERIAR_Read = 0x00000000, ++ ERIAR_Addr_Align = 4, /* ERI access register address must be 4 byte alignment */ ++ ERIAR_ExGMAC = 0, ++ ERIAR_MSIX = 1, ++ ERIAR_ASF = 2, ++ ERIAR_OOB = 2, ++ ERIAR_Type_shift = 16, ++ ERIAR_ByteEn = 0x0f, ++ ERIAR_ByteEn_shift = 12, ++ ++ /* OCP GPHY access */ ++ OCPDR_Write = 0x80000000, ++ OCPDR_Read = 0x00000000, ++ OCPDR_Reg_Mask = 0xFF, ++ OCPDR_Data_Mask = 0xFFFF, ++ OCPDR_GPHY_Reg_shift = 16, ++ OCPAR_Flag = 0x80000000, ++ OCPAR_GPHY_Write = 0x8000F060, ++ OCPAR_GPHY_Read = 0x0000F060, ++ OCPR_Write = 0x80000000, ++ OCPR_Read = 0x00000000, ++ OCPR_Addr_Reg_shift = 16, ++ OCPR_Flag = 0x80000000, ++ OCP_STD_PHY_BASE_PAGE = 0x0A40, ++ ++ /* MCU Command */ ++ Now_is_oob = (1 << 7), ++ Txfifo_empty = (1 << 5), ++ Rxfifo_empty = (1 << 4), ++ ++ /* E-FUSE access */ ++ EFUSE_WRITE = 0x80000000, ++ EFUSE_WRITE_OK = 0x00000000, ++ EFUSE_READ = 0x00000000, ++ EFUSE_READ_OK = 0x80000000, ++ EFUSE_Reg_Mask = 0x03FF, ++ EFUSE_Reg_Shift = 8, ++ EFUSE_Check_Cnt = 300, ++ EFUSE_READ_FAIL = 0xFF, ++ EFUSE_Data_Mask = 0x000000FF, ++ ++ /* GPIO */ ++ GPIO_en = (1 << 0), ++ ++}; ++ ++enum _DescStatusBit { ++ DescOwn = (1 << 31), /* Descriptor is owned by NIC */ ++ RingEnd = (1 << 30), /* End of descriptor ring */ ++ FirstFrag = (1 << 29), /* First segment of a packet */ ++ LastFrag = (1 << 28), /* Final segment of a packet */ ++ ++ /* Tx private */ ++ /*------ offset 0 of tx descriptor ------*/ ++ LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */ ++ MSSShift = 16, /* MSS value position */ ++ MSSMask = 0x7ffU, /* MSS value + LargeSend bit: 12 bits */ ++ TxIPCS = (1 << 18), /* Calculate IP checksum */ ++ TxUDPCS = (1 << 17), /* Calculate UDP/IP checksum */ ++ TxTCPCS = (1 << 16), /* Calculate TCP/IP checksum */ ++ TxVlanTag = (1 << 17), /* Add VLAN tag */ ++ ++ /*@@@@@@ offset 4 of tx descriptor => bits for RTL8168C/CP only begin @@@@@@*/ ++ TxUDPCS_C = (1 << 31), /* Calculate UDP/IP checksum */ ++ TxTCPCS_C = (1 << 30), /* Calculate TCP/IP checksum */ ++ TxIPCS_C = (1 << 29), /* Calculate IP checksum */ ++ /*@@@@@@ offset 4 of tx descriptor => bits for RTL8168C/CP only end @@@@@@*/ ++ ++ ++ /* Rx private */ ++ /*------ offset 0 of rx descriptor ------*/ ++ PID1 = (1 << 18), /* Protocol ID bit 1/2 */ ++ PID0 = (1 << 17), /* Protocol ID bit 2/2 */ ++ ++#define RxProtoUDP (PID1) ++#define RxProtoTCP (PID0) ++#define RxProtoIP (PID1 | PID0) ++#define RxProtoMask RxProtoIP ++ ++ RxIPF = (1 << 16), /* IP checksum failed */ ++ RxUDPF = (1 << 15), /* UDP/IP checksum failed */ ++ RxTCPF = (1 << 14), /* TCP/IP checksum failed */ ++ RxVlanTag = (1 << 16), /* VLAN tag available */ ++ ++ /*@@@@@@ offset 0 of rx descriptor => bits for RTL8168C/CP only begin @@@@@@*/ ++ RxUDPT = (1 << 18), ++ RxTCPT = (1 << 17), ++ /*@@@@@@ offset 0 of rx descriptor => bits for RTL8168C/CP only end @@@@@@*/ ++ ++ /*@@@@@@ offset 4 of rx descriptor => bits for RTL8168C/CP only begin @@@@@@*/ ++ RxV6F = (1 << 31), ++ RxV4F = (1 << 30), ++ /*@@@@@@ offset 4 of rx descriptor => bits for RTL8168C/CP only end @@@@@@*/ ++}; ++ ++enum features { ++// RTL_FEATURE_WOL = (1 << 0), ++ RTL_FEATURE_MSI = (1 << 1), ++}; ++ ++enum wol_capability { ++ WOL_DISABLED = 0, ++ WOL_ENABLED = 1 ++}; ++ ++enum bits { ++ BIT_0 = (1 << 0), ++ BIT_1 = (1 << 1), ++ BIT_2 = (1 << 2), ++ BIT_3 = (1 << 3), ++ BIT_4 = (1 << 4), ++ BIT_5 = (1 << 5), ++ BIT_6 = (1 << 6), ++ BIT_7 = (1 << 7), ++ BIT_8 = (1 << 8), ++ BIT_9 = (1 << 9), ++ BIT_10 = (1 << 10), ++ BIT_11 = (1 << 11), ++ BIT_12 = (1 << 12), ++ BIT_13 = (1 << 13), ++ BIT_14 = (1 << 14), ++ BIT_15 = (1 << 15), ++ BIT_16 = (1 << 16), ++ BIT_17 = (1 << 17), ++ BIT_18 = (1 << 18), ++ BIT_19 = (1 << 19), ++ BIT_20 = (1 << 20), ++ BIT_21 = (1 << 21), ++ BIT_22 = (1 << 22), ++ BIT_23 = (1 << 23), ++ BIT_24 = (1 << 24), ++ BIT_25 = (1 << 25), ++ BIT_26 = (1 << 26), ++ BIT_27 = (1 << 27), ++ BIT_28 = (1 << 28), ++ BIT_29 = (1 << 29), ++ BIT_30 = (1 << 30), ++ BIT_31 = (1 << 31) ++}; ++ ++enum effuse { ++ EFUSE_SUPPORT = 1, ++ EFUSE_NOT_SUPPORT = 0, ++}; ++#define RsvdMask 0x3fffc000 ++ ++struct TxDesc { ++ u32 opts1; ++ u32 opts2; ++ u64 addr; ++}; ++ ++struct RxDesc { ++ u32 opts1; ++ u32 opts2; ++ u64 addr; ++}; ++ ++struct ring_info { ++ struct sk_buff *skb; ++ u32 len; ++ u8 __pad[sizeof(void *) - sizeof(u32)]; ++}; ++ ++struct pci_resource { ++ u8 cmd; ++ u8 cls; ++ u16 io_base_h; ++ u16 io_base_l; ++ u16 mem_base_h; ++ u16 mem_base_l; ++ u8 ilr; ++ u16 resv_0x1c_h; ++ u16 resv_0x1c_l; ++ u16 resv_0x20_h; ++ u16 resv_0x20_l; ++ u16 resv_0x24_h; ++ u16 resv_0x24_l; ++ u16 resv_0x2c_h; ++ u16 resv_0x2c_l; ++ u32 pci_nvidia_geforce_6200; ++ u32 pci_nvidia_geforce__6250_1; ++}; ++ ++struct rtl8168_private { ++ void __iomem *mmio_addr; /* memory map physical address */ ++ struct pci_dev *pci_dev; /* Index of PCI device */ ++ struct net_device *dev; ++#ifdef CONFIG_R8168_NAPI ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) ++ struct napi_struct napi; ++ #endif ++#endif ++ struct net_device_stats stats; /* statistics of net device */ ++ spinlock_t lock; /* spin lock flag */ ++ spinlock_t phy_lock; /* spin lock flag for GPHY */ ++ u32 msg_enable; ++ u32 tx_tcp_csum_cmd; ++ u32 tx_udp_csum_cmd; ++ u32 tx_ip_csum_cmd; ++ int max_jumbo_frame_size; ++ int chipset; ++ u32 mcfg; ++ u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ ++ u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ ++ u32 dirty_rx; ++ u32 dirty_tx; ++ struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */ ++ struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ ++ dma_addr_t TxPhyAddr; ++ dma_addr_t RxPhyAddr; ++ struct sk_buff *Rx_skbuff[NUM_RX_DESC]; /* Rx data buffers */ ++ struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */ ++ unsigned rx_buf_sz; ++ int rx_fifo_overflow; ++ struct timer_list esd_timer; ++ struct timer_list link_timer; ++ int old_link_status; ++ struct pci_resource pci_cfg_space; ++ unsigned int esd_flag; ++ unsigned int pci_cfg_is_read; ++ unsigned int rtl8168_rx_config; ++ u16 cp_cmd; ++ u16 intr_mask; ++ int phy_auto_nego_reg; ++ int phy_1000_ctrl_reg; ++ u8 org_mac_addr[NODE_ADDRESS_SIZE]; ++#ifdef CONFIG_R8168_VLAN ++ struct vlan_group *vlgrp; ++#endif ++ u8 wol_enabled; ++ u8 efuse; ++ u8 eeprom_type; ++ u8 autoneg; ++ u8 duplex; ++ u16 speed; ++ u16 eeprom_len; ++ u16 cur_page; ++ ++ int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex); ++ void (*get_settings)(struct net_device *, struct ethtool_cmd *); ++ void (*phy_reset_enable)(struct net_device *); ++ unsigned int (*phy_reset_pending)(struct net_device *); ++ unsigned int (*link_ok)(struct net_device *); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ++ struct work_struct task; ++#else ++ struct delayed_work task; ++#endif ++ unsigned features; ++}; ++ ++enum eetype { ++ EEPROM_TYPE_NONE=0, ++ EEPROM_TYPE_93C46, ++ EEPROM_TYPE_93C56, ++ EEPROM_TWSI ++}; ++ ++enum mcfg { ++ CFG_METHOD_1=0, ++ CFG_METHOD_2, ++ CFG_METHOD_3, ++ CFG_METHOD_4, ++ CFG_METHOD_5, ++ CFG_METHOD_6, ++ CFG_METHOD_7, ++ CFG_METHOD_8, ++ CFG_METHOD_9 , ++ CFG_METHOD_10, ++ CFG_METHOD_11, ++ CFG_METHOD_12, ++ CFG_METHOD_13, ++ CFG_METHOD_14, ++ CFG_METHOD_15, ++ CFG_METHOD_16, ++ CFG_METHOD_17, ++ CFG_METHOD_18, ++ CFG_METHOD_19, ++ CFG_METHOD_20, ++ CFG_METHOD_21, ++ CFG_METHOD_22, ++ CFG_METHOD_23, ++ CFG_METHOD_MAX, ++ CFG_METHOD_DEFAULT = 0xFF ++}; ++ ++#define OOB_CMD_RESET 0x00 ++#define OOB_CMD_DRIVER_START 0x05 ++#define OOB_CMD_DRIVER_STOP 0x06 ++#define OOB_CMD_SET_IPMAC 0x41 ++ ++void mdio_write(struct rtl8168_private *tp, u32 RegAddr, u32 value); ++void rtl8168_ephy_write(void __iomem *ioaddr, int RegAddr, int value); ++void OCP_write(struct rtl8168_private *tp, u8 mask, u16 Reg, u32 data); ++void OOB_notify(struct rtl8168_private *tp, u8 cmd); ++void rtl8168_init_ring_indexes(struct rtl8168_private *tp); ++int rtl8168_eri_write(void __iomem *ioaddr, int addr, int len, u32 value, int type); ++void OOB_mutex_lock(struct rtl8168_private *tp); ++u32 mdio_read(struct rtl8168_private *tp, u32 RegAddr); ++u32 OCP_read(struct rtl8168_private *tp, u8 mask, u16 Reg); ++u32 rtl8168_eri_read(void __iomem *ioaddr, int addr, int len, int type); ++u16 rtl8168_ephy_read(void __iomem *ioaddr, int RegAddr); ++void OOB_mutex_unlock(struct rtl8168_private *tp); ++ ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34) ++#define netdev_mc_count(dev) ((dev)->mc_count) ++#define netdev_mc_empty(dev) (netdev_mc_count(dev) == 0) ++#define netdev_for_each_mc_addr(mclist, dev) \ ++ for (mclist = dev->mc_list; mclist; mclist = mclist->next) ++#endif +diff -Naur linux-3.4.19-old/drivers/net/ethernet/realtek/r8168/r8168_n.c linux-3.4.19-new/drivers/net/ethernet/realtek/r8168/r8168_n.c +--- linux-3.4.19-old/drivers/net/ethernet/realtek/r8168/r8168_n.c 1969-12-31 16:00:00.000000000 -0800 ++++ linux-3.4.19-new/drivers/net/ethernet/realtek/r8168/r8168_n.c 2012-10-24 23:36:24.000000000 -0700 +@@ -0,0 +1,17499 @@ +/* +################################################################################ +# @@ -2114,6 +2129,7 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt +#include +#include +#include ++#include + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) +#define dev_printk(A,B,fmt,args...) printk(A fmt,##args) @@ -2320,33 +2336,30 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + u32 msg_enable; +} debug = { -1 }; + -+/* media options */ -+#define MAX_UNITS 8 -+static int speed[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 }; -+static int duplex[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 }; -+static int autoneg[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 }; ++static unsigned short speed = SPEED_1000; ++static bool duplex = DUPLEX_FULL; ++static bool autoneg = AUTONEG_ENABLE; ++#ifdef CONFIG_ASPM ++static bool aspm = 1; ++#else ++static bool aspm = 0; ++#endif + +MODULE_AUTHOR("Realtek and the Linux r8168 crew "); +MODULE_DESCRIPTION("RealTek RTL-8168 Gigabit Ethernet driver"); + -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) -+MODULE_PARM(speed, "1-" __MODULE_STRING(MAX_UNITS) "i"); -+MODULE_PARM(duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); -+MODULE_PARM(autoneg, "1-" __MODULE_STRING(MAX_UNITS) "i"); -+#else -+static int num_speed = 0; -+static int num_duplex = 0; -+static int num_autoneg = 0; -+ -+module_param_array(speed, int, &num_speed, 0); -+module_param_array(duplex, int, &num_duplex, 0); -+module_param_array(autoneg, int, &num_autoneg, 0); -+#endif -+ ++module_param(speed, ushort, 0); +MODULE_PARM_DESC(speed, "force phy operation. Deprecated by ethtool (8)."); ++ ++module_param(duplex, bool, 0); +MODULE_PARM_DESC(duplex, "force phy operation. Deprecated by ethtool (8)."); ++ ++module_param(autoneg, bool, 0); +MODULE_PARM_DESC(autoneg, "force phy operation. Deprecated by ethtool (8)."); + ++module_param(aspm, bool, 0); ++MODULE_PARM_DESC(aspm, "force phy operation. Deprecated by ethtool (8)."); ++ +module_param(rx_copybreak, int, 0); +MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames"); +module_param(use_dac, int, 0); @@ -2617,33 +2630,19 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt +} +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7) + -+u16 map_phy_ocp_addr(struct rtl8168_private *tp, -+ u16 page, -+ u8 reg) ++static inline u16 map_phy_ocp_addr(u16 page, u16 reg) +{ -+ u16 ocppage; -+ u8 ocpreg; -+ u16 ocp_addr; -+ -+ if (page == 0) { -+ ocppage = 0x0A40 + (reg/8); -+ ocpreg = 0x10 + (reg % 8); -+ } else { -+ ocppage = page; -+ ocpreg = reg; ++ if (page != OCP_STD_PHY_BASE_PAGE) { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) ++ WARN_ON_ONCE(reg < 16); ++#endif ++ reg -= 16; + } + -+ ocppage <<= 4; ++ page <<= 4; ++ reg <<= 1; + -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) -+ WARN_ON_ONCE(ocpreg < 16); -+#endif -+ -+ ocpreg -= 16; -+ ocpreg <<= 1; -+ ocp_addr = ocppage + ocpreg; -+ -+ return ocp_addr; ++ return (page + reg); +} + +void mdio_write(struct rtl8168_private *tp, @@ -2670,18 +2669,17 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + u16 ocp_addr; + + if (RegAddr == 0x1F) { -+ tp->cur_page = value; ++ tp->cur_page = value ? value : OCP_STD_PHY_BASE_PAGE; + return; + } -+ ocp_addr = map_phy_ocp_addr(tp, tp->cur_page, RegAddr); ++ ocp_addr = map_phy_ocp_addr(tp->cur_page, RegAddr); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) + WARN_ON_ONCE(ocp_addr % 2); +#endif + data32 = ocp_addr/2; + data32 <<= OCPR_Addr_Reg_shift; -+ data32 += value; -+ data32 |= OCPR_Write; ++ data32 |= OCPR_Write | value; + + RTL_W32(PHYOCP, data32); + for (i = 0; i < 10; i++) { @@ -2746,7 +2744,7 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + u32 data32; + u16 ocp_addr; + -+ ocp_addr = map_phy_ocp_addr(tp, tp->cur_page, RegAddr); ++ ocp_addr = map_phy_ocp_addr(tp->cur_page, RegAddr); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) + WARN_ON_ONCE(ocp_addr % 2); @@ -2755,7 +2753,6 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + data32 <<= OCPR_Addr_Reg_shift; + + RTL_W32(PHYOCP, data32); -+ + for (i = 0; i < 10; i++) { + udelay(100); + @@ -3210,13 +3207,14 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + udelay(20); +} + -+static int ++static u32 +rtl8168_csi_read(struct rtl8168_private *tp, + u32 addr) +{ + void __iomem *ioaddr = tp->mmio_addr; + u32 cmd; -+ int i, value = -1; ++ int i; ++ u32 value = 0; + + cmd = CSIAR_Read | CSIAR_ByteEn << CSIAR_ByteEn_shift | (addr & CSIAR_Addr_Mask); + @@ -3230,7 +3228,7 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + + /* Check if the RTL8168 has completed CSI read */ + if (RTL_R32(CSIAR) & CSIAR_Flag) { -+ value = (int)RTL_R32(CSIDR); ++ value = (u32)RTL_R32(CSIDR); + break; + } + } @@ -3397,6 +3395,7 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + mdelay(2); + break; + default: ++ mdelay(10); + RTL_W8(ChipCmd, StopReq | CmdRxEnb | CmdTxEnb); + while (!(RTL_R32(TxConfig) & BIT_11)) udelay(100); + break; @@ -3516,6 +3515,7 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + void __iomem *ioaddr) +{ + unsigned long flags; ++ u16 data; + + if (tp->mcfg == CFG_METHOD_11) + rtl8168dp_10mbps_gphy_para(dev); @@ -3562,7 +3562,7 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + rtl8168_eri_write(ioaddr, 0xDC, 1, eri_data, ERIAR_ExGMAC); + eri_data |= BIT_0; + rtl8168_eri_write(ioaddr, 0xDC, 1, eri_data, ERIAR_ExGMAC); -+ if ((RTL_R8(ChipCmd) & (CmdRxEnb | CmdTxEnb)) == 0) { ++ if ((RTL_R8(ChipCmd) & (CmdRxEnb | CmdTxEnb))==0) { + int timeout; + for (timeout = 0; timeout < 10; timeout++) { + if ((rtl8168_eri_read(ioaddr, 0x1AE, 4, ERIAR_ExGMAC) & BIT_13)==0) @@ -3602,7 +3602,13 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + if (netif_msg_ifdown(tp)) + printk(KERN_INFO PFX "%s: link down\n", dev->name); + netif_carrier_off(dev); -+ if (tp->mcfg == CFG_METHOD_23) { ++ if (tp->mcfg == CFG_METHOD_21) { ++ spin_lock_irqsave(&tp->phy_lock, flags); ++ mdio_write(tp, 0x1f, 0x0000); ++ data = mdio_read(tp, MII_BMCR); ++ mdio_write(tp, MII_BMCR, data | BMCR_RESET); ++ spin_unlock_irqrestore(&tp->phy_lock, flags); ++ } else if (tp->mcfg == CFG_METHOD_23) { + RTL_W32(ERIDR, 0x00000001); + RTL_W32(ERIAR, 0x8042f108); + } @@ -3616,25 +3622,19 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + u16 *spd, + u8 *dup) +{ -+ unsigned char opt_speed; -+ unsigned char opt_duplex; -+ unsigned char opt_autoneg; + -+ opt_speed = ((idx < MAX_UNITS) && (idx >= 0)) ? speed[idx] : 0xff; -+ opt_duplex = ((idx < MAX_UNITS) && (idx >= 0)) ? duplex[idx] : 0xff; -+ opt_autoneg = ((idx < MAX_UNITS) && (idx >= 0)) ? autoneg[idx] : 0xff; ++ if ((*spd != SPEED_1000) && ++ (*spd != SPEED_100) && ++ (*spd != SPEED_10)) ++ *spd = SPEED_1000; + -+ if ((opt_speed == 0xff) | -+ (opt_duplex == 0xff) | -+ (opt_autoneg == 0xff)) { -+ *spd = SPEED_1000; -+ *dup = DUPLEX_FULL; -+ *aut = AUTONEG_ENABLE; -+ } else { -+ *spd = speed[idx]; -+ *dup = duplex[idx]; -+ *aut = autoneg[idx]; -+ } ++ if (unlikely((*dup != DUPLEX_FULL) && ++ (*dup != DUPLEX_HALF))) ++ *dup = DUPLEX_FULL; ++ ++ if (unlikely((*aut != AUTONEG_ENABLE) && ++ (*aut != AUTONEG_DISABLE))) ++ *aut = AUTONEG_ENABLE; +} + +static void @@ -3697,6 +3697,10 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + case CFG_METHOD_19: + RTL_W8(PMCH, RTL_R8(PMCH) & ~(BIT_7 | BIT_6)); + break; ++ case CFG_METHOD_21: ++ case CFG_METHOD_22: ++ RTL_W8(PMCH, RTL_R8(PMCH) & ~BIT_6); ++ break; + } +} + @@ -3721,6 +3725,10 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + case CFG_METHOD_18: + case CFG_METHOD_19: + RTL_W8(PMCH, RTL_R8(PMCH) | BIT_7 | BIT_6); ++ break; ++ case CFG_METHOD_21: ++ case CFG_METHOD_22: ++ RTL_W8(PMCH, RTL_R8(PMCH) | BIT_6); + break; + } + @@ -3924,17 +3932,13 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + tp->phy_auto_nego_reg = auto_nego; + tp->phy_1000_ctrl_reg = giga_ctrl; + -+ tp->autoneg = autoneg; -+ tp->speed = speed; -+ tp->duplex = duplex; -+ + spin_lock_irqsave(&tp->phy_lock, flags); + mdio_write(tp, 0x1f, 0x0000); + mdio_write(tp, MII_ADVERTISE, auto_nego); + mdio_write(tp, MII_CTRL1000, giga_ctrl); + mdio_write(tp, MII_BMCR, BMCR_RESET | BMCR_ANENABLE | BMCR_ANRESTART); + spin_unlock_irqrestore(&tp->phy_lock, flags); -+ mdelay(20); ++ mdelay(20); + } else { + /*true force*/ +#ifndef BMCR_SPEED100 @@ -3960,6 +3964,10 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + spin_unlock_irqrestore(&tp->phy_lock, flags); + } + ++ tp->autoneg = autoneg; ++ tp->speed = speed; ++ tp->duplex = duplex; ++ + if (tp->mcfg == CFG_METHOD_11) + rtl8168dp_10mbps_gphy_para(dev); + @@ -4275,12 +4283,15 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt +{ + struct rtl8168_private *tp = netdev_priv(dev); + unsigned long flags; ++ unsigned int i; ++ u8 *data = p; + + if (regs->len > R8168_REGS_SIZE) + regs->len = R8168_REGS_SIZE; + + spin_lock_irqsave(&tp->lock, flags); -+ memcpy_fromio(p, tp->mmio_addr, regs->len); ++ for (i = 0; i < regs->len; i++) ++ data[i] = readb(tp->mmio_addr + i); + spin_unlock_irqrestore(&tp->lock, flags); +} + @@ -4673,12 +4684,8 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + mdio_write(tp, 0x1F, 0x0A43); + data = mdio_read(tp, 0x11); + mdio_write(tp, 0x11, data | BIT_4); -+ mdio_write(tp, 0x1F, 0x0A41); -+ mdio_write(tp, 0x15, 0x0007); -+ mdio_write(tp, 0x16, 0x003C); -+ mdio_write(tp, 0x15, 0x4007); -+ mdio_write(tp, 0x16, 0x0006); -+ mdio_write(tp, 0x15, 0x0000); ++ mdio_write(tp, 0x1F, 0x0A5D); ++ mdio_write(tp, 0x10, 0x0006); + mdio_write(tp, 0x1F, 0x0000); + spin_unlock_irqrestore(&tp->phy_lock,flags); + break; @@ -4791,12 +4798,8 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + mdio_write(tp, 0x1F, 0x0A43); + data = mdio_read(tp, 0x11); + mdio_write(tp, 0x11, data & ~BIT_4); -+ mdio_write(tp, 0x1F, 0x0A41); -+ mdio_write(tp, 0x15, 0x0007); -+ mdio_write(tp, 0x16, 0x003C); -+ mdio_write(tp, 0x15, 0x4007); -+ mdio_write(tp, 0x16, 0x0000); -+ mdio_write(tp, 0x15, 0x0000); ++ mdio_write(tp, 0x1F, 0x0A5D); ++ mdio_write(tp, 0x10, 0x0000); + mdio_write(tp, 0x1F, 0x0000); + spin_unlock_irqrestore(&tp->phy_lock,flags); + break; @@ -8747,8 +8750,10 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + } else if (tp->mcfg == CFG_METHOD_16) { + struct pci_dev *pdev = tp->pci_dev; + -+ RTL_W8(0x6E, RTL_R8(0x6E) | BIT_6); -+ rtl8168_eri_write(ioaddr, 0x1AE, 2, 0x0403, ERIAR_ExGMAC); ++ if(aspm) { ++ RTL_W8(0x6E, RTL_R8(0x6E) | BIT_6); ++ rtl8168_eri_write(ioaddr, 0x1AE, 2, 0x0403, ERIAR_ExGMAC); ++ } + + mdio_write(tp, 0x1f, 0x0000); + mdio_write(tp, 0x00, 0x1800); @@ -11417,8 +11422,10 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + } else if (tp->mcfg == CFG_METHOD_17) { + struct pci_dev *pdev = tp->pci_dev; + -+ RTL_W8(0x6E, RTL_R8(0x6E) | BIT_6); -+ rtl8168_eri_write(ioaddr, 0x1AE, 2, 0x0403, ERIAR_ExGMAC); ++ if(aspm) { ++ RTL_W8(0x6E, RTL_R8(0x6E) | BIT_6); ++ rtl8168_eri_write(ioaddr, 0x1AE, 2, 0x0403, ERIAR_ExGMAC); ++ } + + mdio_write(tp, 0x1f, 0x0000); + mdio_write(tp, 0x00, 0x1800); @@ -12493,13 +12500,17 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + mdio_write(tp, 0x06, mdio_read(tp, 0x06) & ~BIT_8); + mdio_write(tp, 0x1f, 0x0000); + -+ mdio_write(tp, 0x1f, 0x0000); -+ gphy_val = mdio_read(tp, 0x15); -+ gphy_val |= BIT_12; -+ mdio_write(tp, 0x15, gphy_val); ++ if (aspm) { ++ mdio_write(tp, 0x1f, 0x0000); ++ gphy_val = mdio_read(tp, 0x15); ++ gphy_val |= BIT_12; ++ mdio_write(tp, 0x15, gphy_val); ++ } + } else if (tp->mcfg == CFG_METHOD_18) { -+ RTL_W8(0x6E, RTL_R8(0x6E) | BIT_6); -+ rtl8168_eri_write(ioaddr, 0x1AE, 2, 0x0403, ERIAR_ExGMAC); ++ if(aspm) { ++ RTL_W8(0x6E, RTL_R8(0x6E) | BIT_6); ++ rtl8168_eri_write(ioaddr, 0x1AE, 2, 0x0403, ERIAR_ExGMAC); ++ } + + mdio_write(tp, 0x1f, 0x0000); + mdio_write(tp, 0x00, 0x1800); @@ -13399,14 +13410,18 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + mdio_write(tp, 0x05, 0x8b85); + mdio_write(tp, 0x06, mdio_read(tp, 0x06) | BIT_15); + mdio_write(tp, 0x1f, 0x0000); -+ -+ mdio_write(tp, 0x1f, 0x0000); -+ gphy_val = mdio_read(tp, 0x15); -+ gphy_val |= BIT_12; -+ mdio_write(tp, 0x15, gphy_val); ++ ++ if (aspm) { ++ mdio_write(tp, 0x1f, 0x0000); ++ gphy_val = mdio_read(tp, 0x15); ++ gphy_val |= BIT_12; ++ mdio_write(tp, 0x15, gphy_val); ++ } + } else if (tp->mcfg == CFG_METHOD_19) { -+ RTL_W8(0x6E, RTL_R8(0x6E) | BIT_6); -+ rtl8168_eri_write(ioaddr, 0x1AE, 2, 0x0403, ERIAR_ExGMAC); ++ if(aspm) { ++ RTL_W8(0x6E, RTL_R8(0x6E) | BIT_6); ++ rtl8168_eri_write(ioaddr, 0x1AE, 2, 0x0403, ERIAR_ExGMAC); ++ } + + mdio_write(tp, 0x1f, 0x0000); + mdio_write(tp, 0x00, 0x1800); @@ -13728,13 +13743,17 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + mdio_write(tp, 0x06, mdio_read(tp, 0x06) | BIT_15); + mdio_write(tp, 0x1f, 0x0000); + -+ mdio_write(tp, 0x1f, 0x0000); -+ gphy_val = mdio_read(tp, 0x15); -+ gphy_val |= BIT_12; -+ mdio_write(tp, 0x15, gphy_val); ++ if (aspm) { ++ mdio_write(tp, 0x1f, 0x0000); ++ gphy_val = mdio_read(tp, 0x15); ++ gphy_val |= BIT_12; ++ mdio_write(tp, 0x15, gphy_val); ++ } + } else if (tp->mcfg == CFG_METHOD_20) { -+ RTL_W8(0x6E, RTL_R8(0x6E) | BIT_6); -+ rtl8168_eri_write(ioaddr, 0x1AE, 2, 0x0403, ERIAR_ExGMAC); ++ if(aspm) { ++ RTL_W8(0x6E, RTL_R8(0x6E) | BIT_6); ++ rtl8168_eri_write(ioaddr, 0x1AE, 2, 0x0403, ERIAR_ExGMAC); ++ } + + mdio_write(tp, 0x1f, 0x0000); + mdio_write(tp, 0x00, 0x1800); @@ -14318,37 +14337,19 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + mdio_write(tp, 0x06, mdio_read(tp, 0x06) | BIT_15); + mdio_write(tp, 0x1f, 0x0000); + -+ mdio_write(tp, 0x1f, 0x0000); -+ gphy_val = mdio_read(tp, 0x15); -+ gphy_val |= BIT_12; -+ mdio_write(tp, 0x15, gphy_val); -+ } else if (tp->mcfg == CFG_METHOD_21) { -+ u16 rtl8111g_phy_reset_value[]={ -+ 0xE008, 0xE01B, 0xE01D, 0xE01F, 0xE021, 0xE023, -+ 0xE025, 0xE027, 0x49D2, 0xF10D, 0x766C, 0x49E2, -+ 0xF00A, 0x1EC0, 0x8EE1, 0xC60A, 0x77C0, 0x4870, -+ 0x9FC0, 0x1EA0, 0xC707, 0x8EE1, 0x9D6C, 0xC603, -+ 0xBE00, 0xB416, 0x0076, 0xE86C, 0xC602, 0xBE00, -+ 0x0000, 0xC602, 0xBE00, 0x0000, 0xC602, 0xBE00, -+ 0x0000, 0xC602, 0xBE00, 0x0000, 0xC602, 0xBE00, -+ 0x0000, 0xC602, 0xBE00, 0x0000, 0xC602, 0xBE00, -+ 0x0000, 0x0000, 0x0000, 0x0000 -+ }; -+ for (i = 0; i < ARRAY_SIZE(rtl8111g_phy_reset_value); i++) -+ mac_ocp_write(tp, 0xF800+i*2, rtl8111g_phy_reset_value[i]); -+ mac_ocp_write(tp, 0xFC26, 0x8000); -+ mac_ocp_write(tp, 0xFC28, 0x0075); -+ ++ if (aspm) { ++ mdio_write(tp, 0x1f, 0x0000); ++ gphy_val = mdio_read(tp, 0x15); ++ gphy_val |= BIT_12; ++ mdio_write(tp, 0x15, gphy_val); ++ } ++ } else if (tp->mcfg == CFG_METHOD_21) { + RTL_W8(0xD0, RTL_R8(0xD0) | BIT_6 | BIT_7); -+ RTL_W8(0x6E, RTL_R8(0x6E) | BIT_6); + RTL_W8(0xF2, RTL_R8(0xF2) | BIT_6); + rtl8168_eri_write(ioaddr, 0x5F0, 2, 0x4f87, ERIAR_ExGMAC); + gphy_val = rtl8168_eri_read(ioaddr, 0xD4, 2, ERIAR_ExGMAC); + gphy_val |= (0x3F << 7); + rtl8168_eri_write(ioaddr, 0xD4, 2, gphy_val, ERIAR_ExGMAC); -+ gphy_val = rtl8168_eri_read(ioaddr, 0x3E8, 2, ERIAR_ExGMAC); -+ gphy_val |= BIT_14; -+ rtl8168_eri_write(ioaddr, 0x3E8, 2, gphy_val, ERIAR_ExGMAC); + gphy_val = rtl8168_eri_read(ioaddr, 0x1D0, 1, ERIAR_ExGMAC); + gphy_val |= BIT_1; + rtl8168_eri_write(ioaddr, 0x1D0, 1, gphy_val, ERIAR_ExGMAC); @@ -14827,20 +14828,20 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + mdio_write(tp, 0x14, 0x9a02); + mdio_write(tp, 0x14, 0x09a9); + mdio_write(tp, 0x14, 0x0284); -+ mdio_write(tp, 0x14, 0x55af); ++ mdio_write(tp, 0x14, 0x61af); + mdio_write(tp, 0x14, 0x02fc); + mdio_write(tp, 0x14, 0xad20); + mdio_write(tp, 0x14, 0x0302); -+ mdio_write(tp, 0x14, 0x8670); ++ mdio_write(tp, 0x14, 0x867c); + mdio_write(tp, 0x14, 0xad21); + mdio_write(tp, 0x14, 0x0302); -+ mdio_write(tp, 0x14, 0x85bd); ++ mdio_write(tp, 0x14, 0x85c9); + mdio_write(tp, 0x14, 0xad22); + mdio_write(tp, 0x14, 0x0302); + mdio_write(tp, 0x14, 0x1bc0); + mdio_write(tp, 0x14, 0xaf17); + mdio_write(tp, 0x14, 0xe302); -+ mdio_write(tp, 0x14, 0x86f7); ++ mdio_write(tp, 0x14, 0x8703); + mdio_write(tp, 0x14, 0xaf18); + mdio_write(tp, 0x14, 0x6201); + mdio_write(tp, 0x14, 0x06e0); @@ -14855,11 +14856,11 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + mdio_write(tp, 0x14, 0x131f); + mdio_write(tp, 0x14, 0xd104); + mdio_write(tp, 0x14, 0xbf87); -+ mdio_write(tp, 0x14, 0xea02); ++ mdio_write(tp, 0x14, 0xf302); + mdio_write(tp, 0x14, 0x4259); + mdio_write(tp, 0x14, 0x0287); -+ mdio_write(tp, 0x14, 0x78bf); -+ mdio_write(tp, 0x14, 0x87c3); ++ mdio_write(tp, 0x14, 0x88bf); ++ mdio_write(tp, 0x14, 0x87cf); + mdio_write(tp, 0x14, 0xd7b8); + mdio_write(tp, 0x14, 0x22d0); + mdio_write(tp, 0x14, 0x0c02); @@ -14904,13 +14905,19 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + mdio_write(tp, 0x14, 0x0002); + mdio_write(tp, 0x14, 0x0e66); + mdio_write(tp, 0x14, 0x0285); -+ mdio_write(tp, 0x14, 0xb4ef); ++ mdio_write(tp, 0x14, 0xc0ee); ++ mdio_write(tp, 0x14, 0x87fc); ++ mdio_write(tp, 0x14, 0x00e0); ++ mdio_write(tp, 0x14, 0x8245); ++ mdio_write(tp, 0x14, 0xf622); ++ mdio_write(tp, 0x14, 0xe482); ++ mdio_write(tp, 0x14, 0x45ef); + mdio_write(tp, 0x14, 0x96fe); + mdio_write(tp, 0x14, 0xfdfc); + mdio_write(tp, 0x14, 0x0402); -+ mdio_write(tp, 0x14, 0x846e); ++ mdio_write(tp, 0x14, 0x847a); + mdio_write(tp, 0x14, 0x0284); -+ mdio_write(tp, 0x14, 0xa702); ++ mdio_write(tp, 0x14, 0xb302); + mdio_write(tp, 0x14, 0x0cab); + mdio_write(tp, 0x14, 0x020c); + mdio_write(tp, 0x14, 0xc402); @@ -14957,16 +14964,16 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + mdio_write(tp, 0x14, 0x2202); + mdio_write(tp, 0x14, 0xae26); + mdio_write(tp, 0x14, 0x0284); -+ mdio_write(tp, 0x14, 0xec02); -+ mdio_write(tp, 0x14, 0x8559); ++ mdio_write(tp, 0x14, 0xf802); ++ mdio_write(tp, 0x14, 0x8565); + mdio_write(tp, 0x14, 0xd101); + mdio_write(tp, 0x14, 0xbf44); + mdio_write(tp, 0x14, 0xd502); + mdio_write(tp, 0x14, 0x4259); + mdio_write(tp, 0x14, 0xae0e); + mdio_write(tp, 0x14, 0x0284); -+ mdio_write(tp, 0x14, 0xde02); -+ mdio_write(tp, 0x14, 0x859d); ++ mdio_write(tp, 0x14, 0xea02); ++ mdio_write(tp, 0x14, 0x85a9); + mdio_write(tp, 0x14, 0xe182); + mdio_write(tp, 0x14, 0x2ff6); + mdio_write(tp, 0x14, 0x2ae5); @@ -15006,7 +15013,7 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + mdio_write(tp, 0x14, 0xae07); + mdio_write(tp, 0x14, 0xd306); + mdio_write(tp, 0x14, 0xaf85); -+ mdio_write(tp, 0x14, 0x4ad3); ++ mdio_write(tp, 0x14, 0x56d3); + mdio_write(tp, 0x14, 0x03e0); + mdio_write(tp, 0x14, 0x8011); + mdio_write(tp, 0x14, 0xad26); @@ -15062,11 +15069,11 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + mdio_write(tp, 0x14, 0x2711); + mdio_write(tp, 0x14, 0xe187); + mdio_write(tp, 0x14, 0xfebf); -+ mdio_write(tp, 0x14, 0x87db); ++ mdio_write(tp, 0x14, 0x87e4); + mdio_write(tp, 0x14, 0x0242); + mdio_write(tp, 0x14, 0x590d); + mdio_write(tp, 0x14, 0x11bf); -+ mdio_write(tp, 0x14, 0x87de); ++ mdio_write(tp, 0x14, 0x87e7); + mdio_write(tp, 0x14, 0x0242); + mdio_write(tp, 0x14, 0x59ef); + mdio_write(tp, 0x14, 0x96fe); @@ -15075,10 +15082,10 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + mdio_write(tp, 0x14, 0xfaef); + mdio_write(tp, 0x14, 0x69d1); + mdio_write(tp, 0x14, 0x00bf); -+ mdio_write(tp, 0x14, 0x87db); ++ mdio_write(tp, 0x14, 0x87e4); + mdio_write(tp, 0x14, 0x0242); + mdio_write(tp, 0x14, 0x59bf); -+ mdio_write(tp, 0x14, 0x87de); ++ mdio_write(tp, 0x14, 0x87e7); + mdio_write(tp, 0x14, 0x0242); + mdio_write(tp, 0x14, 0x59ef); + mdio_write(tp, 0x14, 0x96fe); @@ -15093,7 +15100,7 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + mdio_write(tp, 0x14, 0x8241); + mdio_write(tp, 0x14, 0xa000); + mdio_write(tp, 0x14, 0x0502); -+ mdio_write(tp, 0x14, 0x85df); ++ mdio_write(tp, 0x14, 0x85eb); + mdio_write(tp, 0x14, 0xae0e); + mdio_write(tp, 0x14, 0xa001); + mdio_write(tp, 0x14, 0x0502); @@ -15183,7 +15190,7 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + mdio_write(tp, 0x14, 0x46a0); + mdio_write(tp, 0x14, 0x0005); + mdio_write(tp, 0x14, 0x0286); -+ mdio_write(tp, 0x14, 0x8aae); ++ mdio_write(tp, 0x14, 0x96ae); + mdio_write(tp, 0x14, 0x06a0); + mdio_write(tp, 0x14, 0x0103); + mdio_write(tp, 0x14, 0x0219); @@ -15250,7 +15257,7 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + mdio_write(tp, 0x14, 0x8013); + mdio_write(tp, 0x14, 0xad24); + mdio_write(tp, 0x14, 0x1cbf); -+ mdio_write(tp, 0x14, 0x87e7); ++ mdio_write(tp, 0x14, 0x87f0); + mdio_write(tp, 0x14, 0x0242); + mdio_write(tp, 0x14, 0x97ad); + mdio_write(tp, 0x14, 0x2813); @@ -15258,11 +15265,11 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + mdio_write(tp, 0x14, 0xfca0); + mdio_write(tp, 0x14, 0x0005); + mdio_write(tp, 0x14, 0x0287); -+ mdio_write(tp, 0x14, 0x2aae); ++ mdio_write(tp, 0x14, 0x36ae); + mdio_write(tp, 0x14, 0x10a0); + mdio_write(tp, 0x14, 0x0105); + mdio_write(tp, 0x14, 0x0287); -+ mdio_write(tp, 0x14, 0x3cae); ++ mdio_write(tp, 0x14, 0x48ae); + mdio_write(tp, 0x14, 0x08e0); + mdio_write(tp, 0x14, 0x8230); + mdio_write(tp, 0x14, 0xf626); @@ -15284,12 +15291,12 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + mdio_write(tp, 0x14, 0xfb02); + mdio_write(tp, 0x14, 0x46d3); + mdio_write(tp, 0x14, 0xad50); -+ mdio_write(tp, 0x14, 0x2bbf); -+ mdio_write(tp, 0x14, 0x87e4); ++ mdio_write(tp, 0x14, 0x2fbf); ++ mdio_write(tp, 0x14, 0x87ed); + mdio_write(tp, 0x14, 0xd101); + mdio_write(tp, 0x14, 0x0242); + mdio_write(tp, 0x14, 0x59bf); -+ mdio_write(tp, 0x14, 0x87e4); ++ mdio_write(tp, 0x14, 0x87ed); + mdio_write(tp, 0x14, 0xd100); + mdio_write(tp, 0x14, 0x0242); + mdio_write(tp, 0x14, 0x59e0); @@ -15300,8 +15307,10 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + mdio_write(tp, 0x14, 0x46ae); + mdio_write(tp, 0x14, 0xd100); + mdio_write(tp, 0x14, 0xbf87); -+ mdio_write(tp, 0x14, 0xe702); ++ mdio_write(tp, 0x14, 0xf002); + mdio_write(tp, 0x14, 0x4259); ++ mdio_write(tp, 0x14, 0xee87); ++ mdio_write(tp, 0x14, 0xfc00); + mdio_write(tp, 0x14, 0xe082); + mdio_write(tp, 0x14, 0x30f6); + mdio_write(tp, 0x14, 0x26e4); @@ -15314,8 +15323,8 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + mdio_write(tp, 0x14, 0xfaef); + mdio_write(tp, 0x14, 0x69fb); + mdio_write(tp, 0x14, 0xbf87); -+ mdio_write(tp, 0x14, 0xa3d7); -+ mdio_write(tp, 0x14, 0x0020); ++ mdio_write(tp, 0x14, 0xb3d7); ++ mdio_write(tp, 0x14, 0x001c); + mdio_write(tp, 0x14, 0xd819); + mdio_write(tp, 0x14, 0xd919); + mdio_write(tp, 0x14, 0xda19); @@ -15335,39 +15344,35 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + mdio_write(tp, 0x14, 0x7d00); + mdio_write(tp, 0x14, 0x0345); + mdio_write(tp, 0x14, 0x5c00); -+ mdio_write(tp, 0x14, 0x0087); -+ mdio_write(tp, 0x14, 0xcf00); + mdio_write(tp, 0x14, 0x0143); + mdio_write(tp, 0x14, 0x4f00); + mdio_write(tp, 0x14, 0x0387); -+ mdio_write(tp, 0x14, 0xd200); ++ mdio_write(tp, 0x14, 0xdb00); + mdio_write(tp, 0x14, 0x0987); -+ mdio_write(tp, 0x14, 0xd500); ++ mdio_write(tp, 0x14, 0xde00); + mdio_write(tp, 0x14, 0x0987); -+ mdio_write(tp, 0x14, 0xd800); ++ mdio_write(tp, 0x14, 0xe100); + mdio_write(tp, 0x14, 0x0087); -+ mdio_write(tp, 0x14, 0xe1a4); ++ mdio_write(tp, 0x14, 0xeaa4); + mdio_write(tp, 0x14, 0x00b8); + mdio_write(tp, 0x14, 0x20c4); + mdio_write(tp, 0x14, 0x1600); + mdio_write(tp, 0x14, 0x000f); + mdio_write(tp, 0x14, 0xf800); -+ mdio_write(tp, 0x14, 0x7000); -+ mdio_write(tp, 0x14, 0xb82e); -+ mdio_write(tp, 0x14, 0x98a5); -+ mdio_write(tp, 0x14, 0x8ab6); ++ mdio_write(tp, 0x14, 0x7098); ++ mdio_write(tp, 0x14, 0xa58a); ++ mdio_write(tp, 0x14, 0xb6a8); ++ mdio_write(tp, 0x14, 0x3e50); + mdio_write(tp, 0x14, 0xa83e); -+ mdio_write(tp, 0x14, 0x50a8); -+ mdio_write(tp, 0x14, 0x3e33); ++ mdio_write(tp, 0x14, 0x33bc); ++ mdio_write(tp, 0x14, 0xc622); + mdio_write(tp, 0x14, 0xbcc6); -+ mdio_write(tp, 0x14, 0x22bc); -+ mdio_write(tp, 0x14, 0xc6aa); -+ mdio_write(tp, 0x14, 0xa442); -+ mdio_write(tp, 0x14, 0xffc4); -+ mdio_write(tp, 0x14, 0x0800); -+ mdio_write(tp, 0x14, 0xc416); -+ mdio_write(tp, 0x14, 0xa8bc); -+ mdio_write(tp, 0x14, 0xc000); ++ mdio_write(tp, 0x14, 0xaaa4); ++ mdio_write(tp, 0x14, 0x42ff); ++ mdio_write(tp, 0x14, 0xc408); ++ mdio_write(tp, 0x14, 0x00c4); ++ mdio_write(tp, 0x14, 0x16a8); ++ mdio_write(tp, 0x14, 0xbcc0); + mdio_write(tp, 0x13, 0xb818); + mdio_write(tp, 0x14, 0x02f3); + mdio_write(tp, 0x13, 0xb81a); @@ -15378,6 +15383,10 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + mdio_write(tp, 0x14, 0x3c66); + mdio_write(tp, 0x13, 0xb820); + mdio_write(tp, 0x14, 0x021f); ++ mdio_write(tp, 0x13, 0xc416); ++ mdio_write(tp, 0x14, 0x0500); ++ mdio_write(tp, 0x13, 0xb82e); ++ mdio_write(tp, 0x14, 0xfffc); + mdio_write(tp, 0x1F, 0x0A43); + mdio_write(tp, 0x13, 0x0000); + mdio_write(tp, 0x14, 0x0000); @@ -15456,18 +15465,16 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + mdio_write(tp, 0x14, 0x9065); + mdio_write(tp, 0x14, 0x1065); + -+ mdio_write(tp, 0x1F, 0x0A43); -+ mdio_write(tp, 0x10, mdio_read(tp, 0x10) | BIT_2); ++ if(aspm){ ++ mdio_write(tp, 0x1F, 0x0A43); ++ mdio_write(tp, 0x10, mdio_read(tp, 0x10) | BIT_2); ++ } ++ + mdio_write(tp, 0x1F, 0x0000); + } else if (tp->mcfg == CFG_METHOD_22) { + RTL_W8(0xD0, RTL_R8(0xD0) | BIT_6 | BIT_7); -+ RTL_W8(0x6E, RTL_R8(0x6E) | BIT_6); + RTL_W8(0xF2, RTL_R8(0xF2) | BIT_6); + rtl8168_eri_write(ioaddr, 0x5F0, 2, 0x4f87, ERIAR_ExGMAC); -+ -+ gphy_val = rtl8168_eri_read(ioaddr, 0x3E8, 2, ERIAR_ExGMAC); -+ gphy_val |= BIT_14; -+ rtl8168_eri_write(ioaddr, 0x3E8, 2, gphy_val, ERIAR_ExGMAC); + gphy_val = rtl8168_eri_read(ioaddr, 0x1D0, 1, ERIAR_ExGMAC); + gphy_val |= BIT_1; + rtl8168_eri_write(ioaddr, 0x1D0, 1, gphy_val, ERIAR_ExGMAC); @@ -16384,7 +16391,7 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt +rtl8168_phy_power_up (struct net_device *dev) +{ + struct rtl8168_private *tp = netdev_priv(dev); -+ unsigned long flags; ++ unsigned long flags; + + spin_lock_irqsave(&tp->phy_lock, flags); + mdio_write(tp, 0x1F, 0x0000); @@ -16415,7 +16422,7 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt +rtl8168_phy_power_down (struct net_device *dev) +{ + struct rtl8168_private *tp = netdev_priv(dev); -+ unsigned long flags; ++ unsigned long flags; + + spin_lock_irqsave(&tp->phy_lock, flags); + mdio_write(tp, 0x1F, 0x0000); @@ -16475,6 +16482,12 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + tp->dev = dev; + tp->msg_enable = netif_msg_init(debug.msg_enable, R8168_MSG_DEFAULT); + ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,26) ++ if (!aspm) ++ pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | ++ PCIE_LINK_STATE_CLKPM); ++#endif ++ + /* enable device (incl. PCI PM wakeup and hotplug setup) */ + rc = pci_enable_device(pdev); + if (rc < 0) { @@ -16667,16 +16680,20 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + struct timer_list *timer = &tp->esd_timer; + unsigned long timeout = RTL8168_ESD_TIMEOUT; + u8 cmd; -+ u8 cls; + u16 io_base_l; -+ u16 io_base_h; + u16 mem_base_l; + u16 mem_base_h; + u8 ilr; ++ u16 resv_0x1c_h; ++ u16 resv_0x1c_l; + u16 resv_0x20_l; + u16 resv_0x20_h; + u16 resv_0x24_l; + u16 resv_0x24_h; ++ u16 resv_0x2c_h; ++ u16 resv_0x2c_l; ++ u32 pci_nvidia_geforce_6200; ++ u32 pci_nvidia_geforce__6250_1; + + tp->esd_flag = 0; + @@ -16686,24 +16703,12 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + tp->esd_flag = 1; + } + -+ pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cls); -+ if (cls != tp->pci_cfg_space.cls) { -+ pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, tp->pci_cfg_space.cls); -+ tp->esd_flag = 1; -+ } -+ + pci_read_config_word(pdev, PCI_BASE_ADDRESS_0, &io_base_l); + if (io_base_l != tp->pci_cfg_space.io_base_l) { + pci_write_config_word(pdev, PCI_BASE_ADDRESS_0, tp->pci_cfg_space.io_base_l); + tp->esd_flag = 1; + } + -+ pci_read_config_word(pdev, PCI_BASE_ADDRESS_0 + 2, &io_base_h); -+ if (io_base_h != tp->pci_cfg_space.io_base_h) { -+ pci_write_config_word(pdev, PCI_BASE_ADDRESS_0 + 2, tp->pci_cfg_space.io_base_h); -+ tp->esd_flag = 1; -+ } -+ + pci_read_config_word(pdev, PCI_BASE_ADDRESS_2, &mem_base_l); + if (mem_base_l != tp->pci_cfg_space.mem_base_l) { + pci_write_config_word(pdev, PCI_BASE_ADDRESS_2, tp->pci_cfg_space.mem_base_l); @@ -16711,14 +16716,20 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + } + + pci_read_config_word(pdev, PCI_BASE_ADDRESS_2 + 2, &mem_base_h); -+ if (mem_base_h != tp->pci_cfg_space.mem_base_h) { ++ if (mem_base_h!= tp->pci_cfg_space.mem_base_h) { + pci_write_config_word(pdev, PCI_BASE_ADDRESS_2 + 2, tp->pci_cfg_space.mem_base_h); + tp->esd_flag = 1; + } + -+ pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &ilr); -+ if (ilr != tp->pci_cfg_space.ilr) { -+ pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, tp->pci_cfg_space.ilr); ++ pci_read_config_word(pdev, PCI_BASE_ADDRESS_3, &resv_0x1c_l); ++ if (resv_0x1c_l != tp->pci_cfg_space.resv_0x1c_l) { ++ pci_write_config_word(pdev, PCI_BASE_ADDRESS_3, tp->pci_cfg_space.resv_0x1c_l); ++ tp->esd_flag = 1; ++ } ++ ++ pci_read_config_word(pdev, PCI_BASE_ADDRESS_3 + 2, &resv_0x1c_h); ++ if (resv_0x1c_h != tp->pci_cfg_space.resv_0x1c_h) { ++ pci_write_config_word(pdev, PCI_BASE_ADDRESS_3 + 2, tp->pci_cfg_space.resv_0x1c_h); + tp->esd_flag = 1; + } + @@ -16746,6 +16757,36 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + tp->esd_flag = 1; + } + ++ pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &ilr); ++ if (ilr != tp->pci_cfg_space.ilr) { ++ pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, tp->pci_cfg_space.ilr); ++ tp->esd_flag = 1; ++ } ++ ++ pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &resv_0x2c_l); ++ if (resv_0x2c_l != tp->pci_cfg_space.resv_0x2c_l) { ++ pci_write_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, tp->pci_cfg_space.resv_0x2c_l); ++ tp->esd_flag = 1; ++ } ++ ++ pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID + 2, &resv_0x2c_h); ++ if (resv_0x2c_h != tp->pci_cfg_space.resv_0x2c_h) { ++ pci_write_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID + 2, tp->pci_cfg_space.resv_0x2c_h); ++ tp->esd_flag = 1; ++ } ++ ++ pci_nvidia_geforce_6200 = rtl8168_csi_read(tp, PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6200); ++ if (pci_nvidia_geforce_6200 != tp->pci_cfg_space.pci_nvidia_geforce_6200) { ++ rtl8168_csi_write(tp, PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6200, tp->pci_cfg_space.pci_nvidia_geforce_6200); ++ tp->esd_flag = 1; ++ } ++ ++ pci_nvidia_geforce__6250_1 = rtl8168_csi_read(tp, PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6250_1); ++ if (pci_nvidia_geforce__6250_1 != tp->pci_cfg_space.pci_nvidia_geforce__6250_1) { ++ rtl8168_csi_write(tp, PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6250_1, tp->pci_cfg_space.pci_nvidia_geforce__6250_1); ++ tp->esd_flag = 1; ++ } ++ + if (tp->esd_flag != 0) { + rtl8168_tx_clear(tp); + rtl8168_hw_start(dev); @@ -16832,8 +16873,6 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + struct rtl8168_private *tp; + void __iomem *ioaddr = NULL; + static int board_idx = -1; -+ u8 autoneg, duplex; -+ u16 speed; + u16 mac_addr[4]; + + int i, rc; @@ -16966,7 +17005,7 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + + pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40); + -+ rtl8168_link_option(board_idx, &autoneg, &speed, &duplex); ++ rtl8168_link_option(board_idx, (u8*)&autoneg, (u16*)&speed, (u8*)&duplex); + + rtl8168_set_speed(dev, autoneg, speed, duplex); + @@ -17710,9 +17749,16 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + ephy_data = rtl8168_ephy_read(ioaddr, 0x19); + ephy_data |= (BIT_2 | BIT_5 | BIT_9); + rtl8168_ephy_write(ioaddr, 0x19, ephy_data); -+ RTL_W8(Config5, RTL_R8(Config5) | BIT_0); -+ RTL_W8(Config2, (RTL_R8(Config2) | BIT_7) & ~BIT_5); + ++ if(aspm){ ++ RTL_W8(Config5, RTL_R8(Config5) | BIT_0); ++ RTL_W8(Config2, RTL_R8(Config2) | BIT_7); ++ } else { ++ RTL_W8(Config5, RTL_R8(Config5) & ~BIT_0); ++ RTL_W8(Config2, RTL_R8(Config2) & ~BIT_7); ++ } ++ ++ RTL_W8(Config2, RTL_R8(Config2) & ~BIT_5); + + RTL_W8(0xD0, RTL_R8(0xD0) | BIT_6); + RTL_W8(0xF2, RTL_R8(0xF2) | BIT_6); @@ -17769,8 +17815,13 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + ephy_data |= (BIT_2 | BIT_5 | BIT_9); + rtl8168_ephy_write(ioaddr, 0x19, ephy_data); + -+ RTL_W8(Config5, RTL_R8(Config5) | BIT_0); -+ RTL_W8(Config2, RTL_R8(Config2) | BIT_7); ++ if(aspm){ ++ RTL_W8(Config5, RTL_R8(Config5) | BIT_0); ++ RTL_W8(Config2, RTL_R8(Config2) | BIT_7); ++ } else { ++ RTL_W8(Config5, RTL_R8(Config5) & ~BIT_0); ++ RTL_W8(Config2, RTL_R8(Config2) & ~BIT_7); ++ } + + tp->cp_cmd &= 0x2063; + if (dev->mtu > ETH_DATA_LEN) { @@ -17849,8 +17900,13 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + ephy_data |= (BIT_2 | BIT_5 | BIT_9); + rtl8168_ephy_write(ioaddr, 0x19, ephy_data); + -+ RTL_W8(Config5, RTL_R8(Config5) | BIT_0); -+ RTL_W8(Config2, RTL_R8(Config2) | BIT_7); ++ if(aspm){ ++ RTL_W8(Config5, RTL_R8(Config5) | BIT_0); ++ RTL_W8(Config2, RTL_R8(Config2) | BIT_7); ++ } else { ++ RTL_W8(Config5, RTL_R8(Config5) & ~BIT_0); ++ RTL_W8(Config2, RTL_R8(Config2) & ~BIT_7); ++ } + + tp->cp_cmd &= 0x2063; + if (dev->mtu > ETH_DATA_LEN) { @@ -17909,36 +17965,21 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + rtl8168_eri_write(ioaddr, 0xB8, 2, 0x00000000, ERIAR_ExGMAC); + RTL_W8(0x1B, RTL_R8(0x1B) & ~0x07); + -+ RTL_W8(Config5, RTL_R8(Config5) | BIT_0); -+ RTL_W8(Config2, RTL_R8(Config2) | BIT_7); ++ if(aspm){ ++ RTL_W8(Config5, RTL_R8(Config5) | BIT_0); ++ RTL_W8(Config2, RTL_R8(Config2) | BIT_7); ++ } else { ++ RTL_W8(Config5, RTL_R8(Config5) & ~BIT_0); ++ RTL_W8(Config2, RTL_R8(Config2) & ~BIT_7); ++ } ++ + RTL_W8(0xF1, RTL_R8(0xF1) | BIT_7); + + csi_tmp = rtl8168_eri_read(ioaddr, 0x2FC, 1, ERIAR_ExGMAC); -+ csi_tmp &= ~(BIT_0 | BIT_1); -+ csi_tmp |= (BIT_2 | BIT_0); ++ csi_tmp &= ~(BIT_0 | BIT_1 | BIT_2); ++ csi_tmp |= BIT_0; + rtl8168_eri_write(ioaddr, 0x2FC, 1, csi_tmp, ERIAR_ExGMAC); + -+ csi_tmp = rtl8168_eri_read(ioaddr, 0x3F2, 2, ERIAR_ExGMAC); -+ csi_tmp &= ~(BIT_0 | BIT_1 | BIT_8 | BIT_9 | BIT_10 | BIT_11 | BIT_12 | BIT_13 | BIT_14); -+ csi_tmp |= (BIT_0 | BIT_1 | BIT_9 | BIT_10 | BIT_12 | BIT_13 | BIT_14); -+ rtl8168_eri_write(ioaddr, 0x3F2, 2, csi_tmp, ERIAR_ExGMAC); -+ csi_tmp = rtl8168_eri_read(ioaddr, 0x3F5, 1, ERIAR_ExGMAC); -+ csi_tmp |= BIT_6 | BIT_7; -+ rtl8168_eri_write(ioaddr, 0x3F5, 1, csi_tmp, ERIAR_ExGMAC); -+ rtl8168_eri_write(ioaddr, 0x2E8, 2, 0x883C, ERIAR_ExGMAC); -+ rtl8168_eri_write(ioaddr, 0x2EA, 2, 0x8C12, ERIAR_ExGMAC); -+ rtl8168_eri_write(ioaddr, 0x2EC, 2, 0x9003, ERIAR_ExGMAC); -+ rtl8168_eri_write(ioaddr, 0x2E2, 2, 0x883C, ERIAR_ExGMAC); -+ rtl8168_eri_write(ioaddr, 0x2E4, 2, 0x8C12, ERIAR_ExGMAC); -+ rtl8168_eri_write(ioaddr, 0x2E6, 2, 0x9003, ERIAR_ExGMAC); -+ -+ if (!(RTL_R8(PHYstatus) & BIT_7)) { -+ rtl8168_eri_write(ioaddr, 0x3FC, 4, 0x083C083C, ERIAR_ExGMAC); -+ csi_tmp = rtl8168_eri_read(ioaddr, 0x3F8, 1, ERIAR_ExGMAC); -+ csi_tmp |= BIT_0; -+ rtl8168_eri_write(ioaddr, 0x3F8, 1, csi_tmp, ERIAR_ExGMAC); -+ } -+ + if (dev->mtu > ETH_DATA_LEN) { + RTL_W8(MTPS, 0x27); + @@ -17983,8 +18024,14 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + rtl8168_eri_write(ioaddr, 0xB8, 2, 0x00000000, ERIAR_ExGMAC); + RTL_W8(0x1B, RTL_R8(0x1B) & ~0x07); + -+ RTL_W8(Config5, RTL_R8(Config5) | BIT_0); -+ RTL_W8(Config2, RTL_R8(Config2) | BIT_7); ++ if(aspm){ ++ RTL_W8(Config5, RTL_R8(Config5) | BIT_0); ++ RTL_W8(Config2, RTL_R8(Config2) | BIT_7); ++ } else { ++ RTL_W8(Config5, RTL_R8(Config5) & ~BIT_0); ++ RTL_W8(Config2, RTL_R8(Config2) & ~BIT_7); ++ } ++ + csi_tmp = rtl8168_eri_read(ioaddr, 0x2FC, 1, ERIAR_ExGMAC); + csi_tmp |= BIT_2; + rtl8168_eri_write(ioaddr, 0x2FC, 1, csi_tmp, ERIAR_ExGMAC); @@ -18136,16 +18183,20 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + + if (!tp->pci_cfg_is_read) { + pci_read_config_byte(pdev, PCI_COMMAND, &tp->pci_cfg_space.cmd); -+ pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &tp->pci_cfg_space.cls); + pci_read_config_word(pdev, PCI_BASE_ADDRESS_0, &tp->pci_cfg_space.io_base_l); + pci_read_config_word(pdev, PCI_BASE_ADDRESS_0 + 2, &tp->pci_cfg_space.io_base_h); + pci_read_config_word(pdev, PCI_BASE_ADDRESS_2, &tp->pci_cfg_space.mem_base_l); + pci_read_config_word(pdev, PCI_BASE_ADDRESS_2 + 2, &tp->pci_cfg_space.mem_base_h); ++ pci_read_config_word(pdev, PCI_BASE_ADDRESS_3, &tp->pci_cfg_space.resv_0x1c_l); ++ pci_read_config_word(pdev, PCI_BASE_ADDRESS_3 + 2, &tp->pci_cfg_space.resv_0x1c_h); + pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &tp->pci_cfg_space.ilr); + pci_read_config_word(pdev, PCI_BASE_ADDRESS_4, &tp->pci_cfg_space.resv_0x20_l); + pci_read_config_word(pdev, PCI_BASE_ADDRESS_4 + 2, &tp->pci_cfg_space.resv_0x20_h); + pci_read_config_word(pdev, PCI_BASE_ADDRESS_5, &tp->pci_cfg_space.resv_0x24_l); + pci_read_config_word(pdev, PCI_BASE_ADDRESS_5 + 2, &tp->pci_cfg_space.resv_0x24_h); ++ pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &tp->pci_cfg_space.resv_0x2c_l); ++ pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID + 2, &tp->pci_cfg_space.resv_0x2c_h); ++ tp->pci_cfg_space.pci_nvidia_geforce_6200 = rtl8168_csi_read(tp, PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6200); + + tp->pci_cfg_is_read = 1; + } @@ -19523,7049 +19574,9 @@ diff -rupN a/drivers/net/ethernet/realtek/r8168_n.c b/drivers/net/ethernet/realt + +module_init(rtl8168_init_module); +module_exit(rtl8168_cleanup_module); -diff -rupN a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c ---- a/drivers/net/ethernet/realtek/r8169.c 2012-10-22 15:38:20.971013133 +0300 -+++ b/drivers/net/ethernet/realtek/r8169.c 2012-10-25 11:47:00.662573148 +0300 -@@ -285,7 +285,6 @@ static DEFINE_PCI_DEVICE_TABLE(rtl8169_p - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 }, -- { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4302), 0, 0, RTL_CFG_0 }, -diff -rupN a/drivers/net/ethernet/realtek/r8169.c.orig b/drivers/net/ethernet/realtek/r8169.c.orig ---- a/drivers/net/ethernet/realtek/r8169.c.orig 1970-01-01 03:00:00.000000000 +0300 -+++ b/drivers/net/ethernet/realtek/r8169.c.orig 2012-10-12 23:50:59.000000000 +0300 -@@ -0,0 +1,7025 @@ -+/* -+ * r8169.c: RealTek 8169/8168/8101 ethernet driver. -+ * -+ * Copyright (c) 2002 ShuChen -+ * Copyright (c) 2003 - 2007 Francois Romieu -+ * Copyright (c) a lot of people too. Please respect their work. -+ * -+ * See MAINTAINERS file for support contact information. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#define RTL8169_VERSION "2.3LK-NAPI" -+#define MODULENAME "r8169" -+#define PFX MODULENAME ": " -+ -+#define FIRMWARE_8168D_1 "rtl_nic/rtl8168d-1.fw" -+#define FIRMWARE_8168D_2 "rtl_nic/rtl8168d-2.fw" -+#define FIRMWARE_8168E_1 "rtl_nic/rtl8168e-1.fw" -+#define FIRMWARE_8168E_2 "rtl_nic/rtl8168e-2.fw" -+#define FIRMWARE_8168E_3 "rtl_nic/rtl8168e-3.fw" -+#define FIRMWARE_8168F_1 "rtl_nic/rtl8168f-1.fw" -+#define FIRMWARE_8168F_2 "rtl_nic/rtl8168f-2.fw" -+#define FIRMWARE_8105E_1 "rtl_nic/rtl8105e-1.fw" -+#define FIRMWARE_8402_1 "rtl_nic/rtl8402-1.fw" -+#define FIRMWARE_8411_1 "rtl_nic/rtl8411-1.fw" -+#define FIRMWARE_8106E_1 "rtl_nic/rtl8106e-1.fw" -+#define FIRMWARE_8168G_1 "rtl_nic/rtl8168g-1.fw" -+ -+#ifdef RTL8169_DEBUG -+#define assert(expr) \ -+ if (!(expr)) { \ -+ printk( "Assertion failed! %s,%s,%s,line=%d\n", \ -+ #expr,__FILE__,__func__,__LINE__); \ -+ } -+#define dprintk(fmt, args...) \ -+ do { printk(KERN_DEBUG PFX fmt, ## args); } while (0) -+#else -+#define assert(expr) do {} while (0) -+#define dprintk(fmt, args...) do {} while (0) -+#endif /* RTL8169_DEBUG */ -+ -+#define R8169_MSG_DEFAULT \ -+ (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN) -+ -+#define TX_SLOTS_AVAIL(tp) \ -+ (tp->dirty_tx + NUM_TX_DESC - tp->cur_tx) -+ -+/* A skbuff with nr_frags needs nr_frags+1 entries in the tx queue */ -+#define TX_FRAGS_READY_FOR(tp,nr_frags) \ -+ (TX_SLOTS_AVAIL(tp) >= (nr_frags + 1)) -+ -+/* 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; -+ -+#define MAX_READ_REQUEST_SHIFT 12 -+#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -+#define SafeMtu 0x1c20 /* ... actually life sucks beyond ~7k */ -+#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ -+ -+#define R8169_REGS_SIZE 256 -+#define R8169_NAPI_WEIGHT 64 -+#define NUM_TX_DESC 64 /* Number of Tx descriptor registers */ -+#define NUM_RX_DESC 256 /* Number of Rx descriptor registers */ -+#define RX_BUF_SIZE 1536 /* Rx Buffer size */ -+#define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc)) -+#define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc)) -+ -+#define RTL8169_TX_TIMEOUT (6*HZ) -+#define RTL8169_PHY_TIMEOUT (10*HZ) -+ -+#define RTL_EEPROM_SIG cpu_to_le32(0x8129) -+#define RTL_EEPROM_SIG_MASK cpu_to_le32(0xffff) -+#define RTL_EEPROM_SIG_ADDR 0x0000 -+ -+/* write/read MMIO register */ -+#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) -+#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg)) -+#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg)) -+#define RTL_R8(reg) readb (ioaddr + (reg)) -+#define RTL_R16(reg) readw (ioaddr + (reg)) -+#define RTL_R32(reg) readl (ioaddr + (reg)) -+ -+enum mac_version { -+ RTL_GIGA_MAC_VER_01 = 0, -+ RTL_GIGA_MAC_VER_02, -+ RTL_GIGA_MAC_VER_03, -+ RTL_GIGA_MAC_VER_04, -+ RTL_GIGA_MAC_VER_05, -+ RTL_GIGA_MAC_VER_06, -+ RTL_GIGA_MAC_VER_07, -+ RTL_GIGA_MAC_VER_08, -+ RTL_GIGA_MAC_VER_09, -+ RTL_GIGA_MAC_VER_10, -+ RTL_GIGA_MAC_VER_11, -+ RTL_GIGA_MAC_VER_12, -+ RTL_GIGA_MAC_VER_13, -+ RTL_GIGA_MAC_VER_14, -+ RTL_GIGA_MAC_VER_15, -+ RTL_GIGA_MAC_VER_16, -+ RTL_GIGA_MAC_VER_17, -+ RTL_GIGA_MAC_VER_18, -+ RTL_GIGA_MAC_VER_19, -+ RTL_GIGA_MAC_VER_20, -+ RTL_GIGA_MAC_VER_21, -+ RTL_GIGA_MAC_VER_22, -+ RTL_GIGA_MAC_VER_23, -+ RTL_GIGA_MAC_VER_24, -+ RTL_GIGA_MAC_VER_25, -+ RTL_GIGA_MAC_VER_26, -+ RTL_GIGA_MAC_VER_27, -+ RTL_GIGA_MAC_VER_28, -+ RTL_GIGA_MAC_VER_29, -+ RTL_GIGA_MAC_VER_30, -+ RTL_GIGA_MAC_VER_31, -+ RTL_GIGA_MAC_VER_32, -+ RTL_GIGA_MAC_VER_33, -+ RTL_GIGA_MAC_VER_34, -+ RTL_GIGA_MAC_VER_35, -+ RTL_GIGA_MAC_VER_36, -+ RTL_GIGA_MAC_VER_37, -+ RTL_GIGA_MAC_VER_38, -+ RTL_GIGA_MAC_VER_39, -+ RTL_GIGA_MAC_VER_40, -+ RTL_GIGA_MAC_VER_41, -+ RTL_GIGA_MAC_NONE = 0xff, -+}; -+ -+enum rtl_tx_desc_version { -+ RTL_TD_0 = 0, -+ RTL_TD_1 = 1, -+}; -+ -+#define JUMBO_1K ETH_DATA_LEN -+#define JUMBO_4K (4*1024 - ETH_HLEN - 2) -+#define JUMBO_6K (6*1024 - ETH_HLEN - 2) -+#define JUMBO_7K (7*1024 - ETH_HLEN - 2) -+#define JUMBO_9K (9*1024 - ETH_HLEN - 2) -+ -+#define _R(NAME,TD,FW,SZ,B) { \ -+ .name = NAME, \ -+ .txd_version = TD, \ -+ .fw_name = FW, \ -+ .jumbo_max = SZ, \ -+ .jumbo_tx_csum = B \ -+} -+ -+static const struct { -+ const char *name; -+ enum rtl_tx_desc_version txd_version; -+ const char *fw_name; -+ u16 jumbo_max; -+ bool jumbo_tx_csum; -+} rtl_chip_infos[] = { -+ /* PCI devices. */ -+ [RTL_GIGA_MAC_VER_01] = -+ _R("RTL8169", RTL_TD_0, NULL, JUMBO_7K, true), -+ [RTL_GIGA_MAC_VER_02] = -+ _R("RTL8169s", RTL_TD_0, NULL, JUMBO_7K, true), -+ [RTL_GIGA_MAC_VER_03] = -+ _R("RTL8110s", RTL_TD_0, NULL, JUMBO_7K, true), -+ [RTL_GIGA_MAC_VER_04] = -+ _R("RTL8169sb/8110sb", RTL_TD_0, NULL, JUMBO_7K, true), -+ [RTL_GIGA_MAC_VER_05] = -+ _R("RTL8169sc/8110sc", RTL_TD_0, NULL, JUMBO_7K, true), -+ [RTL_GIGA_MAC_VER_06] = -+ _R("RTL8169sc/8110sc", RTL_TD_0, NULL, JUMBO_7K, true), -+ /* PCI-E devices. */ -+ [RTL_GIGA_MAC_VER_07] = -+ _R("RTL8102e", RTL_TD_1, NULL, JUMBO_1K, true), -+ [RTL_GIGA_MAC_VER_08] = -+ _R("RTL8102e", RTL_TD_1, NULL, JUMBO_1K, true), -+ [RTL_GIGA_MAC_VER_09] = -+ _R("RTL8102e", RTL_TD_1, NULL, JUMBO_1K, true), -+ [RTL_GIGA_MAC_VER_10] = -+ _R("RTL8101e", RTL_TD_0, NULL, JUMBO_1K, true), -+ [RTL_GIGA_MAC_VER_11] = -+ _R("RTL8168b/8111b", RTL_TD_0, NULL, JUMBO_4K, false), -+ [RTL_GIGA_MAC_VER_12] = -+ _R("RTL8168b/8111b", RTL_TD_0, NULL, JUMBO_4K, false), -+ [RTL_GIGA_MAC_VER_13] = -+ _R("RTL8101e", RTL_TD_0, NULL, JUMBO_1K, true), -+ [RTL_GIGA_MAC_VER_14] = -+ _R("RTL8100e", RTL_TD_0, NULL, JUMBO_1K, true), -+ [RTL_GIGA_MAC_VER_15] = -+ _R("RTL8100e", RTL_TD_0, NULL, JUMBO_1K, true), -+ [RTL_GIGA_MAC_VER_16] = -+ _R("RTL8101e", RTL_TD_0, NULL, JUMBO_1K, true), -+ [RTL_GIGA_MAC_VER_17] = -+ _R("RTL8168b/8111b", RTL_TD_1, NULL, JUMBO_4K, false), -+ [RTL_GIGA_MAC_VER_18] = -+ _R("RTL8168cp/8111cp", RTL_TD_1, NULL, JUMBO_6K, false), -+ [RTL_GIGA_MAC_VER_19] = -+ _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false), -+ [RTL_GIGA_MAC_VER_20] = -+ _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false), -+ [RTL_GIGA_MAC_VER_21] = -+ _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false), -+ [RTL_GIGA_MAC_VER_22] = -+ _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false), -+ [RTL_GIGA_MAC_VER_23] = -+ _R("RTL8168cp/8111cp", RTL_TD_1, NULL, JUMBO_6K, false), -+ [RTL_GIGA_MAC_VER_24] = -+ _R("RTL8168cp/8111cp", RTL_TD_1, NULL, JUMBO_6K, false), -+ [RTL_GIGA_MAC_VER_25] = -+ _R("RTL8168d/8111d", RTL_TD_1, FIRMWARE_8168D_1, -+ JUMBO_9K, false), -+ [RTL_GIGA_MAC_VER_26] = -+ _R("RTL8168d/8111d", RTL_TD_1, FIRMWARE_8168D_2, -+ JUMBO_9K, false), -+ [RTL_GIGA_MAC_VER_27] = -+ _R("RTL8168dp/8111dp", RTL_TD_1, NULL, JUMBO_9K, false), -+ [RTL_GIGA_MAC_VER_28] = -+ _R("RTL8168dp/8111dp", RTL_TD_1, NULL, JUMBO_9K, false), -+ [RTL_GIGA_MAC_VER_29] = -+ _R("RTL8105e", RTL_TD_1, FIRMWARE_8105E_1, -+ JUMBO_1K, true), -+ [RTL_GIGA_MAC_VER_30] = -+ _R("RTL8105e", RTL_TD_1, FIRMWARE_8105E_1, -+ JUMBO_1K, true), -+ [RTL_GIGA_MAC_VER_31] = -+ _R("RTL8168dp/8111dp", RTL_TD_1, NULL, JUMBO_9K, false), -+ [RTL_GIGA_MAC_VER_32] = -+ _R("RTL8168e/8111e", RTL_TD_1, FIRMWARE_8168E_1, -+ JUMBO_9K, false), -+ [RTL_GIGA_MAC_VER_33] = -+ _R("RTL8168e/8111e", RTL_TD_1, FIRMWARE_8168E_2, -+ JUMBO_9K, false), -+ [RTL_GIGA_MAC_VER_34] = -+ _R("RTL8168evl/8111evl",RTL_TD_1, FIRMWARE_8168E_3, -+ JUMBO_9K, false), -+ [RTL_GIGA_MAC_VER_35] = -+ _R("RTL8168f/8111f", RTL_TD_1, FIRMWARE_8168F_1, -+ JUMBO_9K, false), -+ [RTL_GIGA_MAC_VER_36] = -+ _R("RTL8168f/8111f", RTL_TD_1, FIRMWARE_8168F_2, -+ JUMBO_9K, false), -+ [RTL_GIGA_MAC_VER_37] = -+ _R("RTL8402", RTL_TD_1, FIRMWARE_8402_1, -+ JUMBO_1K, true), -+ [RTL_GIGA_MAC_VER_38] = -+ _R("RTL8411", RTL_TD_1, FIRMWARE_8411_1, -+ JUMBO_9K, false), -+ [RTL_GIGA_MAC_VER_39] = -+ _R("RTL8106e", RTL_TD_1, FIRMWARE_8106E_1, -+ JUMBO_1K, true), -+ [RTL_GIGA_MAC_VER_40] = -+ _R("RTL8168g/8111g", RTL_TD_1, FIRMWARE_8168G_1, -+ JUMBO_9K, false), -+ [RTL_GIGA_MAC_VER_41] = -+ _R("RTL8168g/8111g", RTL_TD_1, NULL, JUMBO_9K, false), -+}; -+#undef _R -+ -+enum cfg_version { -+ RTL_CFG_0 = 0x00, -+ RTL_CFG_1, -+ RTL_CFG_2 -+}; -+ -+static DEFINE_PCI_DEVICE_TABLE(rtl8169_pci_tbl) = { -+ { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 }, -+ { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 }, -+ { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 }, -+ { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 }, -+ { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 }, -+ { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), 0, 0, RTL_CFG_0 }, -+ { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4302), 0, 0, RTL_CFG_0 }, -+ { PCI_DEVICE(PCI_VENDOR_ID_AT, 0xc107), 0, 0, RTL_CFG_0 }, -+ { PCI_DEVICE(0x16ec, 0x0116), 0, 0, RTL_CFG_0 }, -+ { PCI_VENDOR_ID_LINKSYS, 0x1032, -+ PCI_ANY_ID, 0x0024, 0, 0, RTL_CFG_0 }, -+ { 0x0001, 0x8168, -+ PCI_ANY_ID, 0x2410, 0, 0, RTL_CFG_2 }, -+ {0,}, -+}; -+ -+MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl); -+ -+static int rx_buf_sz = 16383; -+static int use_dac; -+static struct { -+ u32 msg_enable; -+} debug = { -1 }; -+ -+enum rtl_registers { -+ MAC0 = 0, /* Ethernet hardware address. */ -+ MAC4 = 4, -+ MAR0 = 8, /* Multicast filter. */ -+ CounterAddrLow = 0x10, -+ CounterAddrHigh = 0x14, -+ TxDescStartAddrLow = 0x20, -+ TxDescStartAddrHigh = 0x24, -+ TxHDescStartAddrLow = 0x28, -+ TxHDescStartAddrHigh = 0x2c, -+ FLASH = 0x30, -+ ERSR = 0x36, -+ ChipCmd = 0x37, -+ TxPoll = 0x38, -+ IntrMask = 0x3c, -+ IntrStatus = 0x3e, -+ -+ TxConfig = 0x40, -+#define TXCFG_AUTO_FIFO (1 << 7) /* 8111e-vl */ -+#define TXCFG_EMPTY (1 << 11) /* 8111e-vl */ -+ -+ RxConfig = 0x44, -+#define RX128_INT_EN (1 << 15) /* 8111c and later */ -+#define RX_MULTI_EN (1 << 14) /* 8111c only */ -+#define RXCFG_FIFO_SHIFT 13 -+ /* No threshold before first PCI xfer */ -+#define RX_FIFO_THRESH (7 << RXCFG_FIFO_SHIFT) -+#define RXCFG_DMA_SHIFT 8 -+ /* Unlimited maximum PCI burst. */ -+#define RX_DMA_BURST (7 << RXCFG_DMA_SHIFT) -+ -+ RxMissed = 0x4c, -+ Cfg9346 = 0x50, -+ Config0 = 0x51, -+ Config1 = 0x52, -+ Config2 = 0x53, -+#define PME_SIGNAL (1 << 5) /* 8168c and later */ -+ -+ Config3 = 0x54, -+ Config4 = 0x55, -+ Config5 = 0x56, -+ MultiIntr = 0x5c, -+ PHYAR = 0x60, -+ PHYstatus = 0x6c, -+ RxMaxSize = 0xda, -+ CPlusCmd = 0xe0, -+ IntrMitigate = 0xe2, -+ RxDescAddrLow = 0xe4, -+ RxDescAddrHigh = 0xe8, -+ EarlyTxThres = 0xec, /* 8169. Unit of 32 bytes. */ -+ -+#define NoEarlyTx 0x3f /* Max value : no early transmit. */ -+ -+ MaxTxPacketSize = 0xec, /* 8101/8168. Unit of 128 bytes. */ -+ -+#define TxPacketMax (8064 >> 7) -+#define EarlySize 0x27 -+ -+ FuncEvent = 0xf0, -+ FuncEventMask = 0xf4, -+ FuncPresetState = 0xf8, -+ FuncForceEvent = 0xfc, -+}; -+ -+enum rtl8110_registers { -+ TBICSR = 0x64, -+ TBI_ANAR = 0x68, -+ TBI_LPAR = 0x6a, -+}; -+ -+enum rtl8168_8101_registers { -+ CSIDR = 0x64, -+ CSIAR = 0x68, -+#define CSIAR_FLAG 0x80000000 -+#define CSIAR_WRITE_CMD 0x80000000 -+#define CSIAR_BYTE_ENABLE 0x0f -+#define CSIAR_BYTE_ENABLE_SHIFT 12 -+#define CSIAR_ADDR_MASK 0x0fff -+#define CSIAR_FUNC_CARD 0x00000000 -+#define CSIAR_FUNC_SDIO 0x00010000 -+#define CSIAR_FUNC_NIC 0x00020000 -+ PMCH = 0x6f, -+ EPHYAR = 0x80, -+#define EPHYAR_FLAG 0x80000000 -+#define EPHYAR_WRITE_CMD 0x80000000 -+#define EPHYAR_REG_MASK 0x1f -+#define EPHYAR_REG_SHIFT 16 -+#define EPHYAR_DATA_MASK 0xffff -+ DLLPR = 0xd0, -+#define PFM_EN (1 << 6) -+ DBG_REG = 0xd1, -+#define FIX_NAK_1 (1 << 4) -+#define FIX_NAK_2 (1 << 3) -+ TWSI = 0xd2, -+ MCU = 0xd3, -+#define NOW_IS_OOB (1 << 7) -+#define TX_EMPTY (1 << 5) -+#define RX_EMPTY (1 << 4) -+#define RXTX_EMPTY (TX_EMPTY | RX_EMPTY) -+#define EN_NDP (1 << 3) -+#define EN_OOB_RESET (1 << 2) -+#define LINK_LIST_RDY (1 << 1) -+ EFUSEAR = 0xdc, -+#define EFUSEAR_FLAG 0x80000000 -+#define EFUSEAR_WRITE_CMD 0x80000000 -+#define EFUSEAR_READ_CMD 0x00000000 -+#define EFUSEAR_REG_MASK 0x03ff -+#define EFUSEAR_REG_SHIFT 8 -+#define EFUSEAR_DATA_MASK 0xff -+}; -+ -+enum rtl8168_registers { -+ LED_FREQ = 0x1a, -+ EEE_LED = 0x1b, -+ ERIDR = 0x70, -+ ERIAR = 0x74, -+#define ERIAR_FLAG 0x80000000 -+#define ERIAR_WRITE_CMD 0x80000000 -+#define ERIAR_READ_CMD 0x00000000 -+#define ERIAR_ADDR_BYTE_ALIGN 4 -+#define ERIAR_TYPE_SHIFT 16 -+#define ERIAR_EXGMAC (0x00 << ERIAR_TYPE_SHIFT) -+#define ERIAR_MSIX (0x01 << ERIAR_TYPE_SHIFT) -+#define ERIAR_ASF (0x02 << ERIAR_TYPE_SHIFT) -+#define ERIAR_MASK_SHIFT 12 -+#define ERIAR_MASK_0001 (0x1 << ERIAR_MASK_SHIFT) -+#define ERIAR_MASK_0011 (0x3 << ERIAR_MASK_SHIFT) -+#define ERIAR_MASK_0101 (0x5 << ERIAR_MASK_SHIFT) -+#define ERIAR_MASK_1111 (0xf << ERIAR_MASK_SHIFT) -+ EPHY_RXER_NUM = 0x7c, -+ OCPDR = 0xb0, /* OCP GPHY access */ -+#define OCPDR_WRITE_CMD 0x80000000 -+#define OCPDR_READ_CMD 0x00000000 -+#define OCPDR_REG_MASK 0x7f -+#define OCPDR_GPHY_REG_SHIFT 16 -+#define OCPDR_DATA_MASK 0xffff -+ OCPAR = 0xb4, -+#define OCPAR_FLAG 0x80000000 -+#define OCPAR_GPHY_WRITE_CMD 0x8000f060 -+#define OCPAR_GPHY_READ_CMD 0x0000f060 -+ GPHY_OCP = 0xb8, -+ RDSAR1 = 0xd0, /* 8168c only. Undocumented on 8168dp */ -+ MISC = 0xf0, /* 8168e only. */ -+#define TXPLA_RST (1 << 29) -+#define DISABLE_LAN_EN (1 << 23) /* Enable GPIO pin */ -+#define PWM_EN (1 << 22) -+#define RXDV_GATED_EN (1 << 19) -+#define EARLY_TALLY_EN (1 << 16) -+}; -+ -+enum rtl_register_content { -+ /* InterruptStatusBits */ -+ SYSErr = 0x8000, -+ PCSTimeout = 0x4000, -+ SWInt = 0x0100, -+ TxDescUnavail = 0x0080, -+ RxFIFOOver = 0x0040, -+ LinkChg = 0x0020, -+ RxOverflow = 0x0010, -+ TxErr = 0x0008, -+ TxOK = 0x0004, -+ RxErr = 0x0002, -+ RxOK = 0x0001, -+ -+ /* RxStatusDesc */ -+ RxBOVF = (1 << 24), -+ RxFOVF = (1 << 23), -+ RxRWT = (1 << 22), -+ RxRES = (1 << 21), -+ RxRUNT = (1 << 20), -+ RxCRC = (1 << 19), -+ -+ /* ChipCmdBits */ -+ StopReq = 0x80, -+ CmdReset = 0x10, -+ CmdRxEnb = 0x08, -+ CmdTxEnb = 0x04, -+ RxBufEmpty = 0x01, -+ -+ /* TXPoll register p.5 */ -+ HPQ = 0x80, /* Poll cmd on the high prio queue */ -+ NPQ = 0x40, /* Poll cmd on the low prio queue */ -+ FSWInt = 0x01, /* Forced software interrupt */ -+ -+ /* Cfg9346Bits */ -+ Cfg9346_Lock = 0x00, -+ Cfg9346_Unlock = 0xc0, -+ -+ /* rx_mode_bits */ -+ AcceptErr = 0x20, -+ AcceptRunt = 0x10, -+ AcceptBroadcast = 0x08, -+ AcceptMulticast = 0x04, -+ AcceptMyPhys = 0x02, -+ AcceptAllPhys = 0x01, -+#define RX_CONFIG_ACCEPT_MASK 0x3f -+ -+ /* TxConfigBits */ -+ TxInterFrameGapShift = 24, -+ TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ -+ -+ /* Config1 register p.24 */ -+ LEDS1 = (1 << 7), -+ LEDS0 = (1 << 6), -+ Speed_down = (1 << 4), -+ MEMMAP = (1 << 3), -+ IOMAP = (1 << 2), -+ VPD = (1 << 1), -+ PMEnable = (1 << 0), /* Power Management Enable */ -+ -+ /* Config2 register p. 25 */ -+ MSIEnable = (1 << 5), /* 8169 only. Reserved in the 8168. */ -+ PCI_Clock_66MHz = 0x01, -+ PCI_Clock_33MHz = 0x00, -+ -+ /* Config3 register p.25 */ -+ MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */ -+ LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */ -+ Jumbo_En0 = (1 << 2), /* 8168 only. Reserved in the 8168b */ -+ Beacon_en = (1 << 0), /* 8168 only. Reserved in the 8168b */ -+ -+ /* Config4 register */ -+ Jumbo_En1 = (1 << 1), /* 8168 only. Reserved in the 8168b */ -+ -+ /* Config5 register p.27 */ -+ BWF = (1 << 6), /* Accept Broadcast wakeup frame */ -+ MWF = (1 << 5), /* Accept Multicast wakeup frame */ -+ UWF = (1 << 4), /* Accept Unicast wakeup frame */ -+ Spi_en = (1 << 3), -+ LanWake = (1 << 1), /* LanWake enable/disable */ -+ PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */ -+ -+ /* TBICSR p.28 */ -+ TBIReset = 0x80000000, -+ TBILoopback = 0x40000000, -+ TBINwEnable = 0x20000000, -+ TBINwRestart = 0x10000000, -+ TBILinkOk = 0x02000000, -+ TBINwComplete = 0x01000000, -+ -+ /* CPlusCmd p.31 */ -+ EnableBist = (1 << 15), // 8168 8101 -+ Mac_dbgo_oe = (1 << 14), // 8168 8101 -+ Normal_mode = (1 << 13), // unused -+ Force_half_dup = (1 << 12), // 8168 8101 -+ Force_rxflow_en = (1 << 11), // 8168 8101 -+ Force_txflow_en = (1 << 10), // 8168 8101 -+ Cxpl_dbg_sel = (1 << 9), // 8168 8101 -+ ASF = (1 << 8), // 8168 8101 -+ PktCntrDisable = (1 << 7), // 8168 8101 -+ Mac_dbgo_sel = 0x001c, // 8168 -+ RxVlan = (1 << 6), -+ RxChkSum = (1 << 5), -+ PCIDAC = (1 << 4), -+ PCIMulRW = (1 << 3), -+ INTT_0 = 0x0000, // 8168 -+ INTT_1 = 0x0001, // 8168 -+ INTT_2 = 0x0002, // 8168 -+ INTT_3 = 0x0003, // 8168 -+ -+ /* rtl8169_PHYstatus */ -+ TBI_Enable = 0x80, -+ TxFlowCtrl = 0x40, -+ RxFlowCtrl = 0x20, -+ _1000bpsF = 0x10, -+ _100bps = 0x08, -+ _10bps = 0x04, -+ LinkStatus = 0x02, -+ FullDup = 0x01, -+ -+ /* _TBICSRBit */ -+ TBILinkOK = 0x02000000, -+ -+ /* DumpCounterCommand */ -+ CounterDump = 0x8, -+}; -+ -+enum rtl_desc_bit { -+ /* First doubleword. */ -+ DescOwn = (1 << 31), /* Descriptor is owned by NIC */ -+ RingEnd = (1 << 30), /* End of descriptor ring */ -+ FirstFrag = (1 << 29), /* First segment of a packet */ -+ LastFrag = (1 << 28), /* Final segment of a packet */ -+}; -+ -+/* Generic case. */ -+enum rtl_tx_desc_bit { -+ /* First doubleword. */ -+ TD_LSO = (1 << 27), /* Large Send Offload */ -+#define TD_MSS_MAX 0x07ffu /* MSS value */ -+ -+ /* Second doubleword. */ -+ TxVlanTag = (1 << 17), /* Add VLAN tag */ -+}; -+ -+/* 8169, 8168b and 810x except 8102e. */ -+enum rtl_tx_desc_bit_0 { -+ /* First doubleword. */ -+#define TD0_MSS_SHIFT 16 /* MSS position (11 bits) */ -+ TD0_TCP_CS = (1 << 16), /* Calculate TCP/IP checksum */ -+ TD0_UDP_CS = (1 << 17), /* Calculate UDP/IP checksum */ -+ TD0_IP_CS = (1 << 18), /* Calculate IP checksum */ -+}; -+ -+/* 8102e, 8168c and beyond. */ -+enum rtl_tx_desc_bit_1 { -+ /* Second doubleword. */ -+#define TD1_MSS_SHIFT 18 /* MSS position (11 bits) */ -+ TD1_IP_CS = (1 << 29), /* Calculate IP checksum */ -+ TD1_TCP_CS = (1 << 30), /* Calculate TCP/IP checksum */ -+ TD1_UDP_CS = (1 << 31), /* Calculate UDP/IP checksum */ -+}; -+ -+static const struct rtl_tx_desc_info { -+ struct { -+ u32 udp; -+ u32 tcp; -+ } checksum; -+ u16 mss_shift; -+ u16 opts_offset; -+} tx_desc_info [] = { -+ [RTL_TD_0] = { -+ .checksum = { -+ .udp = TD0_IP_CS | TD0_UDP_CS, -+ .tcp = TD0_IP_CS | TD0_TCP_CS -+ }, -+ .mss_shift = TD0_MSS_SHIFT, -+ .opts_offset = 0 -+ }, -+ [RTL_TD_1] = { -+ .checksum = { -+ .udp = TD1_IP_CS | TD1_UDP_CS, -+ .tcp = TD1_IP_CS | TD1_TCP_CS -+ }, -+ .mss_shift = TD1_MSS_SHIFT, -+ .opts_offset = 1 -+ } -+}; -+ -+enum rtl_rx_desc_bit { -+ /* Rx private */ -+ PID1 = (1 << 18), /* Protocol ID bit 1/2 */ -+ PID0 = (1 << 17), /* Protocol ID bit 2/2 */ -+ -+#define RxProtoUDP (PID1) -+#define RxProtoTCP (PID0) -+#define RxProtoIP (PID1 | PID0) -+#define RxProtoMask RxProtoIP -+ -+ IPFail = (1 << 16), /* IP checksum failed */ -+ UDPFail = (1 << 15), /* UDP/IP checksum failed */ -+ TCPFail = (1 << 14), /* TCP/IP checksum failed */ -+ RxVlanTag = (1 << 16), /* VLAN tag available */ -+}; -+ -+#define RsvdMask 0x3fffc000 -+ -+struct TxDesc { -+ __le32 opts1; -+ __le32 opts2; -+ __le64 addr; -+}; -+ -+struct RxDesc { -+ __le32 opts1; -+ __le32 opts2; -+ __le64 addr; -+}; -+ -+struct ring_info { -+ struct sk_buff *skb; -+ u32 len; -+ u8 __pad[sizeof(void *) - sizeof(u32)]; -+}; -+ -+enum features { -+ RTL_FEATURE_WOL = (1 << 0), -+ RTL_FEATURE_MSI = (1 << 1), -+ 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; -+}; -+ -+enum rtl_flag { -+ RTL_FLAG_TASK_ENABLED, -+ RTL_FLAG_TASK_SLOW_PENDING, -+ RTL_FLAG_TASK_RESET_PENDING, -+ RTL_FLAG_TASK_PHY_PENDING, -+ RTL_FLAG_MAX -+}; -+ -+struct rtl8169_stats { -+ u64 packets; -+ u64 bytes; -+ struct u64_stats_sync syncp; -+}; -+ -+struct rtl8169_private { -+ void __iomem *mmio_addr; /* memory map physical address */ -+ struct pci_dev *pci_dev; -+ struct net_device *dev; -+ struct napi_struct napi; -+ u32 msg_enable; -+ u16 txd_version; -+ u16 mac_version; -+ u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ -+ u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ -+ u32 dirty_rx; -+ u32 dirty_tx; -+ struct rtl8169_stats rx_stats; -+ struct rtl8169_stats tx_stats; -+ struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */ -+ struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ -+ dma_addr_t TxPhyAddr; -+ dma_addr_t RxPhyAddr; -+ void *Rx_databuff[NUM_RX_DESC]; /* Rx data buffers */ -+ struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */ -+ struct timer_list timer; -+ u16 cp_cmd; -+ -+ u16 event_slow; -+ -+ struct mdio_ops { -+ void (*write)(struct rtl8169_private *, int, int); -+ int (*read)(struct rtl8169_private *, int); -+ } mdio_ops; -+ -+ struct pll_power_ops { -+ void (*down)(struct rtl8169_private *); -+ void (*up)(struct rtl8169_private *); -+ } pll_power_ops; -+ -+ struct jumbo_ops { -+ void (*enable)(struct rtl8169_private *); -+ void (*disable)(struct rtl8169_private *); -+ } jumbo_ops; -+ -+ struct csi_ops { -+ void (*write)(struct rtl8169_private *, int, int); -+ u32 (*read)(struct rtl8169_private *, int); -+ } csi_ops; -+ -+ int (*set_speed)(struct net_device *, u8 aneg, u16 sp, u8 dpx, u32 adv); -+ int (*get_settings)(struct net_device *, struct ethtool_cmd *); -+ void (*phy_reset_enable)(struct rtl8169_private *tp); -+ void (*hw_start)(struct net_device *); -+ unsigned int (*phy_reset_pending)(struct rtl8169_private *tp); -+ unsigned int (*link_ok)(void __iomem *); -+ int (*do_ioctl)(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd); -+ -+ struct { -+ DECLARE_BITMAP(flags, RTL_FLAG_MAX); -+ struct mutex mutex; -+ struct work_struct work; -+ } wk; -+ -+ unsigned features; -+ -+ struct mii_if_info mii; -+ struct rtl8169_counters counters; -+ u32 saved_wolopts; -+ u32 opts1_mask; -+ -+ struct rtl_fw { -+ const struct firmware *fw; -+ -+#define RTL_VER_SIZE 32 -+ -+ char version[RTL_VER_SIZE]; -+ -+ struct rtl_fw_phy_action { -+ __le32 *code; -+ size_t size; -+ } phy_action; -+ } *rtl_fw; -+#define RTL_FIRMWARE_UNKNOWN ERR_PTR(-EAGAIN) -+ -+ u32 ocp_base; -+}; -+ -+MODULE_AUTHOR("Realtek and the Linux r8169 crew "); -+MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver"); -+module_param(use_dac, int, 0); -+MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot."); -+module_param_named(debug, debug.msg_enable, int, 0); -+MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)"); -+MODULE_LICENSE("GPL"); -+MODULE_VERSION(RTL8169_VERSION); -+MODULE_FIRMWARE(FIRMWARE_8168D_1); -+MODULE_FIRMWARE(FIRMWARE_8168D_2); -+MODULE_FIRMWARE(FIRMWARE_8168E_1); -+MODULE_FIRMWARE(FIRMWARE_8168E_2); -+MODULE_FIRMWARE(FIRMWARE_8168E_3); -+MODULE_FIRMWARE(FIRMWARE_8105E_1); -+MODULE_FIRMWARE(FIRMWARE_8168F_1); -+MODULE_FIRMWARE(FIRMWARE_8168F_2); -+MODULE_FIRMWARE(FIRMWARE_8402_1); -+MODULE_FIRMWARE(FIRMWARE_8411_1); -+MODULE_FIRMWARE(FIRMWARE_8106E_1); -+MODULE_FIRMWARE(FIRMWARE_8168G_1); -+ -+static void rtl_lock_work(struct rtl8169_private *tp) -+{ -+ mutex_lock(&tp->wk.mutex); -+} -+ -+static void rtl_unlock_work(struct rtl8169_private *tp) -+{ -+ mutex_unlock(&tp->wk.mutex); -+} -+ -+static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force) -+{ -+ int cap = pci_pcie_cap(pdev); -+ -+ if (cap) { -+ u16 ctl; -+ -+ pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl); -+ ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | force; -+ pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl); -+ } -+} -+ -+struct rtl_cond { -+ bool (*check)(struct rtl8169_private *); -+ const char *msg; -+}; -+ -+static void rtl_udelay(unsigned int d) -+{ -+ udelay(d); -+} -+ -+static bool rtl_loop_wait(struct rtl8169_private *tp, const struct rtl_cond *c, -+ void (*delay)(unsigned int), unsigned int d, int n, -+ bool high) -+{ -+ int i; -+ -+ for (i = 0; i < n; i++) { -+ delay(d); -+ if (c->check(tp) == high) -+ return true; -+ } -+ netif_err(tp, drv, tp->dev, "%s == %d (loop: %d, delay: %d).\n", -+ c->msg, !high, n, d); -+ return false; -+} -+ -+static bool rtl_udelay_loop_wait_high(struct rtl8169_private *tp, -+ const struct rtl_cond *c, -+ unsigned int d, int n) -+{ -+ return rtl_loop_wait(tp, c, rtl_udelay, d, n, true); -+} -+ -+static bool rtl_udelay_loop_wait_low(struct rtl8169_private *tp, -+ const struct rtl_cond *c, -+ unsigned int d, int n) -+{ -+ return rtl_loop_wait(tp, c, rtl_udelay, d, n, false); -+} -+ -+static bool rtl_msleep_loop_wait_high(struct rtl8169_private *tp, -+ const struct rtl_cond *c, -+ unsigned int d, int n) -+{ -+ return rtl_loop_wait(tp, c, msleep, d, n, true); -+} -+ -+static bool rtl_msleep_loop_wait_low(struct rtl8169_private *tp, -+ const struct rtl_cond *c, -+ unsigned int d, int n) -+{ -+ return rtl_loop_wait(tp, c, msleep, d, n, false); -+} -+ -+#define DECLARE_RTL_COND(name) \ -+static bool name ## _check(struct rtl8169_private *); \ -+ \ -+static const struct rtl_cond name = { \ -+ .check = name ## _check, \ -+ .msg = #name \ -+}; \ -+ \ -+static bool name ## _check(struct rtl8169_private *tp) -+ -+DECLARE_RTL_COND(rtl_ocpar_cond) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ return RTL_R32(OCPAR) & OCPAR_FLAG; -+} -+ -+static u32 ocp_read(struct rtl8169_private *tp, u8 mask, u16 reg) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ RTL_W32(OCPAR, ((u32)mask & 0x0f) << 12 | (reg & 0x0fff)); -+ -+ return rtl_udelay_loop_wait_high(tp, &rtl_ocpar_cond, 100, 20) ? -+ RTL_R32(OCPDR) : ~0; -+} -+ -+static void ocp_write(struct rtl8169_private *tp, u8 mask, u16 reg, u32 data) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ RTL_W32(OCPDR, data); -+ RTL_W32(OCPAR, OCPAR_FLAG | ((u32)mask & 0x0f) << 12 | (reg & 0x0fff)); -+ -+ rtl_udelay_loop_wait_low(tp, &rtl_ocpar_cond, 100, 20); -+} -+ -+DECLARE_RTL_COND(rtl_eriar_cond) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ return RTL_R32(ERIAR) & ERIAR_FLAG; -+} -+ -+static void rtl8168_oob_notify(struct rtl8169_private *tp, u8 cmd) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ RTL_W8(ERIDR, cmd); -+ RTL_W32(ERIAR, 0x800010e8); -+ msleep(2); -+ -+ if (!rtl_udelay_loop_wait_low(tp, &rtl_eriar_cond, 100, 5)) -+ return; -+ -+ ocp_write(tp, 0x1, 0x30, 0x00000001); -+} -+ -+#define OOB_CMD_RESET 0x00 -+#define OOB_CMD_DRIVER_START 0x05 -+#define OOB_CMD_DRIVER_STOP 0x06 -+ -+static u16 rtl8168_get_ocp_reg(struct rtl8169_private *tp) -+{ -+ return (tp->mac_version == RTL_GIGA_MAC_VER_31) ? 0xb8 : 0x10; -+} -+ -+DECLARE_RTL_COND(rtl_ocp_read_cond) -+{ -+ u16 reg; -+ -+ reg = rtl8168_get_ocp_reg(tp); -+ -+ return ocp_read(tp, 0x0f, reg) & 0x00000800; -+} -+ -+static void rtl8168_driver_start(struct rtl8169_private *tp) -+{ -+ rtl8168_oob_notify(tp, OOB_CMD_DRIVER_START); -+ -+ rtl_msleep_loop_wait_high(tp, &rtl_ocp_read_cond, 10, 10); -+} -+ -+static void rtl8168_driver_stop(struct rtl8169_private *tp) -+{ -+ rtl8168_oob_notify(tp, OOB_CMD_DRIVER_STOP); -+ -+ rtl_msleep_loop_wait_low(tp, &rtl_ocp_read_cond, 10, 10); -+} -+ -+static int r8168dp_check_dash(struct rtl8169_private *tp) -+{ -+ u16 reg = rtl8168_get_ocp_reg(tp); -+ -+ return (ocp_read(tp, 0x0f, reg) & 0x00008000) ? 1 : 0; -+} -+ -+static bool rtl_ocp_reg_failure(struct rtl8169_private *tp, u32 reg) -+{ -+ if (reg & 0xffff0001) { -+ netif_err(tp, drv, tp->dev, "Invalid ocp reg %x!\n", reg); -+ return true; -+ } -+ return false; -+} -+ -+DECLARE_RTL_COND(rtl_ocp_gphy_cond) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ return RTL_R32(GPHY_OCP) & OCPAR_FLAG; -+} -+ -+static void r8168_phy_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ if (rtl_ocp_reg_failure(tp, reg)) -+ return; -+ -+ RTL_W32(GPHY_OCP, OCPAR_FLAG | (reg << 15) | data); -+ -+ rtl_udelay_loop_wait_low(tp, &rtl_ocp_gphy_cond, 25, 10); -+} -+ -+static u16 r8168_phy_ocp_read(struct rtl8169_private *tp, u32 reg) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ if (rtl_ocp_reg_failure(tp, reg)) -+ return 0; -+ -+ RTL_W32(GPHY_OCP, reg << 15); -+ -+ return rtl_udelay_loop_wait_high(tp, &rtl_ocp_gphy_cond, 25, 10) ? -+ (RTL_R32(GPHY_OCP) & 0xffff) : ~0; -+} -+ -+static void rtl_w1w0_phy_ocp(struct rtl8169_private *tp, int reg, int p, int m) -+{ -+ int val; -+ -+ val = r8168_phy_ocp_read(tp, reg); -+ r8168_phy_ocp_write(tp, reg, (val | p) & ~m); -+} -+ -+static void r8168_mac_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ if (rtl_ocp_reg_failure(tp, reg)) -+ return; -+ -+ RTL_W32(OCPDR, OCPAR_FLAG | (reg << 15) | data); -+} -+ -+static u16 r8168_mac_ocp_read(struct rtl8169_private *tp, u32 reg) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ if (rtl_ocp_reg_failure(tp, reg)) -+ return 0; -+ -+ RTL_W32(OCPDR, reg << 15); -+ -+ return RTL_R32(OCPDR); -+} -+ -+#define OCP_STD_PHY_BASE 0xa400 -+ -+static void r8168g_mdio_write(struct rtl8169_private *tp, int reg, int value) -+{ -+ if (reg == 0x1f) { -+ tp->ocp_base = value ? value << 4 : OCP_STD_PHY_BASE; -+ return; -+ } -+ -+ if (tp->ocp_base != OCP_STD_PHY_BASE) -+ reg -= 0x10; -+ -+ r8168_phy_ocp_write(tp, tp->ocp_base + reg * 2, value); -+} -+ -+static int r8168g_mdio_read(struct rtl8169_private *tp, int reg) -+{ -+ if (tp->ocp_base != OCP_STD_PHY_BASE) -+ reg -= 0x10; -+ -+ return r8168_phy_ocp_read(tp, tp->ocp_base + reg * 2); -+} -+ -+DECLARE_RTL_COND(rtl_phyar_cond) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ return RTL_R32(PHYAR) & 0x80000000; -+} -+ -+static void r8169_mdio_write(struct rtl8169_private *tp, int reg, int value) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ RTL_W32(PHYAR, 0x80000000 | (reg & 0x1f) << 16 | (value & 0xffff)); -+ -+ rtl_udelay_loop_wait_low(tp, &rtl_phyar_cond, 25, 20); -+ /* -+ * According to hardware specs a 20us delay is required after write -+ * complete indication, but before sending next command. -+ */ -+ udelay(20); -+} -+ -+static int r8169_mdio_read(struct rtl8169_private *tp, int reg) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ int value; -+ -+ RTL_W32(PHYAR, 0x0 | (reg & 0x1f) << 16); -+ -+ value = rtl_udelay_loop_wait_high(tp, &rtl_phyar_cond, 25, 20) ? -+ RTL_R32(PHYAR) & 0xffff : ~0; -+ -+ /* -+ * According to hardware specs a 20us delay is required after read -+ * complete indication, but before sending next command. -+ */ -+ udelay(20); -+ -+ return value; -+} -+ -+static void r8168dp_1_mdio_access(struct rtl8169_private *tp, int reg, u32 data) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ RTL_W32(OCPDR, data | ((reg & OCPDR_REG_MASK) << OCPDR_GPHY_REG_SHIFT)); -+ RTL_W32(OCPAR, OCPAR_GPHY_WRITE_CMD); -+ RTL_W32(EPHY_RXER_NUM, 0); -+ -+ rtl_udelay_loop_wait_low(tp, &rtl_ocpar_cond, 1000, 100); -+} -+ -+static void r8168dp_1_mdio_write(struct rtl8169_private *tp, int reg, int value) -+{ -+ r8168dp_1_mdio_access(tp, reg, -+ OCPDR_WRITE_CMD | (value & OCPDR_DATA_MASK)); -+} -+ -+static int r8168dp_1_mdio_read(struct rtl8169_private *tp, int reg) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ r8168dp_1_mdio_access(tp, reg, OCPDR_READ_CMD); -+ -+ mdelay(1); -+ RTL_W32(OCPAR, OCPAR_GPHY_READ_CMD); -+ RTL_W32(EPHY_RXER_NUM, 0); -+ -+ return rtl_udelay_loop_wait_high(tp, &rtl_ocpar_cond, 1000, 100) ? -+ RTL_R32(OCPDR) & OCPDR_DATA_MASK : ~0; -+} -+ -+#define R8168DP_1_MDIO_ACCESS_BIT 0x00020000 -+ -+static void r8168dp_2_mdio_start(void __iomem *ioaddr) -+{ -+ RTL_W32(0xd0, RTL_R32(0xd0) & ~R8168DP_1_MDIO_ACCESS_BIT); -+} -+ -+static void r8168dp_2_mdio_stop(void __iomem *ioaddr) -+{ -+ RTL_W32(0xd0, RTL_R32(0xd0) | R8168DP_1_MDIO_ACCESS_BIT); -+} -+ -+static void r8168dp_2_mdio_write(struct rtl8169_private *tp, int reg, int value) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ r8168dp_2_mdio_start(ioaddr); -+ -+ r8169_mdio_write(tp, reg, value); -+ -+ r8168dp_2_mdio_stop(ioaddr); -+} -+ -+static int r8168dp_2_mdio_read(struct rtl8169_private *tp, int reg) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ int value; -+ -+ r8168dp_2_mdio_start(ioaddr); -+ -+ value = r8169_mdio_read(tp, reg); -+ -+ r8168dp_2_mdio_stop(ioaddr); -+ -+ return value; -+} -+ -+static void rtl_writephy(struct rtl8169_private *tp, int location, u32 val) -+{ -+ tp->mdio_ops.write(tp, location, val); -+} -+ -+static int rtl_readphy(struct rtl8169_private *tp, int location) -+{ -+ return tp->mdio_ops.read(tp, location); -+} -+ -+static void rtl_patchphy(struct rtl8169_private *tp, int reg_addr, int value) -+{ -+ rtl_writephy(tp, reg_addr, rtl_readphy(tp, reg_addr) | value); -+} -+ -+static void rtl_w1w0_phy(struct rtl8169_private *tp, int reg_addr, int p, int m) -+{ -+ int val; -+ -+ val = rtl_readphy(tp, reg_addr); -+ rtl_writephy(tp, reg_addr, (val | p) & ~m); -+} -+ -+static void rtl_mdio_write(struct net_device *dev, int phy_id, int location, -+ int val) -+{ -+ struct rtl8169_private *tp = netdev_priv(dev); -+ -+ rtl_writephy(tp, location, val); -+} -+ -+static int rtl_mdio_read(struct net_device *dev, int phy_id, int location) -+{ -+ struct rtl8169_private *tp = netdev_priv(dev); -+ -+ return rtl_readphy(tp, location); -+} -+ -+DECLARE_RTL_COND(rtl_ephyar_cond) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ return RTL_R32(EPHYAR) & EPHYAR_FLAG; -+} -+ -+static void rtl_ephy_write(struct rtl8169_private *tp, int reg_addr, int value) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ RTL_W32(EPHYAR, EPHYAR_WRITE_CMD | (value & EPHYAR_DATA_MASK) | -+ (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); -+ -+ rtl_udelay_loop_wait_low(tp, &rtl_ephyar_cond, 10, 100); -+ -+ udelay(10); -+} -+ -+static u16 rtl_ephy_read(struct rtl8169_private *tp, int reg_addr) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ RTL_W32(EPHYAR, (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); -+ -+ return rtl_udelay_loop_wait_high(tp, &rtl_ephyar_cond, 10, 100) ? -+ RTL_R32(EPHYAR) & EPHYAR_DATA_MASK : ~0; -+} -+ -+static void rtl_eri_write(struct rtl8169_private *tp, int addr, u32 mask, -+ u32 val, int type) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ BUG_ON((addr & 3) || (mask == 0)); -+ RTL_W32(ERIDR, val); -+ RTL_W32(ERIAR, ERIAR_WRITE_CMD | type | mask | addr); -+ -+ rtl_udelay_loop_wait_low(tp, &rtl_eriar_cond, 100, 100); -+} -+ -+static u32 rtl_eri_read(struct rtl8169_private *tp, int addr, int type) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ RTL_W32(ERIAR, ERIAR_READ_CMD | type | ERIAR_MASK_1111 | addr); -+ -+ return rtl_udelay_loop_wait_high(tp, &rtl_eriar_cond, 100, 100) ? -+ RTL_R32(ERIDR) : ~0; -+} -+ -+static void rtl_w1w0_eri(struct rtl8169_private *tp, int addr, u32 mask, u32 p, -+ u32 m, int type) -+{ -+ u32 val; -+ -+ val = rtl_eri_read(tp, addr, type); -+ rtl_eri_write(tp, addr, mask, (val & ~m) | p, type); -+} -+ -+struct exgmac_reg { -+ u16 addr; -+ u16 mask; -+ u32 val; -+}; -+ -+static void rtl_write_exgmac_batch(struct rtl8169_private *tp, -+ const struct exgmac_reg *r, int len) -+{ -+ while (len-- > 0) { -+ rtl_eri_write(tp, r->addr, r->mask, r->val, ERIAR_EXGMAC); -+ r++; -+ } -+} -+ -+DECLARE_RTL_COND(rtl_efusear_cond) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ return RTL_R32(EFUSEAR) & EFUSEAR_FLAG; -+} -+ -+static u8 rtl8168d_efuse_read(struct rtl8169_private *tp, int reg_addr) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ RTL_W32(EFUSEAR, (reg_addr & EFUSEAR_REG_MASK) << EFUSEAR_REG_SHIFT); -+ -+ return rtl_udelay_loop_wait_high(tp, &rtl_efusear_cond, 100, 300) ? -+ RTL_R32(EFUSEAR) & EFUSEAR_DATA_MASK : ~0; -+} -+ -+static u16 rtl_get_events(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ return RTL_R16(IntrStatus); -+} -+ -+static void rtl_ack_events(struct rtl8169_private *tp, u16 bits) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ RTL_W16(IntrStatus, bits); -+ mmiowb(); -+} -+ -+static void rtl_irq_disable(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ RTL_W16(IntrMask, 0); -+ mmiowb(); -+} -+ -+static void rtl_irq_enable(struct rtl8169_private *tp, u16 bits) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ RTL_W16(IntrMask, bits); -+} -+ -+#define RTL_EVENT_NAPI_RX (RxOK | RxErr) -+#define RTL_EVENT_NAPI_TX (TxOK | TxErr) -+#define RTL_EVENT_NAPI (RTL_EVENT_NAPI_RX | RTL_EVENT_NAPI_TX) -+ -+static void rtl_irq_enable_all(struct rtl8169_private *tp) -+{ -+ rtl_irq_enable(tp, RTL_EVENT_NAPI | tp->event_slow); -+} -+ -+static void rtl8169_irq_mask_and_ack(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ rtl_irq_disable(tp); -+ rtl_ack_events(tp, RTL_EVENT_NAPI | tp->event_slow); -+ RTL_R8(ChipCmd); -+} -+ -+static unsigned int rtl8169_tbi_reset_pending(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ return RTL_R32(TBICSR) & TBIReset; -+} -+ -+static unsigned int rtl8169_xmii_reset_pending(struct rtl8169_private *tp) -+{ -+ return rtl_readphy(tp, MII_BMCR) & BMCR_RESET; -+} -+ -+static unsigned int rtl8169_tbi_link_ok(void __iomem *ioaddr) -+{ -+ return RTL_R32(TBICSR) & TBILinkOk; -+} -+ -+static unsigned int rtl8169_xmii_link_ok(void __iomem *ioaddr) -+{ -+ return RTL_R8(PHYstatus) & LinkStatus; -+} -+ -+static void rtl8169_tbi_reset_enable(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ RTL_W32(TBICSR, RTL_R32(TBICSR) | TBIReset); -+} -+ -+static void rtl8169_xmii_reset_enable(struct rtl8169_private *tp) -+{ -+ unsigned int val; -+ -+ val = rtl_readphy(tp, MII_BMCR) | BMCR_RESET; -+ rtl_writephy(tp, MII_BMCR, val & 0xffff); -+} -+ -+static void rtl_link_chg_patch(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ struct net_device *dev = tp->dev; -+ -+ if (!netif_running(dev)) -+ return; -+ -+ if (tp->mac_version == RTL_GIGA_MAC_VER_34 || -+ tp->mac_version == RTL_GIGA_MAC_VER_38) { -+ if (RTL_R8(PHYstatus) & _1000bpsF) { -+ rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x00000011, -+ ERIAR_EXGMAC); -+ rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005, -+ ERIAR_EXGMAC); -+ } else if (RTL_R8(PHYstatus) & _100bps) { -+ rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f, -+ ERIAR_EXGMAC); -+ rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005, -+ ERIAR_EXGMAC); -+ } else { -+ rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f, -+ ERIAR_EXGMAC); -+ rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x0000003f, -+ ERIAR_EXGMAC); -+ } -+ /* Reset packet filter */ -+ rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, -+ ERIAR_EXGMAC); -+ rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, -+ ERIAR_EXGMAC); -+ } else if (tp->mac_version == RTL_GIGA_MAC_VER_35 || -+ tp->mac_version == RTL_GIGA_MAC_VER_36) { -+ if (RTL_R8(PHYstatus) & _1000bpsF) { -+ rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x00000011, -+ ERIAR_EXGMAC); -+ rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005, -+ ERIAR_EXGMAC); -+ } else { -+ rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f, -+ ERIAR_EXGMAC); -+ rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x0000003f, -+ ERIAR_EXGMAC); -+ } -+ } else if (tp->mac_version == RTL_GIGA_MAC_VER_37) { -+ if (RTL_R8(PHYstatus) & _10bps) { -+ rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x4d02, -+ ERIAR_EXGMAC); -+ rtl_eri_write(tp, 0x1dc, ERIAR_MASK_0011, 0x0060, -+ ERIAR_EXGMAC); -+ } else { -+ rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x0000, -+ ERIAR_EXGMAC); -+ } -+ } -+} -+ -+static void __rtl8169_check_link_status(struct net_device *dev, -+ struct rtl8169_private *tp, -+ void __iomem *ioaddr, bool pm) -+{ -+ if (tp->link_ok(ioaddr)) { -+ rtl_link_chg_patch(tp); -+ /* This is to cancel a scheduled suspend if there's one. */ -+ if (pm) -+ pm_request_resume(&tp->pci_dev->dev); -+ netif_carrier_on(dev); -+ if (net_ratelimit()) -+ netif_info(tp, ifup, dev, "link up\n"); -+ } else { -+ netif_carrier_off(dev); -+ netif_info(tp, ifdown, dev, "link down\n"); -+ if (pm) -+ pm_schedule_suspend(&tp->pci_dev->dev, 5000); -+ } -+} -+ -+static void rtl8169_check_link_status(struct net_device *dev, -+ struct rtl8169_private *tp, -+ void __iomem *ioaddr) -+{ -+ __rtl8169_check_link_status(dev, tp, ioaddr, false); -+} -+ -+#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST) -+ -+static u32 __rtl8169_get_wol(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ u8 options; -+ u32 wolopts = 0; -+ -+ options = RTL_R8(Config1); -+ if (!(options & PMEnable)) -+ return 0; -+ -+ options = RTL_R8(Config3); -+ if (options & LinkUp) -+ wolopts |= WAKE_PHY; -+ if (options & MagicPacket) -+ wolopts |= WAKE_MAGIC; -+ -+ options = RTL_R8(Config5); -+ if (options & UWF) -+ wolopts |= WAKE_UCAST; -+ if (options & BWF) -+ wolopts |= WAKE_BCAST; -+ if (options & MWF) -+ wolopts |= WAKE_MCAST; -+ -+ return wolopts; -+} -+ -+static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -+{ -+ struct rtl8169_private *tp = netdev_priv(dev); -+ -+ rtl_lock_work(tp); -+ -+ wol->supported = WAKE_ANY; -+ wol->wolopts = __rtl8169_get_wol(tp); -+ -+ rtl_unlock_work(tp); -+} -+ -+static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ unsigned int i; -+ static const struct { -+ u32 opt; -+ u16 reg; -+ u8 mask; -+ } cfg[] = { -+ { WAKE_PHY, Config3, LinkUp }, -+ { WAKE_MAGIC, Config3, MagicPacket }, -+ { WAKE_UCAST, Config5, UWF }, -+ { WAKE_BCAST, Config5, BWF }, -+ { WAKE_MCAST, Config5, MWF }, -+ { WAKE_ANY, Config5, LanWake } -+ }; -+ u8 options; -+ -+ RTL_W8(Cfg9346, Cfg9346_Unlock); -+ -+ for (i = 0; i < ARRAY_SIZE(cfg); i++) { -+ options = RTL_R8(cfg[i].reg) & ~cfg[i].mask; -+ if (wolopts & cfg[i].opt) -+ options |= cfg[i].mask; -+ RTL_W8(cfg[i].reg, options); -+ } -+ -+ switch (tp->mac_version) { -+ case RTL_GIGA_MAC_VER_01 ... RTL_GIGA_MAC_VER_17: -+ options = RTL_R8(Config1) & ~PMEnable; -+ if (wolopts) -+ options |= PMEnable; -+ RTL_W8(Config1, options); -+ break; -+ default: -+ options = RTL_R8(Config2) & ~PME_SIGNAL; -+ if (wolopts) -+ options |= PME_SIGNAL; -+ RTL_W8(Config2, options); -+ break; -+ } -+ -+ RTL_W8(Cfg9346, Cfg9346_Lock); -+} -+ -+static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -+{ -+ struct rtl8169_private *tp = netdev_priv(dev); -+ -+ rtl_lock_work(tp); -+ -+ if (wol->wolopts) -+ tp->features |= RTL_FEATURE_WOL; -+ else -+ tp->features &= ~RTL_FEATURE_WOL; -+ __rtl8169_set_wol(tp, wol->wolopts); -+ -+ rtl_unlock_work(tp); -+ -+ device_set_wakeup_enable(&tp->pci_dev->dev, wol->wolopts); -+ -+ return 0; -+} -+ -+static const char *rtl_lookup_firmware_name(struct rtl8169_private *tp) -+{ -+ return rtl_chip_infos[tp->mac_version].fw_name; -+} -+ -+static void rtl8169_get_drvinfo(struct net_device *dev, -+ struct ethtool_drvinfo *info) -+{ -+ struct rtl8169_private *tp = netdev_priv(dev); -+ struct rtl_fw *rtl_fw = tp->rtl_fw; -+ -+ strlcpy(info->driver, MODULENAME, sizeof(info->driver)); -+ strlcpy(info->version, RTL8169_VERSION, sizeof(info->version)); -+ strlcpy(info->bus_info, pci_name(tp->pci_dev), sizeof(info->bus_info)); -+ BUILD_BUG_ON(sizeof(info->fw_version) < sizeof(rtl_fw->version)); -+ if (!IS_ERR_OR_NULL(rtl_fw)) -+ strlcpy(info->fw_version, rtl_fw->version, -+ sizeof(info->fw_version)); -+} -+ -+static int rtl8169_get_regs_len(struct net_device *dev) -+{ -+ return R8169_REGS_SIZE; -+} -+ -+static int rtl8169_set_speed_tbi(struct net_device *dev, -+ u8 autoneg, u16 speed, u8 duplex, u32 ignored) -+{ -+ struct rtl8169_private *tp = netdev_priv(dev); -+ void __iomem *ioaddr = tp->mmio_addr; -+ int ret = 0; -+ u32 reg; -+ -+ reg = RTL_R32(TBICSR); -+ if ((autoneg == AUTONEG_DISABLE) && (speed == SPEED_1000) && -+ (duplex == DUPLEX_FULL)) { -+ RTL_W32(TBICSR, reg & ~(TBINwEnable | TBINwRestart)); -+ } else if (autoneg == AUTONEG_ENABLE) -+ RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart); -+ else { -+ netif_warn(tp, link, dev, -+ "incorrect speed setting refused in TBI mode\n"); -+ ret = -EOPNOTSUPP; -+ } -+ -+ return ret; -+} -+ -+static int rtl8169_set_speed_xmii(struct net_device *dev, -+ u8 autoneg, u16 speed, u8 duplex, u32 adv) -+{ -+ struct rtl8169_private *tp = netdev_priv(dev); -+ int giga_ctrl, bmcr; -+ int rc = -EINVAL; -+ -+ rtl_writephy(tp, 0x1f, 0x0000); -+ -+ if (autoneg == AUTONEG_ENABLE) { -+ int auto_nego; -+ -+ auto_nego = rtl_readphy(tp, MII_ADVERTISE); -+ auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL | -+ ADVERTISE_100HALF | ADVERTISE_100FULL); -+ -+ if (adv & ADVERTISED_10baseT_Half) -+ auto_nego |= ADVERTISE_10HALF; -+ if (adv & ADVERTISED_10baseT_Full) -+ auto_nego |= ADVERTISE_10FULL; -+ if (adv & ADVERTISED_100baseT_Half) -+ auto_nego |= ADVERTISE_100HALF; -+ if (adv & ADVERTISED_100baseT_Full) -+ auto_nego |= ADVERTISE_100FULL; -+ -+ auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; -+ -+ giga_ctrl = rtl_readphy(tp, MII_CTRL1000); -+ giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); -+ -+ /* The 8100e/8101e/8102e do Fast Ethernet only. */ -+ if (tp->mii.supports_gmii) { -+ if (adv & ADVERTISED_1000baseT_Half) -+ giga_ctrl |= ADVERTISE_1000HALF; -+ if (adv & ADVERTISED_1000baseT_Full) -+ giga_ctrl |= ADVERTISE_1000FULL; -+ } else if (adv & (ADVERTISED_1000baseT_Half | -+ ADVERTISED_1000baseT_Full)) { -+ netif_info(tp, link, dev, -+ "PHY does not support 1000Mbps\n"); -+ goto out; -+ } -+ -+ bmcr = BMCR_ANENABLE | BMCR_ANRESTART; -+ -+ rtl_writephy(tp, MII_ADVERTISE, auto_nego); -+ rtl_writephy(tp, MII_CTRL1000, giga_ctrl); -+ } else { -+ giga_ctrl = 0; -+ -+ if (speed == SPEED_10) -+ bmcr = 0; -+ else if (speed == SPEED_100) -+ bmcr = BMCR_SPEED100; -+ else -+ goto out; -+ -+ if (duplex == DUPLEX_FULL) -+ bmcr |= BMCR_FULLDPLX; -+ } -+ -+ rtl_writephy(tp, 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)) { -+ rtl_writephy(tp, 0x17, 0x2138); -+ rtl_writephy(tp, 0x0e, 0x0260); -+ } else { -+ rtl_writephy(tp, 0x17, 0x2108); -+ rtl_writephy(tp, 0x0e, 0x0000); -+ } -+ } -+ -+ rc = 0; -+out: -+ return rc; -+} -+ -+static int rtl8169_set_speed(struct net_device *dev, -+ u8 autoneg, u16 speed, u8 duplex, u32 advertising) -+{ -+ struct rtl8169_private *tp = netdev_priv(dev); -+ int ret; -+ -+ ret = tp->set_speed(dev, autoneg, speed, duplex, advertising); -+ if (ret < 0) -+ goto out; -+ -+ if (netif_running(dev) && (autoneg == AUTONEG_ENABLE) && -+ (advertising & ADVERTISED_1000baseT_Full)) { -+ mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT); -+ } -+out: -+ return ret; -+} -+ -+static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -+{ -+ struct rtl8169_private *tp = netdev_priv(dev); -+ int ret; -+ -+ del_timer_sync(&tp->timer); -+ -+ rtl_lock_work(tp); -+ ret = rtl8169_set_speed(dev, cmd->autoneg, ethtool_cmd_speed(cmd), -+ cmd->duplex, cmd->advertising); -+ rtl_unlock_work(tp); -+ -+ return ret; -+} -+ -+static netdev_features_t rtl8169_fix_features(struct net_device *dev, -+ netdev_features_t features) -+{ -+ struct rtl8169_private *tp = netdev_priv(dev); -+ -+ if (dev->mtu > TD_MSS_MAX) -+ features &= ~NETIF_F_ALL_TSO; -+ -+ if (dev->mtu > JUMBO_1K && -+ !rtl_chip_infos[tp->mac_version].jumbo_tx_csum) -+ features &= ~NETIF_F_IP_CSUM; -+ -+ return features; -+} -+ -+static void __rtl8169_set_features(struct net_device *dev, -+ netdev_features_t features) -+{ -+ struct rtl8169_private *tp = netdev_priv(dev); -+ netdev_features_t changed = features ^ dev->features; -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ if (!(changed & (NETIF_F_RXALL | NETIF_F_RXCSUM | NETIF_F_HW_VLAN_RX))) -+ return; -+ -+ if (changed & (NETIF_F_RXCSUM | NETIF_F_HW_VLAN_RX)) { -+ if (features & NETIF_F_RXCSUM) -+ tp->cp_cmd |= RxChkSum; -+ else -+ tp->cp_cmd &= ~RxChkSum; -+ -+ if (dev->features & NETIF_F_HW_VLAN_RX) -+ tp->cp_cmd |= RxVlan; -+ else -+ tp->cp_cmd &= ~RxVlan; -+ -+ RTL_W16(CPlusCmd, tp->cp_cmd); -+ RTL_R16(CPlusCmd); -+ } -+ if (changed & NETIF_F_RXALL) { -+ int tmp = (RTL_R32(RxConfig) & ~(AcceptErr | AcceptRunt)); -+ if (features & NETIF_F_RXALL) -+ tmp |= (AcceptErr | AcceptRunt); -+ RTL_W32(RxConfig, tmp); -+ } -+} -+ -+static int rtl8169_set_features(struct net_device *dev, -+ netdev_features_t features) -+{ -+ struct rtl8169_private *tp = netdev_priv(dev); -+ -+ rtl_lock_work(tp); -+ __rtl8169_set_features(dev, features); -+ rtl_unlock_work(tp); -+ -+ return 0; -+} -+ -+ -+static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, -+ struct sk_buff *skb) -+{ -+ return (vlan_tx_tag_present(skb)) ? -+ TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00; -+} -+ -+static void rtl8169_rx_vlan_tag(struct RxDesc *desc, struct sk_buff *skb) -+{ -+ u32 opts2 = le32_to_cpu(desc->opts2); -+ -+ if (opts2 & RxVlanTag) -+ __vlan_hwaccel_put_tag(skb, swab16(opts2 & 0xffff)); -+ -+ desc->opts2 = 0; -+} -+ -+static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) -+{ -+ struct rtl8169_private *tp = netdev_priv(dev); -+ void __iomem *ioaddr = tp->mmio_addr; -+ u32 status; -+ -+ cmd->supported = -+ SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE; -+ cmd->port = PORT_FIBRE; -+ cmd->transceiver = XCVR_INTERNAL; -+ -+ status = RTL_R32(TBICSR); -+ cmd->advertising = (status & TBINwEnable) ? ADVERTISED_Autoneg : 0; -+ cmd->autoneg = !!(status & TBINwEnable); -+ -+ ethtool_cmd_speed_set(cmd, SPEED_1000); -+ cmd->duplex = DUPLEX_FULL; /* Always set */ -+ -+ return 0; -+} -+ -+static int rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd) -+{ -+ struct rtl8169_private *tp = netdev_priv(dev); -+ -+ return mii_ethtool_gset(&tp->mii, cmd); -+} -+ -+static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -+{ -+ struct rtl8169_private *tp = netdev_priv(dev); -+ int rc; -+ -+ rtl_lock_work(tp); -+ rc = tp->get_settings(dev, cmd); -+ rtl_unlock_work(tp); -+ -+ return rc; -+} -+ -+static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs, -+ void *p) -+{ -+ struct rtl8169_private *tp = netdev_priv(dev); -+ -+ if (regs->len > R8169_REGS_SIZE) -+ regs->len = R8169_REGS_SIZE; -+ -+ rtl_lock_work(tp); -+ memcpy_fromio(p, tp->mmio_addr, regs->len); -+ rtl_unlock_work(tp); -+} -+ -+static u32 rtl8169_get_msglevel(struct net_device *dev) -+{ -+ struct rtl8169_private *tp = netdev_priv(dev); -+ -+ return tp->msg_enable; -+} -+ -+static void rtl8169_set_msglevel(struct net_device *dev, u32 value) -+{ -+ struct rtl8169_private *tp = netdev_priv(dev); -+ -+ tp->msg_enable = value; -+} -+ -+static const char rtl8169_gstrings[][ETH_GSTRING_LEN] = { -+ "tx_packets", -+ "rx_packets", -+ "tx_errors", -+ "rx_errors", -+ "rx_missed", -+ "align_errors", -+ "tx_single_collisions", -+ "tx_multi_collisions", -+ "unicast", -+ "broadcast", -+ "multicast", -+ "tx_aborted", -+ "tx_underrun", -+}; -+ -+static int rtl8169_get_sset_count(struct net_device *dev, int sset) -+{ -+ switch (sset) { -+ case ETH_SS_STATS: -+ return ARRAY_SIZE(rtl8169_gstrings); -+ default: -+ return -EOPNOTSUPP; -+ } -+} -+ -+DECLARE_RTL_COND(rtl_counters_cond) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ return RTL_R32(CounterAddrLow) & CounterDump; -+} -+ -+static void rtl8169_update_counters(struct net_device *dev) -+{ -+ struct rtl8169_private *tp = netdev_priv(dev); -+ void __iomem *ioaddr = tp->mmio_addr; -+ struct device *d = &tp->pci_dev->dev; -+ struct rtl8169_counters *counters; -+ dma_addr_t paddr; -+ u32 cmd; -+ -+ /* -+ * Some chips are unable to dump tally counters when the receiver -+ * is disabled. -+ */ -+ if ((RTL_R8(ChipCmd) & CmdRxEnb) == 0) -+ return; -+ -+ counters = dma_alloc_coherent(d, sizeof(*counters), &paddr, GFP_KERNEL); -+ if (!counters) -+ return; -+ -+ RTL_W32(CounterAddrHigh, (u64)paddr >> 32); -+ cmd = (u64)paddr & DMA_BIT_MASK(32); -+ RTL_W32(CounterAddrLow, cmd); -+ RTL_W32(CounterAddrLow, cmd | CounterDump); -+ -+ if (rtl_udelay_loop_wait_low(tp, &rtl_counters_cond, 10, 1000)) -+ memcpy(&tp->counters, counters, sizeof(*counters)); -+ -+ RTL_W32(CounterAddrLow, 0); -+ RTL_W32(CounterAddrHigh, 0); -+ -+ dma_free_coherent(d, 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) { -+ case ETH_SS_STATS: -+ memcpy(data, *rtl8169_gstrings, sizeof(rtl8169_gstrings)); -+ break; -+ } -+} -+ -+static const struct ethtool_ops rtl8169_ethtool_ops = { -+ .get_drvinfo = rtl8169_get_drvinfo, -+ .get_regs_len = rtl8169_get_regs_len, -+ .get_link = ethtool_op_get_link, -+ .get_settings = rtl8169_get_settings, -+ .set_settings = rtl8169_set_settings, -+ .get_msglevel = rtl8169_get_msglevel, -+ .set_msglevel = rtl8169_set_msglevel, -+ .get_regs = rtl8169_get_regs, -+ .get_wol = rtl8169_get_wol, -+ .set_wol = rtl8169_set_wol, -+ .get_strings = rtl8169_get_strings, -+ .get_sset_count = rtl8169_get_sset_count, -+ .get_ethtool_stats = rtl8169_get_ethtool_stats, -+ .get_ts_info = ethtool_op_get_ts_info, -+}; -+ -+static void rtl8169_get_mac_version(struct rtl8169_private *tp, -+ struct net_device *dev, u8 default_version) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ /* -+ * The driver currently handles the 8168Bf and the 8168Be identically -+ * but they can be identified more specifically through the test below -+ * if needed: -+ * -+ * (RTL_R32(TxConfig) & 0x700000) == 0x500000 ? 8168Bf : 8168Be -+ * -+ * Same thing for the 8101Eb and the 8101Ec: -+ * -+ * (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec -+ */ -+ static const struct rtl_mac_info { -+ u32 mask; -+ u32 val; -+ int mac_version; -+ } mac_info[] = { -+ /* 8168G family. */ -+ { 0x7cf00000, 0x4c100000, RTL_GIGA_MAC_VER_41 }, -+ { 0x7cf00000, 0x4c000000, RTL_GIGA_MAC_VER_40 }, -+ -+ /* 8168F family. */ -+ { 0x7c800000, 0x48800000, RTL_GIGA_MAC_VER_38 }, -+ { 0x7cf00000, 0x48100000, RTL_GIGA_MAC_VER_36 }, -+ { 0x7cf00000, 0x48000000, RTL_GIGA_MAC_VER_35 }, -+ -+ /* 8168E family. */ -+ { 0x7c800000, 0x2c800000, RTL_GIGA_MAC_VER_34 }, -+ { 0x7cf00000, 0x2c200000, RTL_GIGA_MAC_VER_33 }, -+ { 0x7cf00000, 0x2c100000, RTL_GIGA_MAC_VER_32 }, -+ { 0x7c800000, 0x2c000000, RTL_GIGA_MAC_VER_33 }, -+ -+ /* 8168D family. */ -+ { 0x7cf00000, 0x28300000, RTL_GIGA_MAC_VER_26 }, -+ { 0x7cf00000, 0x28100000, RTL_GIGA_MAC_VER_25 }, -+ { 0x7c800000, 0x28000000, RTL_GIGA_MAC_VER_26 }, -+ -+ /* 8168DP family. */ -+ { 0x7cf00000, 0x28800000, RTL_GIGA_MAC_VER_27 }, -+ { 0x7cf00000, 0x28a00000, RTL_GIGA_MAC_VER_28 }, -+ { 0x7cf00000, 0x28b00000, RTL_GIGA_MAC_VER_31 }, -+ -+ /* 8168C family. */ -+ { 0x7cf00000, 0x3cb00000, 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 }, -+ { 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 }, -+ { 0x7cf00000, 0x38500000, RTL_GIGA_MAC_VER_17 }, -+ { 0x7c800000, 0x38000000, RTL_GIGA_MAC_VER_17 }, -+ { 0x7c800000, 0x30000000, RTL_GIGA_MAC_VER_11 }, -+ -+ /* 8101 family. */ -+ { 0x7cf00000, 0x44900000, RTL_GIGA_MAC_VER_39 }, -+ { 0x7c800000, 0x44800000, RTL_GIGA_MAC_VER_39 }, -+ { 0x7c800000, 0x44000000, RTL_GIGA_MAC_VER_37 }, -+ { 0x7cf00000, 0x40b00000, RTL_GIGA_MAC_VER_30 }, -+ { 0x7cf00000, 0x40a00000, RTL_GIGA_MAC_VER_30 }, -+ { 0x7cf00000, 0x40900000, RTL_GIGA_MAC_VER_29 }, -+ { 0x7c800000, 0x40800000, RTL_GIGA_MAC_VER_30 }, -+ { 0x7cf00000, 0x34a00000, RTL_GIGA_MAC_VER_09 }, -+ { 0x7cf00000, 0x24a00000, RTL_GIGA_MAC_VER_09 }, -+ { 0x7cf00000, 0x34900000, RTL_GIGA_MAC_VER_08 }, -+ { 0x7cf00000, 0x24900000, RTL_GIGA_MAC_VER_08 }, -+ { 0x7cf00000, 0x34800000, RTL_GIGA_MAC_VER_07 }, -+ { 0x7cf00000, 0x24800000, RTL_GIGA_MAC_VER_07 }, -+ { 0x7cf00000, 0x34000000, RTL_GIGA_MAC_VER_13 }, -+ { 0x7cf00000, 0x34300000, RTL_GIGA_MAC_VER_10 }, -+ { 0x7cf00000, 0x34200000, RTL_GIGA_MAC_VER_16 }, -+ { 0x7c800000, 0x34800000, RTL_GIGA_MAC_VER_09 }, -+ { 0x7c800000, 0x24800000, RTL_GIGA_MAC_VER_09 }, -+ { 0x7c800000, 0x34000000, RTL_GIGA_MAC_VER_16 }, -+ /* FIXME: where did these entries come from ? -- FR */ -+ { 0xfc800000, 0x38800000, RTL_GIGA_MAC_VER_15 }, -+ { 0xfc800000, 0x30800000, RTL_GIGA_MAC_VER_14 }, -+ -+ /* 8110 family. */ -+ { 0xfc800000, 0x98000000, RTL_GIGA_MAC_VER_06 }, -+ { 0xfc800000, 0x18000000, RTL_GIGA_MAC_VER_05 }, -+ { 0xfc800000, 0x10000000, RTL_GIGA_MAC_VER_04 }, -+ { 0xfc800000, 0x04000000, RTL_GIGA_MAC_VER_03 }, -+ { 0xfc800000, 0x00800000, RTL_GIGA_MAC_VER_02 }, -+ { 0xfc800000, 0x00000000, RTL_GIGA_MAC_VER_01 }, -+ -+ /* Catch-all */ -+ { 0x00000000, 0x00000000, RTL_GIGA_MAC_NONE } -+ }; -+ const struct rtl_mac_info *p = mac_info; -+ u32 reg; -+ -+ reg = RTL_R32(TxConfig); -+ while ((reg & p->mask) != p->val) -+ p++; -+ tp->mac_version = p->mac_version; -+ -+ if (tp->mac_version == RTL_GIGA_MAC_NONE) { -+ netif_notice(tp, probe, dev, -+ "unknown MAC, using family default\n"); -+ tp->mac_version = default_version; -+ } -+} -+ -+static void rtl8169_print_mac_version(struct rtl8169_private *tp) -+{ -+ dprintk("mac_version = 0x%02x\n", tp->mac_version); -+} -+ -+struct phy_reg { -+ u16 reg; -+ u16 val; -+}; -+ -+static void rtl_writephy_batch(struct rtl8169_private *tp, -+ const struct phy_reg *regs, int len) -+{ -+ while (len-- > 0) { -+ rtl_writephy(tp, regs->reg, regs->val); -+ regs++; -+ } -+} -+ -+#define PHY_READ 0x00000000 -+#define PHY_DATA_OR 0x10000000 -+#define PHY_DATA_AND 0x20000000 -+#define PHY_BJMPN 0x30000000 -+#define PHY_READ_EFUSE 0x40000000 -+#define PHY_READ_MAC_BYTE 0x50000000 -+#define PHY_WRITE_MAC_BYTE 0x60000000 -+#define PHY_CLEAR_READCOUNT 0x70000000 -+#define PHY_WRITE 0x80000000 -+#define PHY_READCOUNT_EQ_SKIP 0x90000000 -+#define PHY_COMP_EQ_SKIPN 0xa0000000 -+#define PHY_COMP_NEQ_SKIPN 0xb0000000 -+#define PHY_WRITE_PREVIOUS 0xc0000000 -+#define PHY_SKIPN 0xd0000000 -+#define PHY_DELAY_MS 0xe0000000 -+#define PHY_WRITE_ERI_WORD 0xf0000000 -+ -+struct fw_info { -+ u32 magic; -+ char version[RTL_VER_SIZE]; -+ __le32 fw_start; -+ __le32 fw_len; -+ u8 chksum; -+} __packed; -+ -+#define FW_OPCODE_SIZE sizeof(typeof(*((struct rtl_fw_phy_action *)0)->code)) -+ -+static bool rtl_fw_format_ok(struct rtl8169_private *tp, struct rtl_fw *rtl_fw) -+{ -+ const struct firmware *fw = rtl_fw->fw; -+ struct fw_info *fw_info = (struct fw_info *)fw->data; -+ struct rtl_fw_phy_action *pa = &rtl_fw->phy_action; -+ char *version = rtl_fw->version; -+ bool rc = false; -+ -+ if (fw->size < FW_OPCODE_SIZE) -+ goto out; -+ -+ if (!fw_info->magic) { -+ size_t i, size, start; -+ u8 checksum = 0; -+ -+ if (fw->size < sizeof(*fw_info)) -+ goto out; -+ -+ for (i = 0; i < fw->size; i++) -+ checksum += fw->data[i]; -+ if (checksum != 0) -+ goto out; -+ -+ start = le32_to_cpu(fw_info->fw_start); -+ if (start > fw->size) -+ goto out; -+ -+ size = le32_to_cpu(fw_info->fw_len); -+ if (size > (fw->size - start) / FW_OPCODE_SIZE) -+ goto out; -+ -+ memcpy(version, fw_info->version, RTL_VER_SIZE); -+ -+ pa->code = (__le32 *)(fw->data + start); -+ pa->size = size; -+ } else { -+ if (fw->size % FW_OPCODE_SIZE) -+ goto out; -+ -+ strlcpy(version, rtl_lookup_firmware_name(tp), RTL_VER_SIZE); -+ -+ pa->code = (__le32 *)fw->data; -+ pa->size = fw->size / FW_OPCODE_SIZE; -+ } -+ version[RTL_VER_SIZE - 1] = 0; -+ -+ rc = true; -+out: -+ return rc; -+} -+ -+static bool rtl_fw_data_ok(struct rtl8169_private *tp, struct net_device *dev, -+ struct rtl_fw_phy_action *pa) -+{ -+ bool rc = false; -+ size_t index; -+ -+ for (index = 0; index < pa->size; index++) { -+ u32 action = le32_to_cpu(pa->code[index]); -+ u32 regno = (action & 0x0fff0000) >> 16; -+ -+ switch(action & 0xf0000000) { -+ case PHY_READ: -+ case PHY_DATA_OR: -+ case PHY_DATA_AND: -+ case PHY_READ_EFUSE: -+ case PHY_CLEAR_READCOUNT: -+ case PHY_WRITE: -+ case PHY_WRITE_PREVIOUS: -+ case PHY_DELAY_MS: -+ break; -+ -+ case PHY_BJMPN: -+ if (regno > index) { -+ netif_err(tp, ifup, tp->dev, -+ "Out of range of firmware\n"); -+ goto out; -+ } -+ break; -+ case PHY_READCOUNT_EQ_SKIP: -+ if (index + 2 >= pa->size) { -+ netif_err(tp, ifup, tp->dev, -+ "Out of range of firmware\n"); -+ goto out; -+ } -+ break; -+ case PHY_COMP_EQ_SKIPN: -+ case PHY_COMP_NEQ_SKIPN: -+ case PHY_SKIPN: -+ if (index + 1 + regno >= pa->size) { -+ netif_err(tp, ifup, tp->dev, -+ "Out of range of firmware\n"); -+ goto out; -+ } -+ break; -+ -+ case PHY_READ_MAC_BYTE: -+ case PHY_WRITE_MAC_BYTE: -+ case PHY_WRITE_ERI_WORD: -+ default: -+ netif_err(tp, ifup, tp->dev, -+ "Invalid action 0x%08x\n", action); -+ goto out; -+ } -+ } -+ rc = true; -+out: -+ return rc; -+} -+ -+static int rtl_check_firmware(struct rtl8169_private *tp, struct rtl_fw *rtl_fw) -+{ -+ struct net_device *dev = tp->dev; -+ int rc = -EINVAL; -+ -+ if (!rtl_fw_format_ok(tp, rtl_fw)) { -+ netif_err(tp, ifup, dev, "invalid firwmare\n"); -+ goto out; -+ } -+ -+ if (rtl_fw_data_ok(tp, dev, &rtl_fw->phy_action)) -+ rc = 0; -+out: -+ return rc; -+} -+ -+static void rtl_phy_write_fw(struct rtl8169_private *tp, struct rtl_fw *rtl_fw) -+{ -+ struct rtl_fw_phy_action *pa = &rtl_fw->phy_action; -+ u32 predata, count; -+ size_t index; -+ -+ predata = count = 0; -+ -+ for (index = 0; index < pa->size; ) { -+ u32 action = le32_to_cpu(pa->code[index]); -+ u32 data = action & 0x0000ffff; -+ u32 regno = (action & 0x0fff0000) >> 16; -+ -+ if (!action) -+ break; -+ -+ switch(action & 0xf0000000) { -+ case PHY_READ: -+ predata = rtl_readphy(tp, regno); -+ count++; -+ index++; -+ break; -+ case PHY_DATA_OR: -+ predata |= data; -+ index++; -+ break; -+ case PHY_DATA_AND: -+ predata &= data; -+ index++; -+ break; -+ case PHY_BJMPN: -+ index -= regno; -+ break; -+ case PHY_READ_EFUSE: -+ predata = rtl8168d_efuse_read(tp, regno); -+ index++; -+ break; -+ case PHY_CLEAR_READCOUNT: -+ count = 0; -+ index++; -+ break; -+ case PHY_WRITE: -+ rtl_writephy(tp, regno, data); -+ index++; -+ break; -+ case PHY_READCOUNT_EQ_SKIP: -+ index += (count == data) ? 2 : 1; -+ break; -+ case PHY_COMP_EQ_SKIPN: -+ if (predata == data) -+ index += regno; -+ index++; -+ break; -+ case PHY_COMP_NEQ_SKIPN: -+ if (predata != data) -+ index += regno; -+ index++; -+ break; -+ case PHY_WRITE_PREVIOUS: -+ rtl_writephy(tp, regno, predata); -+ index++; -+ break; -+ case PHY_SKIPN: -+ index += regno + 1; -+ break; -+ case PHY_DELAY_MS: -+ mdelay(data); -+ index++; -+ break; -+ -+ case PHY_READ_MAC_BYTE: -+ case PHY_WRITE_MAC_BYTE: -+ case PHY_WRITE_ERI_WORD: -+ default: -+ BUG(); -+ } -+ } -+} -+ -+static void rtl_release_firmware(struct rtl8169_private *tp) -+{ -+ if (!IS_ERR_OR_NULL(tp->rtl_fw)) { -+ release_firmware(tp->rtl_fw->fw); -+ kfree(tp->rtl_fw); -+ } -+ tp->rtl_fw = RTL_FIRMWARE_UNKNOWN; -+} -+ -+static void rtl_apply_firmware(struct rtl8169_private *tp) -+{ -+ struct rtl_fw *rtl_fw = tp->rtl_fw; -+ -+ /* TODO: release firmware once rtl_phy_write_fw signals failures. */ -+ if (!IS_ERR_OR_NULL(rtl_fw)) -+ rtl_phy_write_fw(tp, rtl_fw); -+} -+ -+static void rtl_apply_firmware_cond(struct rtl8169_private *tp, u8 reg, u16 val) -+{ -+ if (rtl_readphy(tp, reg) != val) -+ netif_warn(tp, hw, tp->dev, "chipset not ready for firmware\n"); -+ else -+ rtl_apply_firmware(tp); -+} -+ -+static void rtl8169s_hw_phy_config(struct rtl8169_private *tp) -+{ -+ static const struct phy_reg phy_reg_init[] = { -+ { 0x1f, 0x0001 }, -+ { 0x06, 0x006e }, -+ { 0x08, 0x0708 }, -+ { 0x15, 0x4000 }, -+ { 0x18, 0x65c7 }, -+ -+ { 0x1f, 0x0001 }, -+ { 0x03, 0x00a1 }, -+ { 0x02, 0x0008 }, -+ { 0x01, 0x0120 }, -+ { 0x00, 0x1000 }, -+ { 0x04, 0x0800 }, -+ { 0x04, 0x0000 }, -+ -+ { 0x03, 0xff41 }, -+ { 0x02, 0xdf60 }, -+ { 0x01, 0x0140 }, -+ { 0x00, 0x0077 }, -+ { 0x04, 0x7800 }, -+ { 0x04, 0x7000 }, -+ -+ { 0x03, 0x802f }, -+ { 0x02, 0x4f02 }, -+ { 0x01, 0x0409 }, -+ { 0x00, 0xf0f9 }, -+ { 0x04, 0x9800 }, -+ { 0x04, 0x9000 }, -+ -+ { 0x03, 0xdf01 }, -+ { 0x02, 0xdf20 }, -+ { 0x01, 0xff95 }, -+ { 0x00, 0xba00 }, -+ { 0x04, 0xa800 }, -+ { 0x04, 0xa000 }, -+ -+ { 0x03, 0xff41 }, -+ { 0x02, 0xdf20 }, -+ { 0x01, 0x0140 }, -+ { 0x00, 0x00bb }, -+ { 0x04, 0xb800 }, -+ { 0x04, 0xb000 }, -+ -+ { 0x03, 0xdf41 }, -+ { 0x02, 0xdc60 }, -+ { 0x01, 0x6340 }, -+ { 0x00, 0x007d }, -+ { 0x04, 0xd800 }, -+ { 0x04, 0xd000 }, -+ -+ { 0x03, 0xdf01 }, -+ { 0x02, 0xdf20 }, -+ { 0x01, 0x100a }, -+ { 0x00, 0xa0ff }, -+ { 0x04, 0xf800 }, -+ { 0x04, 0xf000 }, -+ -+ { 0x1f, 0x0000 }, -+ { 0x0b, 0x0000 }, -+ { 0x00, 0x9200 } -+ }; -+ -+ rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -+} -+ -+static void rtl8169sb_hw_phy_config(struct rtl8169_private *tp) -+{ -+ static const struct phy_reg phy_reg_init[] = { -+ { 0x1f, 0x0002 }, -+ { 0x01, 0x90d0 }, -+ { 0x1f, 0x0000 } -+ }; -+ -+ rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -+} -+ -+static void rtl8169scd_hw_phy_config_quirk(struct rtl8169_private *tp) -+{ -+ struct pci_dev *pdev = tp->pci_dev; -+ -+ if ((pdev->subsystem_vendor != PCI_VENDOR_ID_GIGABYTE) || -+ (pdev->subsystem_device != 0xe000)) -+ return; -+ -+ rtl_writephy(tp, 0x1f, 0x0001); -+ rtl_writephy(tp, 0x10, 0xf01b); -+ rtl_writephy(tp, 0x1f, 0x0000); -+} -+ -+static void rtl8169scd_hw_phy_config(struct rtl8169_private *tp) -+{ -+ static const struct phy_reg phy_reg_init[] = { -+ { 0x1f, 0x0001 }, -+ { 0x04, 0x0000 }, -+ { 0x03, 0x00a1 }, -+ { 0x02, 0x0008 }, -+ { 0x01, 0x0120 }, -+ { 0x00, 0x1000 }, -+ { 0x04, 0x0800 }, -+ { 0x04, 0x9000 }, -+ { 0x03, 0x802f }, -+ { 0x02, 0x4f02 }, -+ { 0x01, 0x0409 }, -+ { 0x00, 0xf099 }, -+ { 0x04, 0x9800 }, -+ { 0x04, 0xa000 }, -+ { 0x03, 0xdf01 }, -+ { 0x02, 0xdf20 }, -+ { 0x01, 0xff95 }, -+ { 0x00, 0xba00 }, -+ { 0x04, 0xa800 }, -+ { 0x04, 0xf000 }, -+ { 0x03, 0xdf01 }, -+ { 0x02, 0xdf20 }, -+ { 0x01, 0x101a }, -+ { 0x00, 0xa0ff }, -+ { 0x04, 0xf800 }, -+ { 0x04, 0x0000 }, -+ { 0x1f, 0x0000 }, -+ -+ { 0x1f, 0x0001 }, -+ { 0x10, 0xf41b }, -+ { 0x14, 0xfb54 }, -+ { 0x18, 0xf5c7 }, -+ { 0x1f, 0x0000 }, -+ -+ { 0x1f, 0x0001 }, -+ { 0x17, 0x0cc0 }, -+ { 0x1f, 0x0000 } -+ }; -+ -+ rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -+ -+ rtl8169scd_hw_phy_config_quirk(tp); -+} -+ -+static void rtl8169sce_hw_phy_config(struct rtl8169_private *tp) -+{ -+ static const struct phy_reg phy_reg_init[] = { -+ { 0x1f, 0x0001 }, -+ { 0x04, 0x0000 }, -+ { 0x03, 0x00a1 }, -+ { 0x02, 0x0008 }, -+ { 0x01, 0x0120 }, -+ { 0x00, 0x1000 }, -+ { 0x04, 0x0800 }, -+ { 0x04, 0x9000 }, -+ { 0x03, 0x802f }, -+ { 0x02, 0x4f02 }, -+ { 0x01, 0x0409 }, -+ { 0x00, 0xf099 }, -+ { 0x04, 0x9800 }, -+ { 0x04, 0xa000 }, -+ { 0x03, 0xdf01 }, -+ { 0x02, 0xdf20 }, -+ { 0x01, 0xff95 }, -+ { 0x00, 0xba00 }, -+ { 0x04, 0xa800 }, -+ { 0x04, 0xf000 }, -+ { 0x03, 0xdf01 }, -+ { 0x02, 0xdf20 }, -+ { 0x01, 0x101a }, -+ { 0x00, 0xa0ff }, -+ { 0x04, 0xf800 }, -+ { 0x04, 0x0000 }, -+ { 0x1f, 0x0000 }, -+ -+ { 0x1f, 0x0001 }, -+ { 0x0b, 0x8480 }, -+ { 0x1f, 0x0000 }, -+ -+ { 0x1f, 0x0001 }, -+ { 0x18, 0x67c7 }, -+ { 0x04, 0x2000 }, -+ { 0x03, 0x002f }, -+ { 0x02, 0x4360 }, -+ { 0x01, 0x0109 }, -+ { 0x00, 0x3022 }, -+ { 0x04, 0x2800 }, -+ { 0x1f, 0x0000 }, -+ -+ { 0x1f, 0x0001 }, -+ { 0x17, 0x0cc0 }, -+ { 0x1f, 0x0000 } -+ }; -+ -+ rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -+} -+ -+static void rtl8168bb_hw_phy_config(struct rtl8169_private *tp) -+{ -+ static const struct phy_reg phy_reg_init[] = { -+ { 0x10, 0xf41b }, -+ { 0x1f, 0x0000 } -+ }; -+ -+ rtl_writephy(tp, 0x1f, 0x0001); -+ rtl_patchphy(tp, 0x16, 1 << 0); -+ -+ rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -+} -+ -+static void rtl8168bef_hw_phy_config(struct rtl8169_private *tp) -+{ -+ static const struct phy_reg phy_reg_init[] = { -+ { 0x1f, 0x0001 }, -+ { 0x10, 0xf41b }, -+ { 0x1f, 0x0000 } -+ }; -+ -+ rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -+} -+ -+static void rtl8168cp_1_hw_phy_config(struct rtl8169_private *tp) -+{ -+ static const struct phy_reg phy_reg_init[] = { -+ { 0x1f, 0x0000 }, -+ { 0x1d, 0x0f00 }, -+ { 0x1f, 0x0002 }, -+ { 0x0c, 0x1ec8 }, -+ { 0x1f, 0x0000 } -+ }; -+ -+ rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -+} -+ -+static void rtl8168cp_2_hw_phy_config(struct rtl8169_private *tp) -+{ -+ static const struct phy_reg phy_reg_init[] = { -+ { 0x1f, 0x0001 }, -+ { 0x1d, 0x3d98 }, -+ { 0x1f, 0x0000 } -+ }; -+ -+ rtl_writephy(tp, 0x1f, 0x0000); -+ rtl_patchphy(tp, 0x14, 1 << 5); -+ rtl_patchphy(tp, 0x0d, 1 << 5); -+ -+ rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -+} -+ -+static void rtl8168c_1_hw_phy_config(struct rtl8169_private *tp) -+{ -+ static const struct phy_reg phy_reg_init[] = { -+ { 0x1f, 0x0001 }, -+ { 0x12, 0x2300 }, -+ { 0x1f, 0x0002 }, -+ { 0x00, 0x88d4 }, -+ { 0x01, 0x82b1 }, -+ { 0x03, 0x7002 }, -+ { 0x08, 0x9e30 }, -+ { 0x09, 0x01f0 }, -+ { 0x0a, 0x5500 }, -+ { 0x0c, 0x00c8 }, -+ { 0x1f, 0x0003 }, -+ { 0x12, 0xc096 }, -+ { 0x16, 0x000a }, -+ { 0x1f, 0x0000 }, -+ { 0x1f, 0x0000 }, -+ { 0x09, 0x2000 }, -+ { 0x09, 0x0000 } -+ }; -+ -+ rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -+ -+ rtl_patchphy(tp, 0x14, 1 << 5); -+ rtl_patchphy(tp, 0x0d, 1 << 5); -+ rtl_writephy(tp, 0x1f, 0x0000); -+} -+ -+static void rtl8168c_2_hw_phy_config(struct rtl8169_private *tp) -+{ -+ static const struct phy_reg phy_reg_init[] = { -+ { 0x1f, 0x0001 }, -+ { 0x12, 0x2300 }, -+ { 0x03, 0x802f }, -+ { 0x02, 0x4f02 }, -+ { 0x01, 0x0409 }, -+ { 0x00, 0xf099 }, -+ { 0x04, 0x9800 }, -+ { 0x04, 0x9000 }, -+ { 0x1d, 0x3d98 }, -+ { 0x1f, 0x0002 }, -+ { 0x0c, 0x7eb8 }, -+ { 0x06, 0x0761 }, -+ { 0x1f, 0x0003 }, -+ { 0x16, 0x0f0a }, -+ { 0x1f, 0x0000 } -+ }; -+ -+ rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -+ -+ rtl_patchphy(tp, 0x16, 1 << 0); -+ rtl_patchphy(tp, 0x14, 1 << 5); -+ rtl_patchphy(tp, 0x0d, 1 << 5); -+ rtl_writephy(tp, 0x1f, 0x0000); -+} -+ -+static void rtl8168c_3_hw_phy_config(struct rtl8169_private *tp) -+{ -+ static const 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_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -+ -+ rtl_patchphy(tp, 0x16, 1 << 0); -+ rtl_patchphy(tp, 0x14, 1 << 5); -+ rtl_patchphy(tp, 0x0d, 1 << 5); -+ rtl_writephy(tp, 0x1f, 0x0000); -+} -+ -+static void rtl8168c_4_hw_phy_config(struct rtl8169_private *tp) -+{ -+ rtl8168c_3_hw_phy_config(tp); -+} -+ -+static void rtl8168d_1_hw_phy_config(struct rtl8169_private *tp) -+{ -+ static const struct phy_reg phy_reg_init_0[] = { -+ /* Channel Estimation */ -+ { 0x1f, 0x0001 }, -+ { 0x06, 0x4064 }, -+ { 0x07, 0x2863 }, -+ { 0x08, 0x059c }, -+ { 0x09, 0x26b4 }, -+ { 0x0a, 0x6a19 }, -+ { 0x0b, 0xdcc8 }, -+ { 0x10, 0xf06d }, -+ { 0x14, 0x7f68 }, -+ { 0x18, 0x7fd9 }, -+ { 0x1c, 0xf0ff }, -+ { 0x1d, 0x3d9c }, -+ { 0x1f, 0x0003 }, -+ { 0x12, 0xf49f }, -+ { 0x13, 0x070b }, -+ { 0x1a, 0x05ad }, -+ { 0x14, 0x94c0 }, -+ -+ /* -+ * Tx Error Issue -+ * Enhance line driver power -+ */ -+ { 0x1f, 0x0002 }, -+ { 0x06, 0x5561 }, -+ { 0x1f, 0x0005 }, -+ { 0x05, 0x8332 }, -+ { 0x06, 0x5561 }, -+ -+ /* -+ * Can not link to 1Gbps with bad cable -+ * Decrease SNR threshold form 21.07dB to 19.04dB -+ */ -+ { 0x1f, 0x0001 }, -+ { 0x17, 0x0cc0 }, -+ -+ { 0x1f, 0x0000 }, -+ { 0x0d, 0xf880 } -+ }; -+ -+ rtl_writephy_batch(tp, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); -+ -+ /* -+ * Rx Error Issue -+ * Fine Tune Switching regulator parameter -+ */ -+ rtl_writephy(tp, 0x1f, 0x0002); -+ rtl_w1w0_phy(tp, 0x0b, 0x0010, 0x00ef); -+ rtl_w1w0_phy(tp, 0x0c, 0xa200, 0x5d00); -+ -+ if (rtl8168d_efuse_read(tp, 0x01) == 0xb1) { -+ static const struct phy_reg phy_reg_init[] = { -+ { 0x1f, 0x0002 }, -+ { 0x05, 0x669a }, -+ { 0x1f, 0x0005 }, -+ { 0x05, 0x8330 }, -+ { 0x06, 0x669a }, -+ { 0x1f, 0x0002 } -+ }; -+ int val; -+ -+ rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -+ -+ val = rtl_readphy(tp, 0x0d); -+ -+ if ((val & 0x00ff) != 0x006c) { -+ static const u32 set[] = { -+ 0x0065, 0x0066, 0x0067, 0x0068, -+ 0x0069, 0x006a, 0x006b, 0x006c -+ }; -+ int i; -+ -+ rtl_writephy(tp, 0x1f, 0x0002); -+ -+ val &= 0xff00; -+ for (i = 0; i < ARRAY_SIZE(set); i++) -+ rtl_writephy(tp, 0x0d, val | set[i]); -+ } -+ } else { -+ static const struct phy_reg phy_reg_init[] = { -+ { 0x1f, 0x0002 }, -+ { 0x05, 0x6662 }, -+ { 0x1f, 0x0005 }, -+ { 0x05, 0x8330 }, -+ { 0x06, 0x6662 } -+ }; -+ -+ rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -+ } -+ -+ /* RSET couple improve */ -+ rtl_writephy(tp, 0x1f, 0x0002); -+ rtl_patchphy(tp, 0x0d, 0x0300); -+ rtl_patchphy(tp, 0x0f, 0x0010); -+ -+ /* Fine tune PLL performance */ -+ rtl_writephy(tp, 0x1f, 0x0002); -+ rtl_w1w0_phy(tp, 0x02, 0x0100, 0x0600); -+ rtl_w1w0_phy(tp, 0x03, 0x0000, 0xe000); -+ -+ rtl_writephy(tp, 0x1f, 0x0005); -+ rtl_writephy(tp, 0x05, 0x001b); -+ -+ rtl_apply_firmware_cond(tp, MII_EXPANSION, 0xbf00); -+ -+ rtl_writephy(tp, 0x1f, 0x0000); -+} -+ -+static void rtl8168d_2_hw_phy_config(struct rtl8169_private *tp) -+{ -+ static const struct phy_reg phy_reg_init_0[] = { -+ /* Channel Estimation */ -+ { 0x1f, 0x0001 }, -+ { 0x06, 0x4064 }, -+ { 0x07, 0x2863 }, -+ { 0x08, 0x059c }, -+ { 0x09, 0x26b4 }, -+ { 0x0a, 0x6a19 }, -+ { 0x0b, 0xdcc8 }, -+ { 0x10, 0xf06d }, -+ { 0x14, 0x7f68 }, -+ { 0x18, 0x7fd9 }, -+ { 0x1c, 0xf0ff }, -+ { 0x1d, 0x3d9c }, -+ { 0x1f, 0x0003 }, -+ { 0x12, 0xf49f }, -+ { 0x13, 0x070b }, -+ { 0x1a, 0x05ad }, -+ { 0x14, 0x94c0 }, -+ -+ /* -+ * Tx Error Issue -+ * Enhance line driver power -+ */ -+ { 0x1f, 0x0002 }, -+ { 0x06, 0x5561 }, -+ { 0x1f, 0x0005 }, -+ { 0x05, 0x8332 }, -+ { 0x06, 0x5561 }, -+ -+ /* -+ * Can not link to 1Gbps with bad cable -+ * Decrease SNR threshold form 21.07dB to 19.04dB -+ */ -+ { 0x1f, 0x0001 }, -+ { 0x17, 0x0cc0 }, -+ -+ { 0x1f, 0x0000 }, -+ { 0x0d, 0xf880 } -+ }; -+ -+ rtl_writephy_batch(tp, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); -+ -+ if (rtl8168d_efuse_read(tp, 0x01) == 0xb1) { -+ static const struct phy_reg phy_reg_init[] = { -+ { 0x1f, 0x0002 }, -+ { 0x05, 0x669a }, -+ { 0x1f, 0x0005 }, -+ { 0x05, 0x8330 }, -+ { 0x06, 0x669a }, -+ -+ { 0x1f, 0x0002 } -+ }; -+ int val; -+ -+ rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -+ -+ val = rtl_readphy(tp, 0x0d); -+ if ((val & 0x00ff) != 0x006c) { -+ static const u32 set[] = { -+ 0x0065, 0x0066, 0x0067, 0x0068, -+ 0x0069, 0x006a, 0x006b, 0x006c -+ }; -+ int i; -+ -+ rtl_writephy(tp, 0x1f, 0x0002); -+ -+ val &= 0xff00; -+ for (i = 0; i < ARRAY_SIZE(set); i++) -+ rtl_writephy(tp, 0x0d, val | set[i]); -+ } -+ } else { -+ static const struct phy_reg phy_reg_init[] = { -+ { 0x1f, 0x0002 }, -+ { 0x05, 0x2642 }, -+ { 0x1f, 0x0005 }, -+ { 0x05, 0x8330 }, -+ { 0x06, 0x2642 } -+ }; -+ -+ rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -+ } -+ -+ /* Fine tune PLL performance */ -+ rtl_writephy(tp, 0x1f, 0x0002); -+ rtl_w1w0_phy(tp, 0x02, 0x0100, 0x0600); -+ rtl_w1w0_phy(tp, 0x03, 0x0000, 0xe000); -+ -+ /* Switching regulator Slew rate */ -+ rtl_writephy(tp, 0x1f, 0x0002); -+ rtl_patchphy(tp, 0x0f, 0x0017); -+ -+ rtl_writephy(tp, 0x1f, 0x0005); -+ rtl_writephy(tp, 0x05, 0x001b); -+ -+ rtl_apply_firmware_cond(tp, MII_EXPANSION, 0xb300); -+ -+ rtl_writephy(tp, 0x1f, 0x0000); -+} -+ -+static void rtl8168d_3_hw_phy_config(struct rtl8169_private *tp) -+{ -+ static const struct phy_reg phy_reg_init[] = { -+ { 0x1f, 0x0002 }, -+ { 0x10, 0x0008 }, -+ { 0x0d, 0x006c }, -+ -+ { 0x1f, 0x0000 }, -+ { 0x0d, 0xf880 }, -+ -+ { 0x1f, 0x0001 }, -+ { 0x17, 0x0cc0 }, -+ -+ { 0x1f, 0x0001 }, -+ { 0x0b, 0xa4d8 }, -+ { 0x09, 0x281c }, -+ { 0x07, 0x2883 }, -+ { 0x0a, 0x6b35 }, -+ { 0x1d, 0x3da4 }, -+ { 0x1c, 0xeffd }, -+ { 0x14, 0x7f52 }, -+ { 0x18, 0x7fc6 }, -+ { 0x08, 0x0601 }, -+ { 0x06, 0x4063 }, -+ { 0x10, 0xf074 }, -+ { 0x1f, 0x0003 }, -+ { 0x13, 0x0789 }, -+ { 0x12, 0xf4bd }, -+ { 0x1a, 0x04fd }, -+ { 0x14, 0x84b0 }, -+ { 0x1f, 0x0000 }, -+ { 0x00, 0x9200 }, -+ -+ { 0x1f, 0x0005 }, -+ { 0x01, 0x0340 }, -+ { 0x1f, 0x0001 }, -+ { 0x04, 0x4000 }, -+ { 0x03, 0x1d21 }, -+ { 0x02, 0x0c32 }, -+ { 0x01, 0x0200 }, -+ { 0x00, 0x5554 }, -+ { 0x04, 0x4800 }, -+ { 0x04, 0x4000 }, -+ { 0x04, 0xf000 }, -+ { 0x03, 0xdf01 }, -+ { 0x02, 0xdf20 }, -+ { 0x01, 0x101a }, -+ { 0x00, 0xa0ff }, -+ { 0x04, 0xf800 }, -+ { 0x04, 0xf000 }, -+ { 0x1f, 0x0000 }, -+ -+ { 0x1f, 0x0007 }, -+ { 0x1e, 0x0023 }, -+ { 0x16, 0x0000 }, -+ { 0x1f, 0x0000 } -+ }; -+ -+ rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -+} -+ -+static void rtl8168d_4_hw_phy_config(struct rtl8169_private *tp) -+{ -+ static const struct phy_reg phy_reg_init[] = { -+ { 0x1f, 0x0001 }, -+ { 0x17, 0x0cc0 }, -+ -+ { 0x1f, 0x0007 }, -+ { 0x1e, 0x002d }, -+ { 0x18, 0x0040 }, -+ { 0x1f, 0x0000 } -+ }; -+ -+ rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -+ rtl_patchphy(tp, 0x0d, 1 << 5); -+} -+ -+static void rtl8168e_1_hw_phy_config(struct rtl8169_private *tp) -+{ -+ static const struct phy_reg phy_reg_init[] = { -+ /* Enable Delay cap */ -+ { 0x1f, 0x0005 }, -+ { 0x05, 0x8b80 }, -+ { 0x06, 0xc896 }, -+ { 0x1f, 0x0000 }, -+ -+ /* Channel estimation fine tune */ -+ { 0x1f, 0x0001 }, -+ { 0x0b, 0x6c20 }, -+ { 0x07, 0x2872 }, -+ { 0x1c, 0xefff }, -+ { 0x1f, 0x0003 }, -+ { 0x14, 0x6420 }, -+ { 0x1f, 0x0000 }, -+ -+ /* Update PFM & 10M TX idle timer */ -+ { 0x1f, 0x0007 }, -+ { 0x1e, 0x002f }, -+ { 0x15, 0x1919 }, -+ { 0x1f, 0x0000 }, -+ -+ { 0x1f, 0x0007 }, -+ { 0x1e, 0x00ac }, -+ { 0x18, 0x0006 }, -+ { 0x1f, 0x0000 } -+ }; -+ -+ rtl_apply_firmware(tp); -+ -+ rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -+ -+ /* DCO enable for 10M IDLE Power */ -+ rtl_writephy(tp, 0x1f, 0x0007); -+ rtl_writephy(tp, 0x1e, 0x0023); -+ rtl_w1w0_phy(tp, 0x17, 0x0006, 0x0000); -+ rtl_writephy(tp, 0x1f, 0x0000); -+ -+ /* For impedance matching */ -+ rtl_writephy(tp, 0x1f, 0x0002); -+ rtl_w1w0_phy(tp, 0x08, 0x8000, 0x7f00); -+ rtl_writephy(tp, 0x1f, 0x0000); -+ -+ /* PHY auto speed down */ -+ rtl_writephy(tp, 0x1f, 0x0007); -+ rtl_writephy(tp, 0x1e, 0x002d); -+ rtl_w1w0_phy(tp, 0x18, 0x0050, 0x0000); -+ rtl_writephy(tp, 0x1f, 0x0000); -+ rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000); -+ -+ rtl_writephy(tp, 0x1f, 0x0005); -+ rtl_writephy(tp, 0x05, 0x8b86); -+ rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000); -+ rtl_writephy(tp, 0x1f, 0x0000); -+ -+ rtl_writephy(tp, 0x1f, 0x0005); -+ rtl_writephy(tp, 0x05, 0x8b85); -+ rtl_w1w0_phy(tp, 0x06, 0x0000, 0x2000); -+ rtl_writephy(tp, 0x1f, 0x0007); -+ rtl_writephy(tp, 0x1e, 0x0020); -+ rtl_w1w0_phy(tp, 0x15, 0x0000, 0x1100); -+ rtl_writephy(tp, 0x1f, 0x0006); -+ rtl_writephy(tp, 0x00, 0x5a00); -+ rtl_writephy(tp, 0x1f, 0x0000); -+ rtl_writephy(tp, 0x0d, 0x0007); -+ rtl_writephy(tp, 0x0e, 0x003c); -+ rtl_writephy(tp, 0x0d, 0x4007); -+ rtl_writephy(tp, 0x0e, 0x0000); -+ rtl_writephy(tp, 0x0d, 0x0000); -+} -+ -+static void rtl8168e_2_hw_phy_config(struct rtl8169_private *tp) -+{ -+ static const struct phy_reg phy_reg_init[] = { -+ /* Enable Delay cap */ -+ { 0x1f, 0x0004 }, -+ { 0x1f, 0x0007 }, -+ { 0x1e, 0x00ac }, -+ { 0x18, 0x0006 }, -+ { 0x1f, 0x0002 }, -+ { 0x1f, 0x0000 }, -+ { 0x1f, 0x0000 }, -+ -+ /* Channel estimation fine tune */ -+ { 0x1f, 0x0003 }, -+ { 0x09, 0xa20f }, -+ { 0x1f, 0x0000 }, -+ { 0x1f, 0x0000 }, -+ -+ /* Green Setting */ -+ { 0x1f, 0x0005 }, -+ { 0x05, 0x8b5b }, -+ { 0x06, 0x9222 }, -+ { 0x05, 0x8b6d }, -+ { 0x06, 0x8000 }, -+ { 0x05, 0x8b76 }, -+ { 0x06, 0x8000 }, -+ { 0x1f, 0x0000 } -+ }; -+ -+ rtl_apply_firmware(tp); -+ -+ rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -+ -+ /* For 4-corner performance improve */ -+ rtl_writephy(tp, 0x1f, 0x0005); -+ rtl_writephy(tp, 0x05, 0x8b80); -+ rtl_w1w0_phy(tp, 0x17, 0x0006, 0x0000); -+ rtl_writephy(tp, 0x1f, 0x0000); -+ -+ /* PHY auto speed down */ -+ rtl_writephy(tp, 0x1f, 0x0004); -+ rtl_writephy(tp, 0x1f, 0x0007); -+ rtl_writephy(tp, 0x1e, 0x002d); -+ rtl_w1w0_phy(tp, 0x18, 0x0010, 0x0000); -+ rtl_writephy(tp, 0x1f, 0x0002); -+ rtl_writephy(tp, 0x1f, 0x0000); -+ rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000); -+ -+ /* improve 10M EEE waveform */ -+ rtl_writephy(tp, 0x1f, 0x0005); -+ rtl_writephy(tp, 0x05, 0x8b86); -+ rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000); -+ rtl_writephy(tp, 0x1f, 0x0000); -+ -+ /* Improve 2-pair detection performance */ -+ rtl_writephy(tp, 0x1f, 0x0005); -+ rtl_writephy(tp, 0x05, 0x8b85); -+ rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000); -+ rtl_writephy(tp, 0x1f, 0x0000); -+ -+ /* EEE setting */ -+ rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_1111, 0x0000, 0x0003, ERIAR_EXGMAC); -+ rtl_writephy(tp, 0x1f, 0x0005); -+ rtl_writephy(tp, 0x05, 0x8b85); -+ rtl_w1w0_phy(tp, 0x06, 0x0000, 0x2000); -+ rtl_writephy(tp, 0x1f, 0x0004); -+ rtl_writephy(tp, 0x1f, 0x0007); -+ rtl_writephy(tp, 0x1e, 0x0020); -+ rtl_w1w0_phy(tp, 0x15, 0x0000, 0x0100); -+ rtl_writephy(tp, 0x1f, 0x0002); -+ rtl_writephy(tp, 0x1f, 0x0000); -+ rtl_writephy(tp, 0x0d, 0x0007); -+ rtl_writephy(tp, 0x0e, 0x003c); -+ rtl_writephy(tp, 0x0d, 0x4007); -+ rtl_writephy(tp, 0x0e, 0x0000); -+ rtl_writephy(tp, 0x0d, 0x0000); -+ -+ /* Green feature */ -+ rtl_writephy(tp, 0x1f, 0x0003); -+ rtl_w1w0_phy(tp, 0x19, 0x0000, 0x0001); -+ rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0400); -+ rtl_writephy(tp, 0x1f, 0x0000); -+} -+ -+static void rtl8168f_hw_phy_config(struct rtl8169_private *tp) -+{ -+ /* For 4-corner performance improve */ -+ rtl_writephy(tp, 0x1f, 0x0005); -+ rtl_writephy(tp, 0x05, 0x8b80); -+ rtl_w1w0_phy(tp, 0x06, 0x0006, 0x0000); -+ rtl_writephy(tp, 0x1f, 0x0000); -+ -+ /* PHY auto speed down */ -+ rtl_writephy(tp, 0x1f, 0x0007); -+ rtl_writephy(tp, 0x1e, 0x002d); -+ rtl_w1w0_phy(tp, 0x18, 0x0010, 0x0000); -+ rtl_writephy(tp, 0x1f, 0x0000); -+ rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000); -+ -+ /* Improve 10M EEE waveform */ -+ rtl_writephy(tp, 0x1f, 0x0005); -+ rtl_writephy(tp, 0x05, 0x8b86); -+ rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000); -+ rtl_writephy(tp, 0x1f, 0x0000); -+} -+ -+static void rtl8168f_1_hw_phy_config(struct rtl8169_private *tp) -+{ -+ static const struct phy_reg phy_reg_init[] = { -+ /* Channel estimation fine tune */ -+ { 0x1f, 0x0003 }, -+ { 0x09, 0xa20f }, -+ { 0x1f, 0x0000 }, -+ -+ /* Modify green table for giga & fnet */ -+ { 0x1f, 0x0005 }, -+ { 0x05, 0x8b55 }, -+ { 0x06, 0x0000 }, -+ { 0x05, 0x8b5e }, -+ { 0x06, 0x0000 }, -+ { 0x05, 0x8b67 }, -+ { 0x06, 0x0000 }, -+ { 0x05, 0x8b70 }, -+ { 0x06, 0x0000 }, -+ { 0x1f, 0x0000 }, -+ { 0x1f, 0x0007 }, -+ { 0x1e, 0x0078 }, -+ { 0x17, 0x0000 }, -+ { 0x19, 0x00fb }, -+ { 0x1f, 0x0000 }, -+ -+ /* Modify green table for 10M */ -+ { 0x1f, 0x0005 }, -+ { 0x05, 0x8b79 }, -+ { 0x06, 0xaa00 }, -+ { 0x1f, 0x0000 }, -+ -+ /* Disable hiimpedance detection (RTCT) */ -+ { 0x1f, 0x0003 }, -+ { 0x01, 0x328a }, -+ { 0x1f, 0x0000 } -+ }; -+ -+ rtl_apply_firmware(tp); -+ -+ rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -+ -+ rtl8168f_hw_phy_config(tp); -+ -+ /* Improve 2-pair detection performance */ -+ rtl_writephy(tp, 0x1f, 0x0005); -+ rtl_writephy(tp, 0x05, 0x8b85); -+ rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000); -+ rtl_writephy(tp, 0x1f, 0x0000); -+} -+ -+static void rtl8168f_2_hw_phy_config(struct rtl8169_private *tp) -+{ -+ rtl_apply_firmware(tp); -+ -+ rtl8168f_hw_phy_config(tp); -+} -+ -+static void rtl8411_hw_phy_config(struct rtl8169_private *tp) -+{ -+ static const struct phy_reg phy_reg_init[] = { -+ /* Channel estimation fine tune */ -+ { 0x1f, 0x0003 }, -+ { 0x09, 0xa20f }, -+ { 0x1f, 0x0000 }, -+ -+ /* Modify green table for giga & fnet */ -+ { 0x1f, 0x0005 }, -+ { 0x05, 0x8b55 }, -+ { 0x06, 0x0000 }, -+ { 0x05, 0x8b5e }, -+ { 0x06, 0x0000 }, -+ { 0x05, 0x8b67 }, -+ { 0x06, 0x0000 }, -+ { 0x05, 0x8b70 }, -+ { 0x06, 0x0000 }, -+ { 0x1f, 0x0000 }, -+ { 0x1f, 0x0007 }, -+ { 0x1e, 0x0078 }, -+ { 0x17, 0x0000 }, -+ { 0x19, 0x00aa }, -+ { 0x1f, 0x0000 }, -+ -+ /* Modify green table for 10M */ -+ { 0x1f, 0x0005 }, -+ { 0x05, 0x8b79 }, -+ { 0x06, 0xaa00 }, -+ { 0x1f, 0x0000 }, -+ -+ /* Disable hiimpedance detection (RTCT) */ -+ { 0x1f, 0x0003 }, -+ { 0x01, 0x328a }, -+ { 0x1f, 0x0000 } -+ }; -+ -+ -+ rtl_apply_firmware(tp); -+ -+ rtl8168f_hw_phy_config(tp); -+ -+ /* Improve 2-pair detection performance */ -+ rtl_writephy(tp, 0x1f, 0x0005); -+ rtl_writephy(tp, 0x05, 0x8b85); -+ rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000); -+ rtl_writephy(tp, 0x1f, 0x0000); -+ -+ rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -+ -+ /* Modify green table for giga */ -+ rtl_writephy(tp, 0x1f, 0x0005); -+ rtl_writephy(tp, 0x05, 0x8b54); -+ rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0800); -+ rtl_writephy(tp, 0x05, 0x8b5d); -+ rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0800); -+ rtl_writephy(tp, 0x05, 0x8a7c); -+ rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100); -+ rtl_writephy(tp, 0x05, 0x8a7f); -+ rtl_w1w0_phy(tp, 0x06, 0x0100, 0x0000); -+ rtl_writephy(tp, 0x05, 0x8a82); -+ rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100); -+ rtl_writephy(tp, 0x05, 0x8a85); -+ rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100); -+ rtl_writephy(tp, 0x05, 0x8a88); -+ rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100); -+ rtl_writephy(tp, 0x1f, 0x0000); -+ -+ /* uc same-seed solution */ -+ rtl_writephy(tp, 0x1f, 0x0005); -+ rtl_writephy(tp, 0x05, 0x8b85); -+ rtl_w1w0_phy(tp, 0x06, 0x8000, 0x0000); -+ rtl_writephy(tp, 0x1f, 0x0000); -+ -+ /* eee setting */ -+ rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_0001, 0x00, 0x03, ERIAR_EXGMAC); -+ rtl_writephy(tp, 0x1f, 0x0005); -+ rtl_writephy(tp, 0x05, 0x8b85); -+ rtl_w1w0_phy(tp, 0x06, 0x0000, 0x2000); -+ rtl_writephy(tp, 0x1f, 0x0004); -+ rtl_writephy(tp, 0x1f, 0x0007); -+ rtl_writephy(tp, 0x1e, 0x0020); -+ rtl_w1w0_phy(tp, 0x15, 0x0000, 0x0100); -+ rtl_writephy(tp, 0x1f, 0x0000); -+ rtl_writephy(tp, 0x0d, 0x0007); -+ rtl_writephy(tp, 0x0e, 0x003c); -+ rtl_writephy(tp, 0x0d, 0x4007); -+ rtl_writephy(tp, 0x0e, 0x0000); -+ rtl_writephy(tp, 0x0d, 0x0000); -+ -+ /* Green feature */ -+ rtl_writephy(tp, 0x1f, 0x0003); -+ rtl_w1w0_phy(tp, 0x19, 0x0000, 0x0001); -+ rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0400); -+ rtl_writephy(tp, 0x1f, 0x0000); -+} -+ -+static void rtl8168g_1_hw_phy_config(struct rtl8169_private *tp) -+{ -+ static const u16 mac_ocp_patch[] = { -+ 0xe008, 0xe01b, 0xe01d, 0xe01f, -+ 0xe021, 0xe023, 0xe025, 0xe027, -+ 0x49d2, 0xf10d, 0x766c, 0x49e2, -+ 0xf00a, 0x1ec0, 0x8ee1, 0xc60a, -+ -+ 0x77c0, 0x4870, 0x9fc0, 0x1ea0, -+ 0xc707, 0x8ee1, 0x9d6c, 0xc603, -+ 0xbe00, 0xb416, 0x0076, 0xe86c, -+ 0xc602, 0xbe00, 0x0000, 0xc602, -+ -+ 0xbe00, 0x0000, 0xc602, 0xbe00, -+ 0x0000, 0xc602, 0xbe00, 0x0000, -+ 0xc602, 0xbe00, 0x0000, 0xc602, -+ 0xbe00, 0x0000, 0xc602, 0xbe00, -+ -+ 0x0000, 0x0000, 0x0000, 0x0000 -+ }; -+ u32 i; -+ -+ /* Patch code for GPHY reset */ -+ for (i = 0; i < ARRAY_SIZE(mac_ocp_patch); i++) -+ r8168_mac_ocp_write(tp, 0xf800 + 2*i, mac_ocp_patch[i]); -+ r8168_mac_ocp_write(tp, 0xfc26, 0x8000); -+ r8168_mac_ocp_write(tp, 0xfc28, 0x0075); -+ -+ rtl_apply_firmware(tp); -+ -+ if (r8168_phy_ocp_read(tp, 0xa460) & 0x0100) -+ rtl_w1w0_phy_ocp(tp, 0xbcc4, 0x0000, 0x8000); -+ else -+ rtl_w1w0_phy_ocp(tp, 0xbcc4, 0x8000, 0x0000); -+ -+ if (r8168_phy_ocp_read(tp, 0xa466) & 0x0100) -+ rtl_w1w0_phy_ocp(tp, 0xc41a, 0x0002, 0x0000); -+ else -+ rtl_w1w0_phy_ocp(tp, 0xbcc4, 0x0000, 0x0002); -+ -+ rtl_w1w0_phy_ocp(tp, 0xa442, 0x000c, 0x0000); -+ rtl_w1w0_phy_ocp(tp, 0xa4b2, 0x0004, 0x0000); -+ -+ r8168_phy_ocp_write(tp, 0xa436, 0x8012); -+ rtl_w1w0_phy_ocp(tp, 0xa438, 0x8000, 0x0000); -+ -+ rtl_w1w0_phy_ocp(tp, 0xc422, 0x4000, 0x2000); -+} -+ -+static void rtl8102e_hw_phy_config(struct rtl8169_private *tp) -+{ -+ static const struct phy_reg phy_reg_init[] = { -+ { 0x1f, 0x0003 }, -+ { 0x08, 0x441d }, -+ { 0x01, 0x9100 }, -+ { 0x1f, 0x0000 } -+ }; -+ -+ rtl_writephy(tp, 0x1f, 0x0000); -+ rtl_patchphy(tp, 0x11, 1 << 12); -+ rtl_patchphy(tp, 0x19, 1 << 13); -+ rtl_patchphy(tp, 0x10, 1 << 15); -+ -+ rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -+} -+ -+static void rtl8105e_hw_phy_config(struct rtl8169_private *tp) -+{ -+ static const struct phy_reg phy_reg_init[] = { -+ { 0x1f, 0x0005 }, -+ { 0x1a, 0x0000 }, -+ { 0x1f, 0x0000 }, -+ -+ { 0x1f, 0x0004 }, -+ { 0x1c, 0x0000 }, -+ { 0x1f, 0x0000 }, -+ -+ { 0x1f, 0x0001 }, -+ { 0x15, 0x7701 }, -+ { 0x1f, 0x0000 } -+ }; -+ -+ /* Disable ALDPS before ram code */ -+ rtl_writephy(tp, 0x1f, 0x0000); -+ rtl_writephy(tp, 0x18, 0x0310); -+ msleep(100); -+ -+ rtl_apply_firmware(tp); -+ -+ rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -+} -+ -+static void rtl8402_hw_phy_config(struct rtl8169_private *tp) -+{ -+ /* Disable ALDPS before setting firmware */ -+ rtl_writephy(tp, 0x1f, 0x0000); -+ rtl_writephy(tp, 0x18, 0x0310); -+ msleep(20); -+ -+ rtl_apply_firmware(tp); -+ -+ /* EEE setting */ -+ rtl_eri_write(tp, 0x1b0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); -+ rtl_writephy(tp, 0x1f, 0x0004); -+ rtl_writephy(tp, 0x10, 0x401f); -+ rtl_writephy(tp, 0x19, 0x7030); -+ rtl_writephy(tp, 0x1f, 0x0000); -+} -+ -+static void rtl8106e_hw_phy_config(struct rtl8169_private *tp) -+{ -+ static const struct phy_reg phy_reg_init[] = { -+ { 0x1f, 0x0004 }, -+ { 0x10, 0xc07f }, -+ { 0x19, 0x7030 }, -+ { 0x1f, 0x0000 } -+ }; -+ -+ /* Disable ALDPS before ram code */ -+ rtl_writephy(tp, 0x1f, 0x0000); -+ rtl_writephy(tp, 0x18, 0x0310); -+ msleep(100); -+ -+ rtl_apply_firmware(tp); -+ -+ rtl_eri_write(tp, 0x1b0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); -+ rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -+ -+ rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); -+} -+ -+static void rtl_hw_phy_config(struct net_device *dev) -+{ -+ struct rtl8169_private *tp = netdev_priv(dev); -+ -+ rtl8169_print_mac_version(tp); -+ -+ switch (tp->mac_version) { -+ case RTL_GIGA_MAC_VER_01: -+ break; -+ case RTL_GIGA_MAC_VER_02: -+ case RTL_GIGA_MAC_VER_03: -+ rtl8169s_hw_phy_config(tp); -+ break; -+ case RTL_GIGA_MAC_VER_04: -+ rtl8169sb_hw_phy_config(tp); -+ break; -+ case RTL_GIGA_MAC_VER_05: -+ rtl8169scd_hw_phy_config(tp); -+ break; -+ case RTL_GIGA_MAC_VER_06: -+ rtl8169sce_hw_phy_config(tp); -+ break; -+ case RTL_GIGA_MAC_VER_07: -+ case RTL_GIGA_MAC_VER_08: -+ case RTL_GIGA_MAC_VER_09: -+ rtl8102e_hw_phy_config(tp); -+ break; -+ case RTL_GIGA_MAC_VER_11: -+ rtl8168bb_hw_phy_config(tp); -+ break; -+ case RTL_GIGA_MAC_VER_12: -+ rtl8168bef_hw_phy_config(tp); -+ break; -+ case RTL_GIGA_MAC_VER_17: -+ rtl8168bef_hw_phy_config(tp); -+ break; -+ case RTL_GIGA_MAC_VER_18: -+ rtl8168cp_1_hw_phy_config(tp); -+ break; -+ case RTL_GIGA_MAC_VER_19: -+ rtl8168c_1_hw_phy_config(tp); -+ break; -+ case RTL_GIGA_MAC_VER_20: -+ rtl8168c_2_hw_phy_config(tp); -+ break; -+ case RTL_GIGA_MAC_VER_21: -+ rtl8168c_3_hw_phy_config(tp); -+ break; -+ case RTL_GIGA_MAC_VER_22: -+ rtl8168c_4_hw_phy_config(tp); -+ break; -+ case RTL_GIGA_MAC_VER_23: -+ case RTL_GIGA_MAC_VER_24: -+ rtl8168cp_2_hw_phy_config(tp); -+ break; -+ case RTL_GIGA_MAC_VER_25: -+ rtl8168d_1_hw_phy_config(tp); -+ break; -+ case RTL_GIGA_MAC_VER_26: -+ rtl8168d_2_hw_phy_config(tp); -+ break; -+ case RTL_GIGA_MAC_VER_27: -+ rtl8168d_3_hw_phy_config(tp); -+ break; -+ case RTL_GIGA_MAC_VER_28: -+ rtl8168d_4_hw_phy_config(tp); -+ break; -+ case RTL_GIGA_MAC_VER_29: -+ case RTL_GIGA_MAC_VER_30: -+ rtl8105e_hw_phy_config(tp); -+ break; -+ case RTL_GIGA_MAC_VER_31: -+ /* None. */ -+ break; -+ case RTL_GIGA_MAC_VER_32: -+ case RTL_GIGA_MAC_VER_33: -+ rtl8168e_1_hw_phy_config(tp); -+ break; -+ case RTL_GIGA_MAC_VER_34: -+ rtl8168e_2_hw_phy_config(tp); -+ break; -+ case RTL_GIGA_MAC_VER_35: -+ rtl8168f_1_hw_phy_config(tp); -+ break; -+ case RTL_GIGA_MAC_VER_36: -+ rtl8168f_2_hw_phy_config(tp); -+ break; -+ -+ case RTL_GIGA_MAC_VER_37: -+ rtl8402_hw_phy_config(tp); -+ break; -+ -+ case RTL_GIGA_MAC_VER_38: -+ rtl8411_hw_phy_config(tp); -+ break; -+ -+ case RTL_GIGA_MAC_VER_39: -+ rtl8106e_hw_phy_config(tp); -+ break; -+ -+ case RTL_GIGA_MAC_VER_40: -+ rtl8168g_1_hw_phy_config(tp); -+ break; -+ -+ case RTL_GIGA_MAC_VER_41: -+ default: -+ break; -+ } -+} -+ -+static void rtl_phy_work(struct rtl8169_private *tp) -+{ -+ struct timer_list *timer = &tp->timer; -+ void __iomem *ioaddr = tp->mmio_addr; -+ unsigned long timeout = RTL8169_PHY_TIMEOUT; -+ -+ assert(tp->mac_version > RTL_GIGA_MAC_VER_01); -+ -+ if (tp->phy_reset_pending(tp)) { -+ /* -+ * A busy loop could burn quite a few cycles on nowadays CPU. -+ * Let's delay the execution of the timer for a few ticks. -+ */ -+ timeout = HZ/10; -+ goto out_mod_timer; -+ } -+ -+ if (tp->link_ok(ioaddr)) -+ return; -+ -+ netif_warn(tp, link, tp->dev, "PHY reset until link up\n"); -+ -+ tp->phy_reset_enable(tp); -+ -+out_mod_timer: -+ mod_timer(timer, jiffies + timeout); -+} -+ -+static void rtl_schedule_task(struct rtl8169_private *tp, enum rtl_flag flag) -+{ -+ if (!test_and_set_bit(flag, tp->wk.flags)) -+ schedule_work(&tp->wk.work); -+} -+ -+static void rtl8169_phy_timer(unsigned long __opaque) -+{ -+ struct net_device *dev = (struct net_device *)__opaque; -+ struct rtl8169_private *tp = netdev_priv(dev); -+ -+ rtl_schedule_task(tp, RTL_FLAG_TASK_PHY_PENDING); -+} -+ -+static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev, -+ void __iomem *ioaddr) -+{ -+ iounmap(ioaddr); -+ pci_release_regions(pdev); -+ pci_clear_mwi(pdev); -+ pci_disable_device(pdev); -+ free_netdev(dev); -+} -+ -+DECLARE_RTL_COND(rtl_phy_reset_cond) -+{ -+ return tp->phy_reset_pending(tp); -+} -+ -+static void rtl8169_phy_reset(struct net_device *dev, -+ struct rtl8169_private *tp) -+{ -+ tp->phy_reset_enable(tp); -+ rtl_msleep_loop_wait_low(tp, &rtl_phy_reset_cond, 1, 100); -+} -+ -+static bool rtl_tbi_enabled(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ return (tp->mac_version == RTL_GIGA_MAC_VER_01) && -+ (RTL_R8(PHYstatus) & TBI_Enable); -+} -+ -+static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ rtl_hw_phy_config(dev); -+ -+ if (tp->mac_version <= RTL_GIGA_MAC_VER_06) { -+ dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); -+ RTL_W8(0x82, 0x01); -+ } -+ -+ pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40); -+ -+ if (tp->mac_version <= RTL_GIGA_MAC_VER_06) -+ pci_write_config_byte(tp->pci_dev, PCI_CACHE_LINE_SIZE, 0x08); -+ -+ if (tp->mac_version == RTL_GIGA_MAC_VER_02) { -+ dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); -+ RTL_W8(0x82, 0x01); -+ dprintk("Set PHY Reg 0x0bh = 0x00h\n"); -+ rtl_writephy(tp, 0x0b, 0x0000); //w 0x0b 15 0 0 -+ } -+ -+ rtl8169_phy_reset(dev, tp); -+ -+ rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL, -+ ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | -+ ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | -+ (tp->mii.supports_gmii ? -+ ADVERTISED_1000baseT_Half | -+ ADVERTISED_1000baseT_Full : 0)); -+ -+ if (rtl_tbi_enabled(tp)) -+ netif_info(tp, link, dev, "TBI auto-negotiating\n"); -+} -+ -+static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ u32 high; -+ u32 low; -+ -+ low = addr[0] | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24); -+ high = addr[4] | (addr[5] << 8); -+ -+ rtl_lock_work(tp); -+ -+ RTL_W8(Cfg9346, Cfg9346_Unlock); -+ -+ RTL_W32(MAC4, high); -+ RTL_R32(MAC4); -+ -+ RTL_W32(MAC0, low); -+ RTL_R32(MAC0); -+ -+ if (tp->mac_version == RTL_GIGA_MAC_VER_34) { -+ const struct exgmac_reg e[] = { -+ { .addr = 0xe0, ERIAR_MASK_1111, .val = low }, -+ { .addr = 0xe4, ERIAR_MASK_1111, .val = high }, -+ { .addr = 0xf0, ERIAR_MASK_1111, .val = low << 16 }, -+ { .addr = 0xf4, ERIAR_MASK_1111, .val = high << 16 | -+ low >> 16 }, -+ }; -+ -+ rtl_write_exgmac_batch(tp, e, ARRAY_SIZE(e)); -+ } -+ -+ RTL_W8(Cfg9346, Cfg9346_Lock); -+ -+ rtl_unlock_work(tp); -+} -+ -+static int rtl_set_mac_address(struct net_device *dev, void *p) -+{ -+ struct rtl8169_private *tp = netdev_priv(dev); -+ struct sockaddr *addr = p; -+ -+ if (!is_valid_ether_addr(addr->sa_data)) -+ return -EADDRNOTAVAIL; -+ -+ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); -+ -+ rtl_rar_set(tp, dev->dev_addr); -+ -+ return 0; -+} -+ -+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); -+ -+ 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 */ -+ return 0; -+ -+ case SIOCGMIIREG: -+ data->val_out = rtl_readphy(tp, data->reg_num & 0x1f); -+ return 0; -+ -+ case SIOCSMIIREG: -+ rtl_writephy(tp, data->reg_num & 0x1f, data->val_in); -+ return 0; -+ } -+ return -EOPNOTSUPP; -+} -+ -+static int rtl_tbi_ioctl(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd) -+{ -+ return -EOPNOTSUPP; -+} -+ -+static void rtl_disable_msi(struct pci_dev *pdev, struct rtl8169_private *tp) -+{ -+ if (tp->features & RTL_FEATURE_MSI) { -+ pci_disable_msi(pdev); -+ tp->features &= ~RTL_FEATURE_MSI; -+ } -+} -+ -+static void __devinit rtl_init_mdio_ops(struct rtl8169_private *tp) -+{ -+ struct mdio_ops *ops = &tp->mdio_ops; -+ -+ switch (tp->mac_version) { -+ case RTL_GIGA_MAC_VER_27: -+ ops->write = r8168dp_1_mdio_write; -+ ops->read = r8168dp_1_mdio_read; -+ break; -+ case RTL_GIGA_MAC_VER_28: -+ case RTL_GIGA_MAC_VER_31: -+ ops->write = r8168dp_2_mdio_write; -+ ops->read = r8168dp_2_mdio_read; -+ break; -+ case RTL_GIGA_MAC_VER_40: -+ case RTL_GIGA_MAC_VER_41: -+ ops->write = r8168g_mdio_write; -+ ops->read = r8168g_mdio_read; -+ break; -+ default: -+ ops->write = r8169_mdio_write; -+ ops->read = r8169_mdio_read; -+ break; -+ } -+} -+ -+static void rtl_wol_suspend_quirk(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ switch (tp->mac_version) { -+ case RTL_GIGA_MAC_VER_29: -+ case RTL_GIGA_MAC_VER_30: -+ case RTL_GIGA_MAC_VER_32: -+ case RTL_GIGA_MAC_VER_33: -+ case RTL_GIGA_MAC_VER_34: -+ case RTL_GIGA_MAC_VER_37: -+ case RTL_GIGA_MAC_VER_38: -+ case RTL_GIGA_MAC_VER_39: -+ case RTL_GIGA_MAC_VER_40: -+ case RTL_GIGA_MAC_VER_41: -+ RTL_W32(RxConfig, RTL_R32(RxConfig) | -+ AcceptBroadcast | AcceptMulticast | AcceptMyPhys); -+ break; -+ default: -+ break; -+ } -+} -+ -+static bool rtl_wol_pll_power_down(struct rtl8169_private *tp) -+{ -+ if (!(__rtl8169_get_wol(tp) & WAKE_ANY)) -+ return false; -+ -+ rtl_writephy(tp, 0x1f, 0x0000); -+ rtl_writephy(tp, MII_BMCR, 0x0000); -+ -+ rtl_wol_suspend_quirk(tp); -+ -+ return true; -+} -+ -+static void r810x_phy_power_down(struct rtl8169_private *tp) -+{ -+ rtl_writephy(tp, 0x1f, 0x0000); -+ rtl_writephy(tp, MII_BMCR, BMCR_PDOWN); -+} -+ -+static void r810x_phy_power_up(struct rtl8169_private *tp) -+{ -+ rtl_writephy(tp, 0x1f, 0x0000); -+ rtl_writephy(tp, MII_BMCR, BMCR_ANENABLE); -+} -+ -+static void r810x_pll_power_down(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ if (rtl_wol_pll_power_down(tp)) -+ return; -+ -+ r810x_phy_power_down(tp); -+ -+ switch (tp->mac_version) { -+ case RTL_GIGA_MAC_VER_07: -+ case RTL_GIGA_MAC_VER_08: -+ case RTL_GIGA_MAC_VER_09: -+ case RTL_GIGA_MAC_VER_10: -+ case RTL_GIGA_MAC_VER_13: -+ case RTL_GIGA_MAC_VER_16: -+ break; -+ default: -+ RTL_W8(PMCH, RTL_R8(PMCH) & ~0x80); -+ break; -+ } -+} -+ -+static void r810x_pll_power_up(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ r810x_phy_power_up(tp); -+ -+ switch (tp->mac_version) { -+ case RTL_GIGA_MAC_VER_07: -+ case RTL_GIGA_MAC_VER_08: -+ case RTL_GIGA_MAC_VER_09: -+ case RTL_GIGA_MAC_VER_10: -+ case RTL_GIGA_MAC_VER_13: -+ case RTL_GIGA_MAC_VER_16: -+ break; -+ default: -+ RTL_W8(PMCH, RTL_R8(PMCH) | 0x80); -+ break; -+ } -+} -+ -+static void r8168_phy_power_up(struct rtl8169_private *tp) -+{ -+ rtl_writephy(tp, 0x1f, 0x0000); -+ switch (tp->mac_version) { -+ case RTL_GIGA_MAC_VER_11: -+ case RTL_GIGA_MAC_VER_12: -+ case RTL_GIGA_MAC_VER_17: -+ case RTL_GIGA_MAC_VER_18: -+ case RTL_GIGA_MAC_VER_19: -+ case RTL_GIGA_MAC_VER_20: -+ case RTL_GIGA_MAC_VER_21: -+ case RTL_GIGA_MAC_VER_22: -+ case RTL_GIGA_MAC_VER_23: -+ case RTL_GIGA_MAC_VER_24: -+ case RTL_GIGA_MAC_VER_25: -+ case RTL_GIGA_MAC_VER_26: -+ case RTL_GIGA_MAC_VER_27: -+ case RTL_GIGA_MAC_VER_28: -+ case RTL_GIGA_MAC_VER_31: -+ rtl_writephy(tp, 0x0e, 0x0000); -+ break; -+ default: -+ break; -+ } -+ rtl_writephy(tp, MII_BMCR, BMCR_ANENABLE); -+} -+ -+static void r8168_phy_power_down(struct rtl8169_private *tp) -+{ -+ rtl_writephy(tp, 0x1f, 0x0000); -+ switch (tp->mac_version) { -+ case RTL_GIGA_MAC_VER_32: -+ case RTL_GIGA_MAC_VER_33: -+ rtl_writephy(tp, MII_BMCR, BMCR_ANENABLE | BMCR_PDOWN); -+ break; -+ -+ case RTL_GIGA_MAC_VER_11: -+ case RTL_GIGA_MAC_VER_12: -+ case RTL_GIGA_MAC_VER_17: -+ case RTL_GIGA_MAC_VER_18: -+ case RTL_GIGA_MAC_VER_19: -+ case RTL_GIGA_MAC_VER_20: -+ case RTL_GIGA_MAC_VER_21: -+ case RTL_GIGA_MAC_VER_22: -+ case RTL_GIGA_MAC_VER_23: -+ case RTL_GIGA_MAC_VER_24: -+ case RTL_GIGA_MAC_VER_25: -+ case RTL_GIGA_MAC_VER_26: -+ case RTL_GIGA_MAC_VER_27: -+ case RTL_GIGA_MAC_VER_28: -+ case RTL_GIGA_MAC_VER_31: -+ rtl_writephy(tp, 0x0e, 0x0200); -+ default: -+ rtl_writephy(tp, MII_BMCR, BMCR_PDOWN); -+ break; -+ } -+} -+ -+static void r8168_pll_power_down(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ if ((tp->mac_version == RTL_GIGA_MAC_VER_27 || -+ tp->mac_version == RTL_GIGA_MAC_VER_28 || -+ tp->mac_version == RTL_GIGA_MAC_VER_31) && -+ r8168dp_check_dash(tp)) { -+ return; -+ } -+ -+ if ((tp->mac_version == RTL_GIGA_MAC_VER_23 || -+ tp->mac_version == RTL_GIGA_MAC_VER_24) && -+ (RTL_R16(CPlusCmd) & ASF)) { -+ return; -+ } -+ -+ if (tp->mac_version == RTL_GIGA_MAC_VER_32 || -+ tp->mac_version == RTL_GIGA_MAC_VER_33) -+ rtl_ephy_write(tp, 0x19, 0xff64); -+ -+ if (rtl_wol_pll_power_down(tp)) -+ return; -+ -+ r8168_phy_power_down(tp); -+ -+ switch (tp->mac_version) { -+ case RTL_GIGA_MAC_VER_25: -+ case RTL_GIGA_MAC_VER_26: -+ case RTL_GIGA_MAC_VER_27: -+ case RTL_GIGA_MAC_VER_28: -+ case RTL_GIGA_MAC_VER_31: -+ case RTL_GIGA_MAC_VER_32: -+ case RTL_GIGA_MAC_VER_33: -+ RTL_W8(PMCH, RTL_R8(PMCH) & ~0x80); -+ break; -+ } -+} -+ -+static void r8168_pll_power_up(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ switch (tp->mac_version) { -+ case RTL_GIGA_MAC_VER_25: -+ case RTL_GIGA_MAC_VER_26: -+ case RTL_GIGA_MAC_VER_27: -+ case RTL_GIGA_MAC_VER_28: -+ case RTL_GIGA_MAC_VER_31: -+ case RTL_GIGA_MAC_VER_32: -+ case RTL_GIGA_MAC_VER_33: -+ RTL_W8(PMCH, RTL_R8(PMCH) | 0x80); -+ break; -+ } -+ -+ r8168_phy_power_up(tp); -+} -+ -+static void rtl_generic_op(struct rtl8169_private *tp, -+ void (*op)(struct rtl8169_private *)) -+{ -+ if (op) -+ op(tp); -+} -+ -+static void rtl_pll_power_down(struct rtl8169_private *tp) -+{ -+ rtl_generic_op(tp, tp->pll_power_ops.down); -+} -+ -+static void rtl_pll_power_up(struct rtl8169_private *tp) -+{ -+ rtl_generic_op(tp, tp->pll_power_ops.up); -+} -+ -+static void __devinit rtl_init_pll_power_ops(struct rtl8169_private *tp) -+{ -+ struct pll_power_ops *ops = &tp->pll_power_ops; -+ -+ switch (tp->mac_version) { -+ case RTL_GIGA_MAC_VER_07: -+ case RTL_GIGA_MAC_VER_08: -+ case RTL_GIGA_MAC_VER_09: -+ case RTL_GIGA_MAC_VER_10: -+ case RTL_GIGA_MAC_VER_16: -+ case RTL_GIGA_MAC_VER_29: -+ case RTL_GIGA_MAC_VER_30: -+ case RTL_GIGA_MAC_VER_37: -+ case RTL_GIGA_MAC_VER_39: -+ ops->down = r810x_pll_power_down; -+ ops->up = r810x_pll_power_up; -+ break; -+ -+ case RTL_GIGA_MAC_VER_11: -+ case RTL_GIGA_MAC_VER_12: -+ case RTL_GIGA_MAC_VER_17: -+ case RTL_GIGA_MAC_VER_18: -+ case RTL_GIGA_MAC_VER_19: -+ case RTL_GIGA_MAC_VER_20: -+ case RTL_GIGA_MAC_VER_21: -+ case RTL_GIGA_MAC_VER_22: -+ case RTL_GIGA_MAC_VER_23: -+ case RTL_GIGA_MAC_VER_24: -+ case RTL_GIGA_MAC_VER_25: -+ case RTL_GIGA_MAC_VER_26: -+ case RTL_GIGA_MAC_VER_27: -+ case RTL_GIGA_MAC_VER_28: -+ case RTL_GIGA_MAC_VER_31: -+ case RTL_GIGA_MAC_VER_32: -+ case RTL_GIGA_MAC_VER_33: -+ case RTL_GIGA_MAC_VER_34: -+ case RTL_GIGA_MAC_VER_35: -+ case RTL_GIGA_MAC_VER_36: -+ case RTL_GIGA_MAC_VER_38: -+ case RTL_GIGA_MAC_VER_40: -+ case RTL_GIGA_MAC_VER_41: -+ ops->down = r8168_pll_power_down; -+ ops->up = r8168_pll_power_up; -+ break; -+ -+ default: -+ ops->down = NULL; -+ ops->up = NULL; -+ break; -+ } -+} -+ -+static void rtl_init_rxcfg(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ switch (tp->mac_version) { -+ case RTL_GIGA_MAC_VER_01: -+ case RTL_GIGA_MAC_VER_02: -+ case RTL_GIGA_MAC_VER_03: -+ case RTL_GIGA_MAC_VER_04: -+ case RTL_GIGA_MAC_VER_05: -+ case RTL_GIGA_MAC_VER_06: -+ case RTL_GIGA_MAC_VER_10: -+ case RTL_GIGA_MAC_VER_11: -+ case RTL_GIGA_MAC_VER_12: -+ case RTL_GIGA_MAC_VER_13: -+ case RTL_GIGA_MAC_VER_14: -+ case RTL_GIGA_MAC_VER_15: -+ case RTL_GIGA_MAC_VER_16: -+ case RTL_GIGA_MAC_VER_17: -+ RTL_W32(RxConfig, RX_FIFO_THRESH | RX_DMA_BURST); -+ break; -+ case RTL_GIGA_MAC_VER_18: -+ case RTL_GIGA_MAC_VER_19: -+ case RTL_GIGA_MAC_VER_20: -+ case RTL_GIGA_MAC_VER_21: -+ case RTL_GIGA_MAC_VER_22: -+ case RTL_GIGA_MAC_VER_23: -+ case RTL_GIGA_MAC_VER_24: -+ case RTL_GIGA_MAC_VER_34: -+ RTL_W32(RxConfig, RX128_INT_EN | RX_MULTI_EN | RX_DMA_BURST); -+ break; -+ default: -+ RTL_W32(RxConfig, RX128_INT_EN | RX_DMA_BURST); -+ break; -+ } -+} -+ -+static void rtl8169_init_ring_indexes(struct rtl8169_private *tp) -+{ -+ tp->dirty_tx = tp->dirty_rx = tp->cur_tx = tp->cur_rx = 0; -+} -+ -+static void rtl_hw_jumbo_enable(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ RTL_W8(Cfg9346, Cfg9346_Unlock); -+ rtl_generic_op(tp, tp->jumbo_ops.enable); -+ RTL_W8(Cfg9346, Cfg9346_Lock); -+} -+ -+static void rtl_hw_jumbo_disable(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ RTL_W8(Cfg9346, Cfg9346_Unlock); -+ rtl_generic_op(tp, tp->jumbo_ops.disable); -+ RTL_W8(Cfg9346, Cfg9346_Lock); -+} -+ -+static void r8168c_hw_jumbo_enable(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0); -+ RTL_W8(Config4, RTL_R8(Config4) | Jumbo_En1); -+ rtl_tx_performance_tweak(tp->pci_dev, 0x2 << MAX_READ_REQUEST_SHIFT); -+} -+ -+static void r8168c_hw_jumbo_disable(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0); -+ RTL_W8(Config4, RTL_R8(Config4) & ~Jumbo_En1); -+ rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT); -+} -+ -+static void r8168dp_hw_jumbo_enable(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0); -+} -+ -+static void r8168dp_hw_jumbo_disable(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0); -+} -+ -+static void r8168e_hw_jumbo_enable(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ RTL_W8(MaxTxPacketSize, 0x3f); -+ RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0); -+ RTL_W8(Config4, RTL_R8(Config4) | 0x01); -+ rtl_tx_performance_tweak(tp->pci_dev, 0x2 << MAX_READ_REQUEST_SHIFT); -+} -+ -+static void r8168e_hw_jumbo_disable(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ RTL_W8(MaxTxPacketSize, 0x0c); -+ RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0); -+ RTL_W8(Config4, RTL_R8(Config4) & ~0x01); -+ rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT); -+} -+ -+static void r8168b_0_hw_jumbo_enable(struct rtl8169_private *tp) -+{ -+ rtl_tx_performance_tweak(tp->pci_dev, -+ (0x2 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN); -+} -+ -+static void r8168b_0_hw_jumbo_disable(struct rtl8169_private *tp) -+{ -+ rtl_tx_performance_tweak(tp->pci_dev, -+ (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN); -+} -+ -+static void r8168b_1_hw_jumbo_enable(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ r8168b_0_hw_jumbo_enable(tp); -+ -+ RTL_W8(Config4, RTL_R8(Config4) | (1 << 0)); -+} -+ -+static void r8168b_1_hw_jumbo_disable(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ r8168b_0_hw_jumbo_disable(tp); -+ -+ RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0)); -+} -+ -+static void __devinit rtl_init_jumbo_ops(struct rtl8169_private *tp) -+{ -+ struct jumbo_ops *ops = &tp->jumbo_ops; -+ -+ switch (tp->mac_version) { -+ case RTL_GIGA_MAC_VER_11: -+ ops->disable = r8168b_0_hw_jumbo_disable; -+ ops->enable = r8168b_0_hw_jumbo_enable; -+ break; -+ case RTL_GIGA_MAC_VER_12: -+ case RTL_GIGA_MAC_VER_17: -+ ops->disable = r8168b_1_hw_jumbo_disable; -+ ops->enable = r8168b_1_hw_jumbo_enable; -+ break; -+ case RTL_GIGA_MAC_VER_18: /* Wild guess. Needs info from Realtek. */ -+ case RTL_GIGA_MAC_VER_19: -+ case RTL_GIGA_MAC_VER_20: -+ case RTL_GIGA_MAC_VER_21: /* Wild guess. Needs info from Realtek. */ -+ case RTL_GIGA_MAC_VER_22: -+ case RTL_GIGA_MAC_VER_23: -+ case RTL_GIGA_MAC_VER_24: -+ case RTL_GIGA_MAC_VER_25: -+ case RTL_GIGA_MAC_VER_26: -+ ops->disable = r8168c_hw_jumbo_disable; -+ ops->enable = r8168c_hw_jumbo_enable; -+ break; -+ case RTL_GIGA_MAC_VER_27: -+ case RTL_GIGA_MAC_VER_28: -+ ops->disable = r8168dp_hw_jumbo_disable; -+ ops->enable = r8168dp_hw_jumbo_enable; -+ break; -+ case RTL_GIGA_MAC_VER_31: /* Wild guess. Needs info from Realtek. */ -+ case RTL_GIGA_MAC_VER_32: -+ case RTL_GIGA_MAC_VER_33: -+ case RTL_GIGA_MAC_VER_34: -+ ops->disable = r8168e_hw_jumbo_disable; -+ ops->enable = r8168e_hw_jumbo_enable; -+ break; -+ -+ /* -+ * No action needed for jumbo frames with 8169. -+ * No jumbo for 810x at all. -+ */ -+ case RTL_GIGA_MAC_VER_40: -+ case RTL_GIGA_MAC_VER_41: -+ default: -+ ops->disable = NULL; -+ ops->enable = NULL; -+ break; -+ } -+} -+ -+DECLARE_RTL_COND(rtl_chipcmd_cond) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ return RTL_R8(ChipCmd) & CmdReset; -+} -+ -+static void rtl_hw_reset(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ RTL_W8(ChipCmd, CmdReset); -+ -+ rtl_udelay_loop_wait_low(tp, &rtl_chipcmd_cond, 100, 100); -+} -+ -+static void rtl_request_uncached_firmware(struct rtl8169_private *tp) -+{ -+ struct rtl_fw *rtl_fw; -+ const char *name; -+ int rc = -ENOMEM; -+ -+ name = rtl_lookup_firmware_name(tp); -+ if (!name) -+ goto out_no_firmware; -+ -+ rtl_fw = kzalloc(sizeof(*rtl_fw), GFP_KERNEL); -+ if (!rtl_fw) -+ goto err_warn; -+ -+ rc = request_firmware(&rtl_fw->fw, name, &tp->pci_dev->dev); -+ if (rc < 0) -+ goto err_free; -+ -+ rc = rtl_check_firmware(tp, rtl_fw); -+ if (rc < 0) -+ goto err_release_firmware; -+ -+ tp->rtl_fw = rtl_fw; -+out: -+ return; -+ -+err_release_firmware: -+ release_firmware(rtl_fw->fw); -+err_free: -+ kfree(rtl_fw); -+err_warn: -+ netif_warn(tp, ifup, tp->dev, "unable to load firmware patch %s (%d)\n", -+ name, rc); -+out_no_firmware: -+ tp->rtl_fw = NULL; -+ goto out; -+} -+ -+static void rtl_request_firmware(struct rtl8169_private *tp) -+{ -+ if (IS_ERR(tp->rtl_fw)) -+ rtl_request_uncached_firmware(tp); -+} -+ -+static void rtl_rx_close(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ RTL_W32(RxConfig, RTL_R32(RxConfig) & ~RX_CONFIG_ACCEPT_MASK); -+} -+ -+DECLARE_RTL_COND(rtl_npq_cond) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ return RTL_R8(TxPoll) & NPQ; -+} -+ -+DECLARE_RTL_COND(rtl_txcfg_empty_cond) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ return RTL_R32(TxConfig) & TXCFG_EMPTY; -+} -+ -+static void rtl8169_hw_reset(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ /* Disable interrupts */ -+ rtl8169_irq_mask_and_ack(tp); -+ -+ rtl_rx_close(tp); -+ -+ if (tp->mac_version == RTL_GIGA_MAC_VER_27 || -+ tp->mac_version == RTL_GIGA_MAC_VER_28 || -+ tp->mac_version == RTL_GIGA_MAC_VER_31) { -+ rtl_udelay_loop_wait_low(tp, &rtl_npq_cond, 20, 42*42); -+ } else if (tp->mac_version == RTL_GIGA_MAC_VER_34 || -+ tp->mac_version == RTL_GIGA_MAC_VER_35 || -+ tp->mac_version == RTL_GIGA_MAC_VER_36 || -+ tp->mac_version == RTL_GIGA_MAC_VER_37 || -+ tp->mac_version == RTL_GIGA_MAC_VER_40 || -+ tp->mac_version == RTL_GIGA_MAC_VER_41 || -+ tp->mac_version == RTL_GIGA_MAC_VER_38) { -+ RTL_W8(ChipCmd, RTL_R8(ChipCmd) | StopReq); -+ rtl_udelay_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 666); -+ } else { -+ RTL_W8(ChipCmd, RTL_R8(ChipCmd) | StopReq); -+ udelay(100); -+ } -+ -+ rtl_hw_reset(tp); -+} -+ -+static void rtl_set_rx_tx_config_registers(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ /* Set DMA burst size and Interframe Gap Time */ -+ RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | -+ (InterFrameGap << TxInterFrameGapShift)); -+} -+ -+static void rtl_hw_start(struct net_device *dev) -+{ -+ struct rtl8169_private *tp = netdev_priv(dev); -+ -+ tp->hw_start(dev); -+ -+ rtl_irq_enable_all(tp); -+} -+ -+static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp, -+ void __iomem *ioaddr) -+{ -+ /* -+ * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh -+ * register to be written before TxDescAddrLow to work. -+ * 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(RxDescAddrHigh, ((u64) tp->RxPhyAddr) >> 32); -+ RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr) & DMA_BIT_MASK(32)); -+} -+ -+static u16 rtl_rw_cpluscmd(void __iomem *ioaddr) -+{ -+ u16 cmd; -+ -+ cmd = RTL_R16(CPlusCmd); -+ RTL_W16(CPlusCmd, cmd); -+ return cmd; -+} -+ -+static void rtl_set_rx_max_size(void __iomem *ioaddr, unsigned int rx_buf_sz) -+{ -+ /* Low hurts. Let's disable the filtering. */ -+ RTL_W16(RxMaxSize, rx_buf_sz + 1); -+} -+ -+static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version) -+{ -+ static const struct rtl_cfg2_info { -+ u32 mac_version; -+ u32 clk; -+ u32 val; -+ } cfg2_info [] = { -+ { RTL_GIGA_MAC_VER_05, PCI_Clock_33MHz, 0x000fff00 }, // 8110SCd -+ { RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff }, -+ { RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe -+ { RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff } -+ }; -+ const struct rtl_cfg2_info *p = cfg2_info; -+ unsigned int i; -+ u32 clk; -+ -+ clk = RTL_R8(Config2) & PCI_Clock_66MHz; -+ for (i = 0; i < ARRAY_SIZE(cfg2_info); i++, p++) { -+ if ((p->mac_version == mac_version) && (p->clk == clk)) { -+ RTL_W32(0x7c, p->val); -+ break; -+ } -+ } -+} -+ -+static void rtl_set_rx_mode(struct net_device *dev) -+{ -+ struct rtl8169_private *tp = netdev_priv(dev); -+ void __iomem *ioaddr = tp->mmio_addr; -+ u32 mc_filter[2]; /* Multicast hash filter */ -+ int rx_mode; -+ u32 tmp = 0; -+ -+ if (dev->flags & IFF_PROMISC) { -+ /* Unconditionally log net taps. */ -+ netif_notice(tp, link, dev, "Promiscuous mode enabled\n"); -+ rx_mode = -+ AcceptBroadcast | AcceptMulticast | AcceptMyPhys | -+ AcceptAllPhys; -+ mc_filter[1] = mc_filter[0] = 0xffffffff; -+ } 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 netdev_hw_addr *ha; -+ -+ rx_mode = AcceptBroadcast | AcceptMyPhys; -+ mc_filter[1] = mc_filter[0] = 0; -+ 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; -+ } -+ } -+ -+ if (dev->features & NETIF_F_RXALL) -+ rx_mode |= (AcceptErr | AcceptRunt); -+ -+ tmp = (RTL_R32(RxConfig) & ~RX_CONFIG_ACCEPT_MASK) | rx_mode; -+ -+ if (tp->mac_version > RTL_GIGA_MAC_VER_06) { -+ u32 data = mc_filter[0]; -+ -+ mc_filter[0] = swab32(mc_filter[1]); -+ mc_filter[1] = swab32(data); -+ } -+ -+ RTL_W32(MAR0 + 4, mc_filter[1]); -+ RTL_W32(MAR0 + 0, mc_filter[0]); -+ -+ RTL_W32(RxConfig, tmp); -+} -+ -+static void rtl_hw_start_8169(struct net_device *dev) -+{ -+ struct rtl8169_private *tp = netdev_priv(dev); -+ void __iomem *ioaddr = tp->mmio_addr; -+ struct pci_dev *pdev = tp->pci_dev; -+ -+ 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); -+ } -+ -+ RTL_W8(Cfg9346, Cfg9346_Unlock); -+ if (tp->mac_version == RTL_GIGA_MAC_VER_01 || -+ tp->mac_version == RTL_GIGA_MAC_VER_02 || -+ tp->mac_version == RTL_GIGA_MAC_VER_03 || -+ tp->mac_version == RTL_GIGA_MAC_VER_04) -+ RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); -+ -+ rtl_init_rxcfg(tp); -+ -+ RTL_W8(EarlyTxThres, NoEarlyTx); -+ -+ rtl_set_rx_max_size(ioaddr, rx_buf_sz); -+ -+ if (tp->mac_version == RTL_GIGA_MAC_VER_01 || -+ tp->mac_version == RTL_GIGA_MAC_VER_02 || -+ tp->mac_version == RTL_GIGA_MAC_VER_03 || -+ tp->mac_version == RTL_GIGA_MAC_VER_04) -+ rtl_set_rx_tx_config_registers(tp); -+ -+ tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; -+ -+ if (tp->mac_version == RTL_GIGA_MAC_VER_02 || -+ tp->mac_version == RTL_GIGA_MAC_VER_03) { -+ dprintk("Set MAC Reg C+CR Offset 0xE0. " -+ "Bit-3 and bit-14 MUST be 1\n"); -+ tp->cp_cmd |= (1 << 14); -+ } -+ -+ RTL_W16(CPlusCmd, tp->cp_cmd); -+ -+ rtl8169_set_magic_reg(ioaddr, tp->mac_version); -+ -+ /* -+ * Undocumented corner. Supposedly: -+ * (TxTimer << 12) | (TxPackets << 8) | (RxTimer << 4) | RxPackets -+ */ -+ RTL_W16(IntrMitigate, 0x0000); -+ -+ rtl_set_rx_tx_desc_registers(tp, ioaddr); -+ -+ if (tp->mac_version != RTL_GIGA_MAC_VER_01 && -+ tp->mac_version != RTL_GIGA_MAC_VER_02 && -+ tp->mac_version != RTL_GIGA_MAC_VER_03 && -+ tp->mac_version != RTL_GIGA_MAC_VER_04) { -+ RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); -+ rtl_set_rx_tx_config_registers(tp); -+ } -+ -+ RTL_W8(Cfg9346, Cfg9346_Lock); -+ -+ /* Initially a 10 us delay. Turned it into a PCI commit. - FR */ -+ RTL_R8(IntrMask); -+ -+ RTL_W32(RxMissed, 0); -+ -+ rtl_set_rx_mode(dev); -+ -+ /* no early-rx interrupts */ -+ RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); -+} -+ -+static void rtl_csi_write(struct rtl8169_private *tp, int addr, int value) -+{ -+ if (tp->csi_ops.write) -+ tp->csi_ops.write(tp, addr, value); -+} -+ -+static u32 rtl_csi_read(struct rtl8169_private *tp, int addr) -+{ -+ return tp->csi_ops.read ? tp->csi_ops.read(tp, addr) : ~0; -+} -+ -+static void rtl_csi_access_enable(struct rtl8169_private *tp, u32 bits) -+{ -+ u32 csi; -+ -+ csi = rtl_csi_read(tp, 0x070c) & 0x00ffffff; -+ rtl_csi_write(tp, 0x070c, csi | bits); -+} -+ -+static void rtl_csi_access_enable_1(struct rtl8169_private *tp) -+{ -+ rtl_csi_access_enable(tp, 0x17000000); -+} -+ -+static void rtl_csi_access_enable_2(struct rtl8169_private *tp) -+{ -+ rtl_csi_access_enable(tp, 0x27000000); -+} -+ -+DECLARE_RTL_COND(rtl_csiar_cond) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ return RTL_R32(CSIAR) & CSIAR_FLAG; -+} -+ -+static void r8169_csi_write(struct rtl8169_private *tp, int addr, int value) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ RTL_W32(CSIDR, value); -+ RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) | -+ CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); -+ -+ rtl_udelay_loop_wait_low(tp, &rtl_csiar_cond, 10, 100); -+} -+ -+static u32 r8169_csi_read(struct rtl8169_private *tp, int addr) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) | -+ CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); -+ -+ return rtl_udelay_loop_wait_high(tp, &rtl_csiar_cond, 10, 100) ? -+ RTL_R32(CSIDR) : ~0; -+} -+ -+static void r8402_csi_write(struct rtl8169_private *tp, int addr, int value) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ RTL_W32(CSIDR, value); -+ RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) | -+ CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT | -+ CSIAR_FUNC_NIC); -+ -+ rtl_udelay_loop_wait_low(tp, &rtl_csiar_cond, 10, 100); -+} -+ -+static u32 r8402_csi_read(struct rtl8169_private *tp, int addr) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) | CSIAR_FUNC_NIC | -+ CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); -+ -+ return rtl_udelay_loop_wait_high(tp, &rtl_csiar_cond, 10, 100) ? -+ RTL_R32(CSIDR) : ~0; -+} -+ -+static void __devinit rtl_init_csi_ops(struct rtl8169_private *tp) -+{ -+ struct csi_ops *ops = &tp->csi_ops; -+ -+ switch (tp->mac_version) { -+ case RTL_GIGA_MAC_VER_01: -+ case RTL_GIGA_MAC_VER_02: -+ case RTL_GIGA_MAC_VER_03: -+ case RTL_GIGA_MAC_VER_04: -+ case RTL_GIGA_MAC_VER_05: -+ case RTL_GIGA_MAC_VER_06: -+ case RTL_GIGA_MAC_VER_10: -+ case RTL_GIGA_MAC_VER_11: -+ case RTL_GIGA_MAC_VER_12: -+ case RTL_GIGA_MAC_VER_13: -+ case RTL_GIGA_MAC_VER_14: -+ case RTL_GIGA_MAC_VER_15: -+ case RTL_GIGA_MAC_VER_16: -+ case RTL_GIGA_MAC_VER_17: -+ ops->write = NULL; -+ ops->read = NULL; -+ break; -+ -+ case RTL_GIGA_MAC_VER_37: -+ case RTL_GIGA_MAC_VER_38: -+ ops->write = r8402_csi_write; -+ ops->read = r8402_csi_read; -+ break; -+ -+ default: -+ ops->write = r8169_csi_write; -+ ops->read = r8169_csi_read; -+ break; -+ } -+} -+ -+struct ephy_info { -+ unsigned int offset; -+ u16 mask; -+ u16 bits; -+}; -+ -+static void rtl_ephy_init(struct rtl8169_private *tp, const struct ephy_info *e, -+ int len) -+{ -+ u16 w; -+ -+ while (len-- > 0) { -+ w = (rtl_ephy_read(tp, e->offset) & ~e->mask) | e->bits; -+ rtl_ephy_write(tp, e->offset, w); -+ e++; -+ } -+} -+ -+static void rtl_disable_clock_request(struct pci_dev *pdev) -+{ -+ int cap = pci_pcie_cap(pdev); -+ -+ if (cap) { -+ u16 ctl; -+ -+ pci_read_config_word(pdev, cap + PCI_EXP_LNKCTL, &ctl); -+ ctl &= ~PCI_EXP_LNKCTL_CLKREQ_EN; -+ pci_write_config_word(pdev, cap + PCI_EXP_LNKCTL, ctl); -+ } -+} -+ -+static void rtl_enable_clock_request(struct pci_dev *pdev) -+{ -+ int cap = pci_pcie_cap(pdev); -+ -+ if (cap) { -+ u16 ctl; -+ -+ pci_read_config_word(pdev, cap + PCI_EXP_LNKCTL, &ctl); -+ ctl |= PCI_EXP_LNKCTL_CLKREQ_EN; -+ pci_write_config_word(pdev, cap + PCI_EXP_LNKCTL, ctl); -+ } -+} -+ -+#define R8168_CPCMD_QUIRK_MASK (\ -+ EnableBist | \ -+ Mac_dbgo_oe | \ -+ Force_half_dup | \ -+ Force_rxflow_en | \ -+ Force_txflow_en | \ -+ Cxpl_dbg_sel | \ -+ ASF | \ -+ PktCntrDisable | \ -+ Mac_dbgo_sel) -+ -+static void rtl_hw_start_8168bb(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ struct pci_dev *pdev = tp->pci_dev; -+ -+ RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); -+ -+ RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -+ -+ rtl_tx_performance_tweak(pdev, -+ (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN); -+} -+ -+static void rtl_hw_start_8168bef(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ rtl_hw_start_8168bb(tp); -+ -+ RTL_W8(MaxTxPacketSize, TxPacketMax); -+ -+ RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0)); -+} -+ -+static void __rtl_hw_start_8168cp(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ struct pci_dev *pdev = tp->pci_dev; -+ -+ RTL_W8(Config1, RTL_R8(Config1) | Speed_down); -+ -+ RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); -+ -+ rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); -+ -+ rtl_disable_clock_request(pdev); -+ -+ RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -+} -+ -+static void rtl_hw_start_8168cp_1(struct rtl8169_private *tp) -+{ -+ static const struct ephy_info e_info_8168cp[] = { -+ { 0x01, 0, 0x0001 }, -+ { 0x02, 0x0800, 0x1000 }, -+ { 0x03, 0, 0x0042 }, -+ { 0x06, 0x0080, 0x0000 }, -+ { 0x07, 0, 0x2000 } -+ }; -+ -+ rtl_csi_access_enable_2(tp); -+ -+ rtl_ephy_init(tp, e_info_8168cp, ARRAY_SIZE(e_info_8168cp)); -+ -+ __rtl_hw_start_8168cp(tp); -+} -+ -+static void rtl_hw_start_8168cp_2(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ struct pci_dev *pdev = tp->pci_dev; -+ -+ rtl_csi_access_enable_2(tp); -+ -+ 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(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ struct pci_dev *pdev = tp->pci_dev; -+ -+ rtl_csi_access_enable_2(tp); -+ -+ RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); -+ -+ /* Magic. */ -+ RTL_W8(DBG_REG, 0x20); -+ -+ RTL_W8(MaxTxPacketSize, TxPacketMax); -+ -+ 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(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ static const struct ephy_info e_info_8168c_1[] = { -+ { 0x02, 0x0800, 0x1000 }, -+ { 0x03, 0, 0x0002 }, -+ { 0x06, 0x0080, 0x0000 } -+ }; -+ -+ rtl_csi_access_enable_2(tp); -+ -+ RTL_W8(DBG_REG, 0x06 | FIX_NAK_1 | FIX_NAK_2); -+ -+ rtl_ephy_init(tp, e_info_8168c_1, ARRAY_SIZE(e_info_8168c_1)); -+ -+ __rtl_hw_start_8168cp(tp); -+} -+ -+static void rtl_hw_start_8168c_2(struct rtl8169_private *tp) -+{ -+ static const struct ephy_info e_info_8168c_2[] = { -+ { 0x01, 0, 0x0001 }, -+ { 0x03, 0x0400, 0x0220 } -+ }; -+ -+ rtl_csi_access_enable_2(tp); -+ -+ rtl_ephy_init(tp, e_info_8168c_2, ARRAY_SIZE(e_info_8168c_2)); -+ -+ __rtl_hw_start_8168cp(tp); -+} -+ -+static void rtl_hw_start_8168c_3(struct rtl8169_private *tp) -+{ -+ rtl_hw_start_8168c_2(tp); -+} -+ -+static void rtl_hw_start_8168c_4(struct rtl8169_private *tp) -+{ -+ rtl_csi_access_enable_2(tp); -+ -+ __rtl_hw_start_8168cp(tp); -+} -+ -+static void rtl_hw_start_8168d(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ struct pci_dev *pdev = tp->pci_dev; -+ -+ rtl_csi_access_enable_2(tp); -+ -+ rtl_disable_clock_request(pdev); -+ -+ RTL_W8(MaxTxPacketSize, TxPacketMax); -+ -+ 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_8168dp(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ struct pci_dev *pdev = tp->pci_dev; -+ -+ rtl_csi_access_enable_1(tp); -+ -+ rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); -+ -+ RTL_W8(MaxTxPacketSize, TxPacketMax); -+ -+ rtl_disable_clock_request(pdev); -+} -+ -+static void rtl_hw_start_8168d_4(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ struct pci_dev *pdev = tp->pci_dev; -+ static const struct ephy_info e_info_8168d_4[] = { -+ { 0x0b, ~0, 0x48 }, -+ { 0x19, 0x20, 0x50 }, -+ { 0x0c, ~0, 0x20 } -+ }; -+ int i; -+ -+ rtl_csi_access_enable_1(tp); -+ -+ rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); -+ -+ RTL_W8(MaxTxPacketSize, TxPacketMax); -+ -+ for (i = 0; i < ARRAY_SIZE(e_info_8168d_4); i++) { -+ const struct ephy_info *e = e_info_8168d_4 + i; -+ u16 w; -+ -+ w = rtl_ephy_read(tp, e->offset); -+ rtl_ephy_write(tp, 0x03, (w & e->mask) | e->bits); -+ } -+ -+ rtl_enable_clock_request(pdev); -+} -+ -+static void rtl_hw_start_8168e_1(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ struct pci_dev *pdev = tp->pci_dev; -+ static const struct ephy_info e_info_8168e_1[] = { -+ { 0x00, 0x0200, 0x0100 }, -+ { 0x00, 0x0000, 0x0004 }, -+ { 0x06, 0x0002, 0x0001 }, -+ { 0x06, 0x0000, 0x0030 }, -+ { 0x07, 0x0000, 0x2000 }, -+ { 0x00, 0x0000, 0x0020 }, -+ { 0x03, 0x5800, 0x2000 }, -+ { 0x03, 0x0000, 0x0001 }, -+ { 0x01, 0x0800, 0x1000 }, -+ { 0x07, 0x0000, 0x4000 }, -+ { 0x1e, 0x0000, 0x2000 }, -+ { 0x19, 0xffff, 0xfe6c }, -+ { 0x0a, 0x0000, 0x0040 } -+ }; -+ -+ rtl_csi_access_enable_2(tp); -+ -+ rtl_ephy_init(tp, e_info_8168e_1, ARRAY_SIZE(e_info_8168e_1)); -+ -+ rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); -+ -+ RTL_W8(MaxTxPacketSize, TxPacketMax); -+ -+ rtl_disable_clock_request(pdev); -+ -+ /* Reset tx FIFO pointer */ -+ RTL_W32(MISC, RTL_R32(MISC) | TXPLA_RST); -+ RTL_W32(MISC, RTL_R32(MISC) & ~TXPLA_RST); -+ -+ RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en); -+} -+ -+static void rtl_hw_start_8168e_2(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ struct pci_dev *pdev = tp->pci_dev; -+ static const struct ephy_info e_info_8168e_2[] = { -+ { 0x09, 0x0000, 0x0080 }, -+ { 0x19, 0x0000, 0x0224 } -+ }; -+ -+ rtl_csi_access_enable_1(tp); -+ -+ rtl_ephy_init(tp, e_info_8168e_2, ARRAY_SIZE(e_info_8168e_2)); -+ -+ rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); -+ -+ rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); -+ rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); -+ rtl_eri_write(tp, 0xc8, ERIAR_MASK_1111, 0x00100002, ERIAR_EXGMAC); -+ rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC); -+ rtl_eri_write(tp, 0xcc, ERIAR_MASK_1111, 0x00000050, ERIAR_EXGMAC); -+ rtl_eri_write(tp, 0xd0, ERIAR_MASK_1111, 0x07ff0060, ERIAR_EXGMAC); -+ rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC); -+ rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0xff00, ERIAR_EXGMAC); -+ -+ RTL_W8(MaxTxPacketSize, EarlySize); -+ -+ rtl_disable_clock_request(pdev); -+ -+ RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO); -+ RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB); -+ -+ /* Adjust EEE LED frequency */ -+ RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07); -+ -+ RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN); -+ RTL_W32(MISC, RTL_R32(MISC) | PWM_EN); -+ RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en); -+} -+ -+static void rtl_hw_start_8168f(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ struct pci_dev *pdev = tp->pci_dev; -+ -+ rtl_csi_access_enable_2(tp); -+ -+ rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); -+ -+ rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); -+ rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); -+ rtl_eri_write(tp, 0xc8, ERIAR_MASK_1111, 0x00100002, ERIAR_EXGMAC); -+ rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC); -+ rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC); -+ rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC); -+ rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC); -+ rtl_w1w0_eri(tp, 0x1d0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC); -+ rtl_eri_write(tp, 0xcc, ERIAR_MASK_1111, 0x00000050, ERIAR_EXGMAC); -+ rtl_eri_write(tp, 0xd0, ERIAR_MASK_1111, 0x00000060, ERIAR_EXGMAC); -+ -+ RTL_W8(MaxTxPacketSize, EarlySize); -+ -+ rtl_disable_clock_request(pdev); -+ -+ RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO); -+ RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB); -+ RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN); -+ RTL_W32(MISC, RTL_R32(MISC) | PWM_EN); -+ RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en); -+} -+ -+static void rtl_hw_start_8168f_1(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ static const struct ephy_info e_info_8168f_1[] = { -+ { 0x06, 0x00c0, 0x0020 }, -+ { 0x08, 0x0001, 0x0002 }, -+ { 0x09, 0x0000, 0x0080 }, -+ { 0x19, 0x0000, 0x0224 } -+ }; -+ -+ rtl_hw_start_8168f(tp); -+ -+ rtl_ephy_init(tp, e_info_8168f_1, ARRAY_SIZE(e_info_8168f_1)); -+ -+ rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0xff00, ERIAR_EXGMAC); -+ -+ /* Adjust EEE LED frequency */ -+ RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07); -+} -+ -+static void rtl_hw_start_8411(struct rtl8169_private *tp) -+{ -+ static const struct ephy_info e_info_8168f_1[] = { -+ { 0x06, 0x00c0, 0x0020 }, -+ { 0x0f, 0xffff, 0x5200 }, -+ { 0x1e, 0x0000, 0x4000 }, -+ { 0x19, 0x0000, 0x0224 } -+ }; -+ -+ rtl_hw_start_8168f(tp); -+ -+ rtl_ephy_init(tp, e_info_8168f_1, ARRAY_SIZE(e_info_8168f_1)); -+ -+ rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0x0000, ERIAR_EXGMAC); -+} -+ -+static void rtl_hw_start_8168g_1(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ struct pci_dev *pdev = tp->pci_dev; -+ -+ rtl_eri_write(tp, 0xc8, ERIAR_MASK_0101, 0x080002, ERIAR_EXGMAC); -+ rtl_eri_write(tp, 0xcc, ERIAR_MASK_0001, 0x38, ERIAR_EXGMAC); -+ rtl_eri_write(tp, 0xd0, ERIAR_MASK_0001, 0x48, ERIAR_EXGMAC); -+ rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC); -+ -+ rtl_csi_access_enable_1(tp); -+ -+ rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); -+ -+ rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC); -+ rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC); -+ -+ RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); -+ RTL_W32(MISC, RTL_R32(MISC) & ~RXDV_GATED_EN); -+ RTL_W8(MaxTxPacketSize, EarlySize); -+ -+ rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); -+ rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); -+ -+ /* Adjust EEE LED frequency */ -+ RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07); -+ -+ rtl_w1w0_eri(tp, 0x2fc, ERIAR_MASK_0001, 0x01, 0x02, ERIAR_EXGMAC); -+} -+ -+static void rtl_hw_start_8168(struct net_device *dev) -+{ -+ struct rtl8169_private *tp = netdev_priv(dev); -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ RTL_W8(Cfg9346, Cfg9346_Unlock); -+ -+ RTL_W8(MaxTxPacketSize, TxPacketMax); -+ -+ rtl_set_rx_max_size(ioaddr, rx_buf_sz); -+ -+ tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1; -+ -+ RTL_W16(CPlusCmd, tp->cp_cmd); -+ -+ RTL_W16(IntrMitigate, 0x5151); -+ -+ /* Work around for RxFIFO overflow. */ -+ if (tp->mac_version == RTL_GIGA_MAC_VER_11) { -+ tp->event_slow |= RxFIFOOver | PCSTimeout; -+ tp->event_slow &= ~RxOverflow; -+ } -+ -+ rtl_set_rx_tx_desc_registers(tp, ioaddr); -+ -+ rtl_set_rx_mode(dev); -+ -+ RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | -+ (InterFrameGap << TxInterFrameGapShift)); -+ -+ RTL_R8(IntrMask); -+ -+ switch (tp->mac_version) { -+ case RTL_GIGA_MAC_VER_11: -+ rtl_hw_start_8168bb(tp); -+ break; -+ -+ case RTL_GIGA_MAC_VER_12: -+ case RTL_GIGA_MAC_VER_17: -+ rtl_hw_start_8168bef(tp); -+ break; -+ -+ case RTL_GIGA_MAC_VER_18: -+ rtl_hw_start_8168cp_1(tp); -+ break; -+ -+ case RTL_GIGA_MAC_VER_19: -+ rtl_hw_start_8168c_1(tp); -+ break; -+ -+ case RTL_GIGA_MAC_VER_20: -+ rtl_hw_start_8168c_2(tp); -+ break; -+ -+ case RTL_GIGA_MAC_VER_21: -+ rtl_hw_start_8168c_3(tp); -+ break; -+ -+ case RTL_GIGA_MAC_VER_22: -+ rtl_hw_start_8168c_4(tp); -+ break; -+ -+ case RTL_GIGA_MAC_VER_23: -+ rtl_hw_start_8168cp_2(tp); -+ break; -+ -+ case RTL_GIGA_MAC_VER_24: -+ rtl_hw_start_8168cp_3(tp); -+ break; -+ -+ case RTL_GIGA_MAC_VER_25: -+ case RTL_GIGA_MAC_VER_26: -+ case RTL_GIGA_MAC_VER_27: -+ rtl_hw_start_8168d(tp); -+ break; -+ -+ case RTL_GIGA_MAC_VER_28: -+ rtl_hw_start_8168d_4(tp); -+ break; -+ -+ case RTL_GIGA_MAC_VER_31: -+ rtl_hw_start_8168dp(tp); -+ break; -+ -+ case RTL_GIGA_MAC_VER_32: -+ case RTL_GIGA_MAC_VER_33: -+ rtl_hw_start_8168e_1(tp); -+ break; -+ case RTL_GIGA_MAC_VER_34: -+ rtl_hw_start_8168e_2(tp); -+ break; -+ -+ case RTL_GIGA_MAC_VER_35: -+ case RTL_GIGA_MAC_VER_36: -+ rtl_hw_start_8168f_1(tp); -+ break; -+ -+ case RTL_GIGA_MAC_VER_38: -+ rtl_hw_start_8411(tp); -+ break; -+ -+ case RTL_GIGA_MAC_VER_40: -+ case RTL_GIGA_MAC_VER_41: -+ rtl_hw_start_8168g_1(tp); -+ break; -+ -+ default: -+ printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n", -+ dev->name, tp->mac_version); -+ break; -+ } -+ -+ RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); -+ -+ RTL_W8(Cfg9346, Cfg9346_Lock); -+ -+ RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); -+} -+ -+#define R810X_CPCMD_QUIRK_MASK (\ -+ EnableBist | \ -+ Mac_dbgo_oe | \ -+ Force_half_dup | \ -+ Force_rxflow_en | \ -+ Force_txflow_en | \ -+ Cxpl_dbg_sel | \ -+ ASF | \ -+ PktCntrDisable | \ -+ Mac_dbgo_sel) -+ -+static void rtl_hw_start_8102e_1(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ struct pci_dev *pdev = tp->pci_dev; -+ static const struct ephy_info e_info_8102e_1[] = { -+ { 0x01, 0, 0x6e65 }, -+ { 0x02, 0, 0x091f }, -+ { 0x03, 0, 0xc2f9 }, -+ { 0x06, 0, 0xafb5 }, -+ { 0x07, 0, 0x0e00 }, -+ { 0x19, 0, 0xec80 }, -+ { 0x01, 0, 0x2e65 }, -+ { 0x01, 0, 0x6e65 } -+ }; -+ u8 cfg1; -+ -+ rtl_csi_access_enable_2(tp); -+ -+ RTL_W8(DBG_REG, FIX_NAK_1); -+ -+ rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); -+ -+ RTL_W8(Config1, -+ LEDS1 | LEDS0 | Speed_down | MEMMAP | IOMAP | VPD | PMEnable); -+ RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); -+ -+ cfg1 = RTL_R8(Config1); -+ if ((cfg1 & LEDS0) && (cfg1 & LEDS1)) -+ RTL_W8(Config1, cfg1 & ~LEDS0); -+ -+ rtl_ephy_init(tp, e_info_8102e_1, ARRAY_SIZE(e_info_8102e_1)); -+} -+ -+static void rtl_hw_start_8102e_2(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ struct pci_dev *pdev = tp->pci_dev; -+ -+ rtl_csi_access_enable_2(tp); -+ -+ rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); -+ -+ RTL_W8(Config1, MEMMAP | IOMAP | VPD | PMEnable); -+ RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); -+} -+ -+static void rtl_hw_start_8102e_3(struct rtl8169_private *tp) -+{ -+ rtl_hw_start_8102e_2(tp); -+ -+ rtl_ephy_write(tp, 0x03, 0xc2f9); -+} -+ -+static void rtl_hw_start_8105e_1(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ static const struct ephy_info e_info_8105e_1[] = { -+ { 0x07, 0, 0x4000 }, -+ { 0x19, 0, 0x0200 }, -+ { 0x19, 0, 0x0020 }, -+ { 0x1e, 0, 0x2000 }, -+ { 0x03, 0, 0x0001 }, -+ { 0x19, 0, 0x0100 }, -+ { 0x19, 0, 0x0004 }, -+ { 0x0a, 0, 0x0020 } -+ }; -+ -+ /* Force LAN exit from ASPM if Rx/Tx are not idle */ -+ RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800); -+ -+ /* Disable Early Tally Counter */ -+ RTL_W32(FuncEvent, RTL_R32(FuncEvent) & ~0x010000); -+ -+ RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET); -+ RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN); -+ -+ rtl_ephy_init(tp, e_info_8105e_1, ARRAY_SIZE(e_info_8105e_1)); -+} -+ -+static void rtl_hw_start_8105e_2(struct rtl8169_private *tp) -+{ -+ rtl_hw_start_8105e_1(tp); -+ rtl_ephy_write(tp, 0x1e, rtl_ephy_read(tp, 0x1e) | 0x8000); -+} -+ -+static void rtl_hw_start_8402(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ static const struct ephy_info e_info_8402[] = { -+ { 0x19, 0xffff, 0xff64 }, -+ { 0x1e, 0, 0x4000 } -+ }; -+ -+ rtl_csi_access_enable_2(tp); -+ -+ /* Force LAN exit from ASPM if Rx/Tx are not idle */ -+ RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800); -+ -+ RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO); -+ RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB); -+ -+ rtl_ephy_init(tp, e_info_8402, ARRAY_SIZE(e_info_8402)); -+ -+ rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT); -+ -+ rtl_eri_write(tp, 0xc8, ERIAR_MASK_1111, 0x00000002, ERIAR_EXGMAC); -+ rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00000006, ERIAR_EXGMAC); -+ rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC); -+ rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC); -+ rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); -+ rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); -+ rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0e00, 0xff00, ERIAR_EXGMAC); -+} -+ -+static void rtl_hw_start_8106(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ /* Force LAN exit from ASPM if Rx/Tx are not idle */ -+ RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800); -+ -+ RTL_W32(MISC, (RTL_R32(MISC) | DISABLE_LAN_EN) & ~EARLY_TALLY_EN); -+ RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET); -+ RTL_W8(DLLPR, RTL_R8(DLLPR) & ~PFM_EN); -+} -+ -+static void rtl_hw_start_8101(struct net_device *dev) -+{ -+ struct rtl8169_private *tp = netdev_priv(dev); -+ void __iomem *ioaddr = tp->mmio_addr; -+ struct pci_dev *pdev = tp->pci_dev; -+ -+ if (tp->mac_version >= RTL_GIGA_MAC_VER_30) -+ tp->event_slow &= ~RxFIFOOver; -+ -+ if (tp->mac_version == RTL_GIGA_MAC_VER_13 || -+ tp->mac_version == RTL_GIGA_MAC_VER_16) { -+ int cap = pci_pcie_cap(pdev); -+ -+ if (cap) { -+ pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, -+ PCI_EXP_DEVCTL_NOSNOOP_EN); -+ } -+ } -+ -+ RTL_W8(Cfg9346, Cfg9346_Unlock); -+ -+ switch (tp->mac_version) { -+ case RTL_GIGA_MAC_VER_07: -+ rtl_hw_start_8102e_1(tp); -+ break; -+ -+ case RTL_GIGA_MAC_VER_08: -+ rtl_hw_start_8102e_3(tp); -+ break; -+ -+ case RTL_GIGA_MAC_VER_09: -+ rtl_hw_start_8102e_2(tp); -+ break; -+ -+ case RTL_GIGA_MAC_VER_29: -+ rtl_hw_start_8105e_1(tp); -+ break; -+ case RTL_GIGA_MAC_VER_30: -+ rtl_hw_start_8105e_2(tp); -+ break; -+ -+ case RTL_GIGA_MAC_VER_37: -+ rtl_hw_start_8402(tp); -+ break; -+ -+ case RTL_GIGA_MAC_VER_39: -+ rtl_hw_start_8106(tp); -+ break; -+ } -+ -+ RTL_W8(Cfg9346, Cfg9346_Lock); -+ -+ RTL_W8(MaxTxPacketSize, TxPacketMax); -+ -+ rtl_set_rx_max_size(ioaddr, rx_buf_sz); -+ -+ tp->cp_cmd &= ~R810X_CPCMD_QUIRK_MASK; -+ RTL_W16(CPlusCmd, tp->cp_cmd); -+ -+ RTL_W16(IntrMitigate, 0x0000); -+ -+ rtl_set_rx_tx_desc_registers(tp, ioaddr); -+ -+ RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); -+ rtl_set_rx_tx_config_registers(tp); -+ -+ RTL_R8(IntrMask); -+ -+ rtl_set_rx_mode(dev); -+ -+ RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000); -+} -+ -+static int rtl8169_change_mtu(struct net_device *dev, int new_mtu) -+{ -+ struct rtl8169_private *tp = netdev_priv(dev); -+ -+ if (new_mtu < ETH_ZLEN || -+ new_mtu > rtl_chip_infos[tp->mac_version].jumbo_max) -+ return -EINVAL; -+ -+ if (new_mtu > ETH_DATA_LEN) -+ rtl_hw_jumbo_enable(tp); -+ else -+ rtl_hw_jumbo_disable(tp); -+ -+ dev->mtu = new_mtu; -+ netdev_update_features(dev); -+ -+ return 0; -+} -+ -+static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc) -+{ -+ desc->addr = cpu_to_le64(0x0badbadbadbadbadull); -+ desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask); -+} -+ -+static void rtl8169_free_rx_databuff(struct rtl8169_private *tp, -+ void **data_buff, struct RxDesc *desc) -+{ -+ dma_unmap_single(&tp->pci_dev->dev, le64_to_cpu(desc->addr), rx_buf_sz, -+ DMA_FROM_DEVICE); -+ -+ kfree(*data_buff); -+ *data_buff = NULL; -+ rtl8169_make_unusable_by_asic(desc); -+} -+ -+static inline void rtl8169_mark_to_asic(struct RxDesc *desc, u32 rx_buf_sz) -+{ -+ u32 eor = le32_to_cpu(desc->opts1) & RingEnd; -+ -+ desc->opts1 = cpu_to_le32(DescOwn | eor | rx_buf_sz); -+} -+ -+static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping, -+ u32 rx_buf_sz) -+{ -+ desc->addr = cpu_to_le64(mapping); -+ wmb(); -+ rtl8169_mark_to_asic(desc, rx_buf_sz); -+} -+ -+static inline void *rtl8169_align(void *data) -+{ -+ return (void *)ALIGN((long)data, 16); -+} -+ -+static struct sk_buff *rtl8169_alloc_rx_data(struct rtl8169_private *tp, -+ struct RxDesc *desc) -+{ -+ void *data; -+ dma_addr_t mapping; -+ struct device *d = &tp->pci_dev->dev; -+ struct net_device *dev = tp->dev; -+ int node = dev->dev.parent ? dev_to_node(dev->dev.parent) : -1; -+ -+ data = kmalloc_node(rx_buf_sz, GFP_KERNEL, node); -+ if (!data) -+ return NULL; -+ -+ if (rtl8169_align(data) != data) { -+ kfree(data); -+ data = kmalloc_node(rx_buf_sz + 15, GFP_KERNEL, node); -+ if (!data) -+ return NULL; -+ } -+ -+ mapping = dma_map_single(d, rtl8169_align(data), rx_buf_sz, -+ DMA_FROM_DEVICE); -+ if (unlikely(dma_mapping_error(d, mapping))) { -+ if (net_ratelimit()) -+ netif_err(tp, drv, tp->dev, "Failed to map RX DMA!\n"); -+ goto err_out; -+ } -+ -+ rtl8169_map_to_asic(desc, mapping, rx_buf_sz); -+ return data; -+ -+err_out: -+ kfree(data); -+ return NULL; -+} -+ -+static void rtl8169_rx_clear(struct rtl8169_private *tp) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < NUM_RX_DESC; i++) { -+ if (tp->Rx_databuff[i]) { -+ rtl8169_free_rx_databuff(tp, tp->Rx_databuff + i, -+ tp->RxDescArray + i); -+ } -+ } -+} -+ -+static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc) -+{ -+ desc->opts1 |= cpu_to_le32(RingEnd); -+} -+ -+static int rtl8169_rx_fill(struct rtl8169_private *tp) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < NUM_RX_DESC; i++) { -+ void *data; -+ -+ if (tp->Rx_databuff[i]) -+ continue; -+ -+ data = rtl8169_alloc_rx_data(tp, tp->RxDescArray + i); -+ if (!data) { -+ rtl8169_make_unusable_by_asic(tp->RxDescArray + i); -+ goto err_out; -+ } -+ tp->Rx_databuff[i] = data; -+ } -+ -+ rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1); -+ return 0; -+ -+err_out: -+ rtl8169_rx_clear(tp); -+ return -ENOMEM; -+} -+ -+static int rtl8169_init_ring(struct net_device *dev) -+{ -+ struct rtl8169_private *tp = netdev_priv(dev); -+ -+ rtl8169_init_ring_indexes(tp); -+ -+ memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info)); -+ memset(tp->Rx_databuff, 0x0, NUM_RX_DESC * sizeof(void *)); -+ -+ return rtl8169_rx_fill(tp); -+} -+ -+static void rtl8169_unmap_tx_skb(struct device *d, struct ring_info *tx_skb, -+ struct TxDesc *desc) -+{ -+ unsigned int len = tx_skb->len; -+ -+ dma_unmap_single(d, le64_to_cpu(desc->addr), len, DMA_TO_DEVICE); -+ -+ desc->opts1 = 0x00; -+ desc->opts2 = 0x00; -+ desc->addr = 0x00; -+ tx_skb->len = 0; -+} -+ -+static void rtl8169_tx_clear_range(struct rtl8169_private *tp, u32 start, -+ unsigned int n) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < n; i++) { -+ unsigned int entry = (start + i) % NUM_TX_DESC; -+ struct ring_info *tx_skb = tp->tx_skb + entry; -+ unsigned int len = tx_skb->len; -+ -+ if (len) { -+ struct sk_buff *skb = tx_skb->skb; -+ -+ rtl8169_unmap_tx_skb(&tp->pci_dev->dev, tx_skb, -+ tp->TxDescArray + entry); -+ if (skb) { -+ tp->dev->stats.tx_dropped++; -+ dev_kfree_skb(skb); -+ tx_skb->skb = NULL; -+ } -+ } -+ } -+} -+ -+static void rtl8169_tx_clear(struct rtl8169_private *tp) -+{ -+ rtl8169_tx_clear_range(tp, tp->dirty_tx, NUM_TX_DESC); -+ tp->cur_tx = tp->dirty_tx = 0; -+} -+ -+static void rtl_reset_work(struct rtl8169_private *tp) -+{ -+ struct net_device *dev = tp->dev; -+ int i; -+ -+ napi_disable(&tp->napi); -+ netif_stop_queue(dev); -+ synchronize_sched(); -+ -+ rtl8169_hw_reset(tp); -+ -+ for (i = 0; i < NUM_RX_DESC; i++) -+ rtl8169_mark_to_asic(tp->RxDescArray + i, rx_buf_sz); -+ -+ rtl8169_tx_clear(tp); -+ rtl8169_init_ring_indexes(tp); -+ -+ napi_enable(&tp->napi); -+ rtl_hw_start(dev); -+ netif_wake_queue(dev); -+ rtl8169_check_link_status(dev, tp, tp->mmio_addr); -+} -+ -+static void rtl8169_tx_timeout(struct net_device *dev) -+{ -+ struct rtl8169_private *tp = netdev_priv(dev); -+ -+ rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING); -+} -+ -+static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb, -+ u32 *opts) -+{ -+ struct skb_shared_info *info = skb_shinfo(skb); -+ unsigned int cur_frag, entry; -+ struct TxDesc * uninitialized_var(txd); -+ struct device *d = &tp->pci_dev->dev; -+ -+ entry = tp->cur_tx; -+ for (cur_frag = 0; cur_frag < info->nr_frags; cur_frag++) { -+ const skb_frag_t *frag = info->frags + cur_frag; -+ dma_addr_t mapping; -+ u32 status, len; -+ void *addr; -+ -+ entry = (entry + 1) % NUM_TX_DESC; -+ -+ txd = tp->TxDescArray + entry; -+ len = skb_frag_size(frag); -+ addr = skb_frag_address(frag); -+ mapping = dma_map_single(d, addr, len, DMA_TO_DEVICE); -+ if (unlikely(dma_mapping_error(d, mapping))) { -+ if (net_ratelimit()) -+ netif_err(tp, drv, tp->dev, -+ "Failed to map TX fragments DMA!\n"); -+ goto err_out; -+ } -+ -+ /* Anti gcc 2.95.3 bugware (sic) */ -+ status = opts[0] | len | -+ (RingEnd * !((entry + 1) % NUM_TX_DESC)); -+ -+ txd->opts1 = cpu_to_le32(status); -+ txd->opts2 = cpu_to_le32(opts[1]); -+ txd->addr = cpu_to_le64(mapping); -+ -+ tp->tx_skb[entry].len = len; -+ } -+ -+ if (cur_frag) { -+ tp->tx_skb[entry].skb = skb; -+ txd->opts1 |= cpu_to_le32(LastFrag); -+ } -+ -+ return cur_frag; -+ -+err_out: -+ rtl8169_tx_clear_range(tp, tp->cur_tx + 1, cur_frag); -+ return -EIO; -+} -+ -+static inline void rtl8169_tso_csum(struct rtl8169_private *tp, -+ struct sk_buff *skb, u32 *opts) -+{ -+ const struct rtl_tx_desc_info *info = tx_desc_info + tp->txd_version; -+ u32 mss = skb_shinfo(skb)->gso_size; -+ int offset = info->opts_offset; -+ -+ if (mss) { -+ opts[0] |= TD_LSO; -+ opts[offset] |= min(mss, TD_MSS_MAX) << info->mss_shift; -+ } else if (skb->ip_summed == CHECKSUM_PARTIAL) { -+ const struct iphdr *ip = ip_hdr(skb); -+ -+ if (ip->protocol == IPPROTO_TCP) -+ opts[offset] |= info->checksum.tcp; -+ else if (ip->protocol == IPPROTO_UDP) -+ opts[offset] |= info->checksum.udp; -+ else -+ WARN_ON_ONCE(1); -+ } -+} -+ -+static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, -+ struct net_device *dev) -+{ -+ struct rtl8169_private *tp = netdev_priv(dev); -+ unsigned int entry = tp->cur_tx % NUM_TX_DESC; -+ struct TxDesc *txd = tp->TxDescArray + entry; -+ void __iomem *ioaddr = tp->mmio_addr; -+ struct device *d = &tp->pci_dev->dev; -+ dma_addr_t mapping; -+ u32 status, len; -+ u32 opts[2]; -+ int frags; -+ -+ if (unlikely(!TX_FRAGS_READY_FOR(tp, skb_shinfo(skb)->nr_frags))) { -+ netif_err(tp, drv, dev, "BUG! Tx Ring full when queue awake!\n"); -+ goto err_stop_0; -+ } -+ -+ if (unlikely(le32_to_cpu(txd->opts1) & DescOwn)) -+ goto err_stop_0; -+ -+ len = skb_headlen(skb); -+ mapping = dma_map_single(d, skb->data, len, DMA_TO_DEVICE); -+ if (unlikely(dma_mapping_error(d, mapping))) { -+ if (net_ratelimit()) -+ netif_err(tp, drv, dev, "Failed to map TX DMA!\n"); -+ goto err_dma_0; -+ } -+ -+ tp->tx_skb[entry].len = len; -+ txd->addr = cpu_to_le64(mapping); -+ -+ opts[1] = cpu_to_le32(rtl8169_tx_vlan_tag(tp, skb)); -+ opts[0] = DescOwn; -+ -+ rtl8169_tso_csum(tp, skb, opts); -+ -+ frags = rtl8169_xmit_frags(tp, skb, opts); -+ if (frags < 0) -+ goto err_dma_1; -+ else if (frags) -+ opts[0] |= FirstFrag; -+ else { -+ opts[0] |= FirstFrag | LastFrag; -+ tp->tx_skb[entry].skb = skb; -+ } -+ -+ txd->opts2 = cpu_to_le32(opts[1]); -+ -+ skb_tx_timestamp(skb); -+ -+ wmb(); -+ -+ /* Anti gcc 2.95.3 bugware (sic) */ -+ status = opts[0] | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); -+ txd->opts1 = cpu_to_le32(status); -+ -+ tp->cur_tx += frags + 1; -+ -+ wmb(); -+ -+ RTL_W8(TxPoll, NPQ); -+ -+ mmiowb(); -+ -+ if (!TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS)) { -+ /* Avoid wrongly optimistic queue wake-up: rtl_tx thread must -+ * not miss a ring update when it notices a stopped queue. -+ */ -+ smp_wmb(); -+ netif_stop_queue(dev); -+ /* Sync with rtl_tx: -+ * - publish queue status and cur_tx ring index (write barrier) -+ * - refresh dirty_tx ring index (read barrier). -+ * May the current thread have a pessimistic view of the ring -+ * status and forget to wake up queue, a racing rtl_tx thread -+ * can't. -+ */ -+ smp_mb(); -+ if (TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS)) -+ netif_wake_queue(dev); -+ } -+ -+ return NETDEV_TX_OK; -+ -+err_dma_1: -+ rtl8169_unmap_tx_skb(d, tp->tx_skb + entry, txd); -+err_dma_0: -+ dev_kfree_skb(skb); -+ dev->stats.tx_dropped++; -+ return NETDEV_TX_OK; -+ -+err_stop_0: -+ netif_stop_queue(dev); -+ dev->stats.tx_dropped++; -+ return NETDEV_TX_BUSY; -+} -+ -+static void rtl8169_pcierr_interrupt(struct net_device *dev) -+{ -+ struct rtl8169_private *tp = netdev_priv(dev); -+ struct pci_dev *pdev = tp->pci_dev; -+ u16 pci_status, pci_cmd; -+ -+ pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd); -+ pci_read_config_word(pdev, PCI_STATUS, &pci_status); -+ -+ netif_err(tp, intr, dev, "PCI error (cmd = 0x%04x, status = 0x%04x)\n", -+ pci_cmd, pci_status); -+ -+ /* -+ * The recovery sequence below admits a very elaborated explanation: -+ * - it seems to work; -+ * - I did not see what else could be done; -+ * - it makes iop3xx happy. -+ * -+ * Feel free to adjust to your needs. -+ */ -+ if (pdev->broken_parity_status) -+ pci_cmd &= ~PCI_COMMAND_PARITY; -+ else -+ pci_cmd |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY; -+ -+ pci_write_config_word(pdev, PCI_COMMAND, pci_cmd); -+ -+ pci_write_config_word(pdev, PCI_STATUS, -+ pci_status & (PCI_STATUS_DETECTED_PARITY | -+ PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_REC_MASTER_ABORT | -+ PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_SIG_TARGET_ABORT)); -+ -+ /* The infamous DAC f*ckup only happens at boot time */ -+ if ((tp->cp_cmd & PCIDAC) && !tp->dirty_rx && !tp->cur_rx) { -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ netif_info(tp, intr, dev, "disabling PCI DAC\n"); -+ tp->cp_cmd &= ~PCIDAC; -+ RTL_W16(CPlusCmd, tp->cp_cmd); -+ dev->features &= ~NETIF_F_HIGHDMA; -+ } -+ -+ rtl8169_hw_reset(tp); -+ -+ rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING); -+} -+ -+static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp) -+{ -+ unsigned int dirty_tx, tx_left; -+ -+ dirty_tx = tp->dirty_tx; -+ smp_rmb(); -+ tx_left = tp->cur_tx - dirty_tx; -+ -+ while (tx_left > 0) { -+ unsigned int entry = dirty_tx % NUM_TX_DESC; -+ struct ring_info *tx_skb = tp->tx_skb + entry; -+ u32 status; -+ -+ rmb(); -+ status = le32_to_cpu(tp->TxDescArray[entry].opts1); -+ if (status & DescOwn) -+ break; -+ -+ rtl8169_unmap_tx_skb(&tp->pci_dev->dev, tx_skb, -+ tp->TxDescArray + entry); -+ if (status & LastFrag) { -+ u64_stats_update_begin(&tp->tx_stats.syncp); -+ tp->tx_stats.packets++; -+ tp->tx_stats.bytes += tx_skb->skb->len; -+ u64_stats_update_end(&tp->tx_stats.syncp); -+ dev_kfree_skb(tx_skb->skb); -+ tx_skb->skb = NULL; -+ } -+ dirty_tx++; -+ tx_left--; -+ } -+ -+ if (tp->dirty_tx != dirty_tx) { -+ tp->dirty_tx = dirty_tx; -+ /* Sync with rtl8169_start_xmit: -+ * - publish dirty_tx ring index (write barrier) -+ * - refresh cur_tx ring index and queue status (read barrier) -+ * May the current thread miss the stopped queue condition, -+ * a racing xmit thread can only have a right view of the -+ * ring status. -+ */ -+ smp_mb(); -+ if (netif_queue_stopped(dev) && -+ TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS)) { -+ netif_wake_queue(dev); -+ } -+ /* -+ * 8168 hack: TxPoll requests are lost when the Tx packets are -+ * too close. Let's kick an extra TxPoll request when a burst -+ * of start_xmit activity is detected (if it is not detected, -+ * it is slow enough). -- FR -+ */ -+ if (tp->cur_tx != dirty_tx) { -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ RTL_W8(TxPoll, NPQ); -+ } -+ } -+} -+ -+static inline int rtl8169_fragmented_frame(u32 status) -+{ -+ return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag); -+} -+ -+static inline void rtl8169_rx_csum(struct sk_buff *skb, u32 opts1) -+{ -+ u32 status = opts1 & RxProtoMask; -+ -+ if (((status == RxProtoTCP) && !(opts1 & TCPFail)) || -+ ((status == RxProtoUDP) && !(opts1 & UDPFail))) -+ skb->ip_summed = CHECKSUM_UNNECESSARY; -+ else -+ skb_checksum_none_assert(skb); -+} -+ -+static struct sk_buff *rtl8169_try_rx_copy(void *data, -+ struct rtl8169_private *tp, -+ int pkt_size, -+ dma_addr_t addr) -+{ -+ struct sk_buff *skb; -+ struct device *d = &tp->pci_dev->dev; -+ -+ data = rtl8169_align(data); -+ dma_sync_single_for_cpu(d, addr, pkt_size, DMA_FROM_DEVICE); -+ prefetch(data); -+ skb = netdev_alloc_skb_ip_align(tp->dev, pkt_size); -+ if (skb) -+ memcpy(skb->data, data, pkt_size); -+ dma_sync_single_for_device(d, addr, pkt_size, DMA_FROM_DEVICE); -+ -+ return skb; -+} -+ -+static int rtl_rx(struct net_device *dev, struct rtl8169_private *tp, u32 budget) -+{ -+ unsigned int cur_rx, rx_left; -+ unsigned int count; -+ -+ cur_rx = tp->cur_rx; -+ rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx; -+ rx_left = min(rx_left, budget); -+ -+ for (; rx_left > 0; rx_left--, cur_rx++) { -+ unsigned int entry = cur_rx % NUM_RX_DESC; -+ struct RxDesc *desc = tp->RxDescArray + entry; -+ u32 status; -+ -+ rmb(); -+ status = le32_to_cpu(desc->opts1) & tp->opts1_mask; -+ -+ if (status & DescOwn) -+ break; -+ if (unlikely(status & RxRES)) { -+ netif_info(tp, rx_err, dev, "Rx ERROR. status = %08x\n", -+ status); -+ dev->stats.rx_errors++; -+ if (status & (RxRWT | RxRUNT)) -+ dev->stats.rx_length_errors++; -+ if (status & RxCRC) -+ dev->stats.rx_crc_errors++; -+ if (status & RxFOVF) { -+ rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING); -+ dev->stats.rx_fifo_errors++; -+ } -+ if ((status & (RxRUNT | RxCRC)) && -+ !(status & (RxRWT | RxFOVF)) && -+ (dev->features & NETIF_F_RXALL)) -+ goto process_pkt; -+ -+ rtl8169_mark_to_asic(desc, rx_buf_sz); -+ } else { -+ struct sk_buff *skb; -+ dma_addr_t addr; -+ int pkt_size; -+ -+process_pkt: -+ addr = le64_to_cpu(desc->addr); -+ if (likely(!(dev->features & NETIF_F_RXFCS))) -+ pkt_size = (status & 0x00003fff) - 4; -+ else -+ pkt_size = status & 0x00003fff; -+ -+ /* -+ * The driver does not support incoming fragmented -+ * frames. They are seen as a symptom of over-mtu -+ * sized frames. -+ */ -+ if (unlikely(rtl8169_fragmented_frame(status))) { -+ dev->stats.rx_dropped++; -+ dev->stats.rx_length_errors++; -+ rtl8169_mark_to_asic(desc, rx_buf_sz); -+ continue; -+ } -+ -+ skb = rtl8169_try_rx_copy(tp->Rx_databuff[entry], -+ tp, pkt_size, addr); -+ rtl8169_mark_to_asic(desc, rx_buf_sz); -+ if (!skb) { -+ dev->stats.rx_dropped++; -+ continue; -+ } -+ -+ rtl8169_rx_csum(skb, status); -+ skb_put(skb, pkt_size); -+ skb->protocol = eth_type_trans(skb, dev); -+ -+ rtl8169_rx_vlan_tag(desc, skb); -+ -+ napi_gro_receive(&tp->napi, skb); -+ -+ u64_stats_update_begin(&tp->rx_stats.syncp); -+ tp->rx_stats.packets++; -+ tp->rx_stats.bytes += pkt_size; -+ u64_stats_update_end(&tp->rx_stats.syncp); -+ } -+ -+ /* Work around for AMD plateform. */ -+ if ((desc->opts2 & cpu_to_le32(0xfffe000)) && -+ (tp->mac_version == RTL_GIGA_MAC_VER_05)) { -+ desc->opts2 = 0; -+ cur_rx++; -+ } -+ } -+ -+ count = cur_rx - tp->cur_rx; -+ tp->cur_rx = cur_rx; -+ -+ tp->dirty_rx += count; -+ -+ return count; -+} -+ -+static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) -+{ -+ struct net_device *dev = dev_instance; -+ struct rtl8169_private *tp = netdev_priv(dev); -+ int handled = 0; -+ u16 status; -+ -+ status = rtl_get_events(tp); -+ if (status && status != 0xffff) { -+ status &= RTL_EVENT_NAPI | tp->event_slow; -+ if (status) { -+ handled = 1; -+ -+ rtl_irq_disable(tp); -+ napi_schedule(&tp->napi); -+ } -+ } -+ return IRQ_RETVAL(handled); -+} -+ -+/* -+ * Workqueue context. -+ */ -+static void rtl_slow_event_work(struct rtl8169_private *tp) -+{ -+ struct net_device *dev = tp->dev; -+ u16 status; -+ -+ status = rtl_get_events(tp) & tp->event_slow; -+ rtl_ack_events(tp, status); -+ -+ if (unlikely(status & RxFIFOOver)) { -+ switch (tp->mac_version) { -+ /* Work around for rx fifo overflow */ -+ case RTL_GIGA_MAC_VER_11: -+ netif_stop_queue(dev); -+ /* XXX - Hack alert. See rtl_task(). */ -+ set_bit(RTL_FLAG_TASK_RESET_PENDING, tp->wk.flags); -+ default: -+ break; -+ } -+ } -+ -+ if (unlikely(status & SYSErr)) -+ rtl8169_pcierr_interrupt(dev); -+ -+ if (status & LinkChg) -+ __rtl8169_check_link_status(dev, tp, tp->mmio_addr, true); -+ -+ rtl_irq_enable_all(tp); -+} -+ -+static void rtl_task(struct work_struct *work) -+{ -+ static const struct { -+ int bitnr; -+ void (*action)(struct rtl8169_private *); -+ } rtl_work[] = { -+ /* XXX - keep rtl_slow_event_work() as first element. */ -+ { RTL_FLAG_TASK_SLOW_PENDING, rtl_slow_event_work }, -+ { RTL_FLAG_TASK_RESET_PENDING, rtl_reset_work }, -+ { RTL_FLAG_TASK_PHY_PENDING, rtl_phy_work } -+ }; -+ struct rtl8169_private *tp = -+ container_of(work, struct rtl8169_private, wk.work); -+ struct net_device *dev = tp->dev; -+ int i; -+ -+ rtl_lock_work(tp); -+ -+ if (!netif_running(dev) || -+ !test_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags)) -+ goto out_unlock; -+ -+ for (i = 0; i < ARRAY_SIZE(rtl_work); i++) { -+ bool pending; -+ -+ pending = test_and_clear_bit(rtl_work[i].bitnr, tp->wk.flags); -+ if (pending) -+ rtl_work[i].action(tp); -+ } -+ -+out_unlock: -+ rtl_unlock_work(tp); -+} -+ -+static int rtl8169_poll(struct napi_struct *napi, int budget) -+{ -+ struct rtl8169_private *tp = container_of(napi, struct rtl8169_private, napi); -+ struct net_device *dev = tp->dev; -+ u16 enable_mask = RTL_EVENT_NAPI | tp->event_slow; -+ int work_done= 0; -+ u16 status; -+ -+ status = rtl_get_events(tp); -+ rtl_ack_events(tp, status & ~tp->event_slow); -+ -+ if (status & RTL_EVENT_NAPI_RX) -+ work_done = rtl_rx(dev, tp, (u32) budget); -+ -+ if (status & RTL_EVENT_NAPI_TX) -+ rtl_tx(dev, tp); -+ -+ if (status & tp->event_slow) { -+ enable_mask &= ~tp->event_slow; -+ -+ rtl_schedule_task(tp, RTL_FLAG_TASK_SLOW_PENDING); -+ } -+ -+ if (work_done < budget) { -+ napi_complete(napi); -+ -+ rtl_irq_enable(tp, enable_mask); -+ mmiowb(); -+ } -+ -+ return work_done; -+} -+ -+static void rtl8169_rx_missed(struct net_device *dev, void __iomem *ioaddr) -+{ -+ struct rtl8169_private *tp = netdev_priv(dev); -+ -+ if (tp->mac_version > RTL_GIGA_MAC_VER_06) -+ return; -+ -+ dev->stats.rx_missed_errors += (RTL_R32(RxMissed) & 0xffffff); -+ RTL_W32(RxMissed, 0); -+} -+ -+static void rtl8169_down(struct net_device *dev) -+{ -+ struct rtl8169_private *tp = netdev_priv(dev); -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ del_timer_sync(&tp->timer); -+ -+ napi_disable(&tp->napi); -+ netif_stop_queue(dev); -+ -+ rtl8169_hw_reset(tp); -+ /* -+ * At this point device interrupts can not be enabled in any function, -+ * as netif_running is not true (rtl8169_interrupt, rtl8169_reset_task) -+ * and napi is disabled (rtl8169_poll). -+ */ -+ rtl8169_rx_missed(dev, ioaddr); -+ -+ /* Give a racing hard_start_xmit a few cycles to complete. */ -+ synchronize_sched(); -+ -+ rtl8169_tx_clear(tp); -+ -+ rtl8169_rx_clear(tp); -+ -+ rtl_pll_power_down(tp); -+} -+ -+static int rtl8169_close(struct net_device *dev) -+{ -+ struct rtl8169_private *tp = netdev_priv(dev); -+ struct pci_dev *pdev = tp->pci_dev; -+ -+ pm_runtime_get_sync(&pdev->dev); -+ -+ /* Update counters before going down */ -+ rtl8169_update_counters(dev); -+ -+ rtl_lock_work(tp); -+ clear_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags); -+ -+ rtl8169_down(dev); -+ rtl_unlock_work(tp); -+ -+ free_irq(pdev->irq, dev); -+ -+ dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray, -+ tp->RxPhyAddr); -+ dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray, -+ tp->TxPhyAddr); -+ tp->TxDescArray = NULL; -+ tp->RxDescArray = NULL; -+ -+ pm_runtime_put_sync(&pdev->dev); -+ -+ return 0; -+} -+ -+#ifdef CONFIG_NET_POLL_CONTROLLER -+static void rtl8169_netpoll(struct net_device *dev) -+{ -+ struct rtl8169_private *tp = netdev_priv(dev); -+ -+ rtl8169_interrupt(tp->pci_dev->irq, dev); -+} -+#endif -+ -+static int rtl_open(struct net_device *dev) -+{ -+ struct rtl8169_private *tp = netdev_priv(dev); -+ void __iomem *ioaddr = tp->mmio_addr; -+ struct pci_dev *pdev = tp->pci_dev; -+ int retval = -ENOMEM; -+ -+ pm_runtime_get_sync(&pdev->dev); -+ -+ /* -+ * Rx and Tx descriptors needs 256 bytes alignment. -+ * dma_alloc_coherent provides more. -+ */ -+ tp->TxDescArray = dma_alloc_coherent(&pdev->dev, R8169_TX_RING_BYTES, -+ &tp->TxPhyAddr, GFP_KERNEL); -+ if (!tp->TxDescArray) -+ goto err_pm_runtime_put; -+ -+ tp->RxDescArray = dma_alloc_coherent(&pdev->dev, R8169_RX_RING_BYTES, -+ &tp->RxPhyAddr, GFP_KERNEL); -+ if (!tp->RxDescArray) -+ goto err_free_tx_0; -+ -+ retval = rtl8169_init_ring(dev); -+ if (retval < 0) -+ goto err_free_rx_1; -+ -+ INIT_WORK(&tp->wk.work, rtl_task); -+ -+ smp_mb(); -+ -+ rtl_request_firmware(tp); -+ -+ retval = request_irq(pdev->irq, rtl8169_interrupt, -+ (tp->features & RTL_FEATURE_MSI) ? 0 : IRQF_SHARED, -+ dev->name, dev); -+ if (retval < 0) -+ goto err_release_fw_2; -+ -+ rtl_lock_work(tp); -+ -+ set_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags); -+ -+ napi_enable(&tp->napi); -+ -+ rtl8169_init_phy(dev, tp); -+ -+ __rtl8169_set_features(dev, dev->features); -+ -+ rtl_pll_power_up(tp); -+ -+ rtl_hw_start(dev); -+ -+ netif_start_queue(dev); -+ -+ rtl_unlock_work(tp); -+ -+ tp->saved_wolopts = 0; -+ pm_runtime_put_noidle(&pdev->dev); -+ -+ rtl8169_check_link_status(dev, tp, ioaddr); -+out: -+ return retval; -+ -+err_release_fw_2: -+ rtl_release_firmware(tp); -+ rtl8169_rx_clear(tp); -+err_free_rx_1: -+ dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray, -+ tp->RxPhyAddr); -+ tp->RxDescArray = NULL; -+err_free_tx_0: -+ dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray, -+ tp->TxPhyAddr); -+ tp->TxDescArray = NULL; -+err_pm_runtime_put: -+ pm_runtime_put_noidle(&pdev->dev); -+ goto out; -+} -+ -+static struct rtnl_link_stats64 * -+rtl8169_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) -+{ -+ struct rtl8169_private *tp = netdev_priv(dev); -+ void __iomem *ioaddr = tp->mmio_addr; -+ unsigned int start; -+ -+ if (netif_running(dev)) -+ rtl8169_rx_missed(dev, ioaddr); -+ -+ do { -+ start = u64_stats_fetch_begin_bh(&tp->rx_stats.syncp); -+ stats->rx_packets = tp->rx_stats.packets; -+ stats->rx_bytes = tp->rx_stats.bytes; -+ } while (u64_stats_fetch_retry_bh(&tp->rx_stats.syncp, start)); -+ -+ -+ do { -+ start = u64_stats_fetch_begin_bh(&tp->tx_stats.syncp); -+ stats->tx_packets = tp->tx_stats.packets; -+ stats->tx_bytes = tp->tx_stats.bytes; -+ } while (u64_stats_fetch_retry_bh(&tp->tx_stats.syncp, start)); -+ -+ stats->rx_dropped = dev->stats.rx_dropped; -+ stats->tx_dropped = dev->stats.tx_dropped; -+ stats->rx_length_errors = dev->stats.rx_length_errors; -+ stats->rx_errors = dev->stats.rx_errors; -+ stats->rx_crc_errors = dev->stats.rx_crc_errors; -+ stats->rx_fifo_errors = dev->stats.rx_fifo_errors; -+ stats->rx_missed_errors = dev->stats.rx_missed_errors; -+ -+ return stats; -+} -+ -+static void rtl8169_net_suspend(struct net_device *dev) -+{ -+ struct rtl8169_private *tp = netdev_priv(dev); -+ -+ if (!netif_running(dev)) -+ return; -+ -+ netif_device_detach(dev); -+ netif_stop_queue(dev); -+ -+ rtl_lock_work(tp); -+ napi_disable(&tp->napi); -+ clear_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags); -+ rtl_unlock_work(tp); -+ -+ rtl_pll_power_down(tp); -+} -+ -+#ifdef CONFIG_PM -+ -+static int rtl8169_suspend(struct device *device) -+{ -+ struct pci_dev *pdev = to_pci_dev(device); -+ struct net_device *dev = pci_get_drvdata(pdev); -+ -+ rtl8169_net_suspend(dev); -+ -+ return 0; -+} -+ -+static void __rtl8169_resume(struct net_device *dev) -+{ -+ struct rtl8169_private *tp = netdev_priv(dev); -+ -+ netif_device_attach(dev); -+ -+ rtl_pll_power_up(tp); -+ -+ rtl_lock_work(tp); -+ napi_enable(&tp->napi); -+ set_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags); -+ rtl_unlock_work(tp); -+ -+ rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING); -+} -+ -+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); -+ -+ rtl8169_init_phy(dev, tp); -+ -+ if (netif_running(dev)) -+ __rtl8169_resume(dev); -+ -+ return 0; -+} -+ -+static int rtl8169_runtime_suspend(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->TxDescArray) -+ return 0; -+ -+ rtl_lock_work(tp); -+ tp->saved_wolopts = __rtl8169_get_wol(tp); -+ __rtl8169_set_wol(tp, WAKE_ANY); -+ rtl_unlock_work(tp); -+ -+ rtl8169_net_suspend(dev); -+ -+ return 0; -+} -+ -+static int rtl8169_runtime_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->TxDescArray) -+ return 0; -+ -+ rtl_lock_work(tp); -+ __rtl8169_set_wol(tp, tp->saved_wolopts); -+ tp->saved_wolopts = 0; -+ rtl_unlock_work(tp); -+ -+ rtl8169_init_phy(dev, tp); -+ -+ __rtl8169_resume(dev); -+ -+ return 0; -+} -+ -+static int rtl8169_runtime_idle(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); -+ -+ return tp->TxDescArray ? -EBUSY : 0; -+} -+ -+static const 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, -+ .runtime_suspend = rtl8169_runtime_suspend, -+ .runtime_resume = rtl8169_runtime_resume, -+ .runtime_idle = rtl8169_runtime_idle, -+}; -+ -+#define RTL8169_PM_OPS (&rtl8169_pm_ops) -+ -+#else /* !CONFIG_PM */ -+ -+#define RTL8169_PM_OPS NULL -+ -+#endif /* !CONFIG_PM */ -+ -+static void rtl_wol_shutdown_quirk(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ /* WoL fails with 8168b when the receiver is disabled. */ -+ switch (tp->mac_version) { -+ case RTL_GIGA_MAC_VER_11: -+ case RTL_GIGA_MAC_VER_12: -+ case RTL_GIGA_MAC_VER_17: -+ pci_clear_master(tp->pci_dev); -+ -+ RTL_W8(ChipCmd, CmdRxEnb); -+ /* PCI commit */ -+ RTL_R8(ChipCmd); -+ break; -+ default: -+ break; -+ } -+} -+ -+static void rtl_shutdown(struct pci_dev *pdev) -+{ -+ struct net_device *dev = pci_get_drvdata(pdev); -+ struct rtl8169_private *tp = netdev_priv(dev); -+ struct device *d = &pdev->dev; -+ -+ pm_runtime_get_sync(d); -+ -+ rtl8169_net_suspend(dev); -+ -+ /* Restore original MAC address */ -+ rtl_rar_set(tp, dev->perm_addr); -+ -+ rtl8169_hw_reset(tp); -+ -+ if (system_state == SYSTEM_POWER_OFF) { -+ if (__rtl8169_get_wol(tp) & WAKE_ANY) { -+ rtl_wol_suspend_quirk(tp); -+ rtl_wol_shutdown_quirk(tp); -+ } -+ -+ pci_wake_from_d3(pdev, true); -+ pci_set_power_state(pdev, PCI_D3hot); -+ } -+ -+ pm_runtime_put_noidle(d); -+} -+ -+static void __devexit rtl_remove_one(struct pci_dev *pdev) -+{ -+ struct net_device *dev = pci_get_drvdata(pdev); -+ struct rtl8169_private *tp = netdev_priv(dev); -+ -+ if (tp->mac_version == RTL_GIGA_MAC_VER_27 || -+ tp->mac_version == RTL_GIGA_MAC_VER_28 || -+ tp->mac_version == RTL_GIGA_MAC_VER_31) { -+ rtl8168_driver_stop(tp); -+ } -+ -+ cancel_work_sync(&tp->wk.work); -+ -+ netif_napi_del(&tp->napi); -+ -+ unregister_netdev(dev); -+ -+ rtl_release_firmware(tp); -+ -+ if (pci_dev_run_wake(pdev)) -+ pm_runtime_get_noresume(&pdev->dev); -+ -+ /* restore original MAC address */ -+ rtl_rar_set(tp, dev->perm_addr); -+ -+ rtl_disable_msi(pdev, tp); -+ rtl8169_release_board(pdev, dev, tp->mmio_addr); -+ pci_set_drvdata(pdev, NULL); -+} -+ -+static const struct net_device_ops rtl_netdev_ops = { -+ .ndo_open = rtl_open, -+ .ndo_stop = rtl8169_close, -+ .ndo_get_stats64 = rtl8169_get_stats64, -+ .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_fix_features = rtl8169_fix_features, -+ .ndo_set_features = rtl8169_set_features, -+ .ndo_set_mac_address = rtl_set_mac_address, -+ .ndo_do_ioctl = rtl8169_ioctl, -+ .ndo_set_rx_mode = rtl_set_rx_mode, -+#ifdef CONFIG_NET_POLL_CONTROLLER -+ .ndo_poll_controller = rtl8169_netpoll, -+#endif -+ -+}; -+ -+static const struct rtl_cfg_info { -+ void (*hw_start)(struct net_device *); -+ unsigned int region; -+ unsigned int align; -+ u16 event_slow; -+ unsigned features; -+ u8 default_ver; -+} rtl_cfg_infos [] = { -+ [RTL_CFG_0] = { -+ .hw_start = rtl_hw_start_8169, -+ .region = 1, -+ .align = 0, -+ .event_slow = SYSErr | LinkChg | RxOverflow | RxFIFOOver, -+ .features = RTL_FEATURE_GMII, -+ .default_ver = RTL_GIGA_MAC_VER_01, -+ }, -+ [RTL_CFG_1] = { -+ .hw_start = rtl_hw_start_8168, -+ .region = 2, -+ .align = 8, -+ .event_slow = SYSErr | LinkChg | RxOverflow, -+ .features = RTL_FEATURE_GMII | RTL_FEATURE_MSI, -+ .default_ver = RTL_GIGA_MAC_VER_11, -+ }, -+ [RTL_CFG_2] = { -+ .hw_start = rtl_hw_start_8101, -+ .region = 2, -+ .align = 8, -+ .event_slow = SYSErr | LinkChg | RxOverflow | RxFIFOOver | -+ PCSTimeout, -+ .features = RTL_FEATURE_MSI, -+ .default_ver = RTL_GIGA_MAC_VER_13, -+ } -+}; -+ -+/* Cfg9346_Unlock assumed. */ -+static unsigned rtl_try_msi(struct rtl8169_private *tp, -+ const struct rtl_cfg_info *cfg) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ unsigned msi = 0; -+ u8 cfg2; -+ -+ cfg2 = RTL_R8(Config2) & ~MSIEnable; -+ if (cfg->features & RTL_FEATURE_MSI) { -+ if (pci_enable_msi(tp->pci_dev)) { -+ netif_info(tp, hw, tp->dev, "no MSI. Back to INTx.\n"); -+ } else { -+ cfg2 |= MSIEnable; -+ msi = RTL_FEATURE_MSI; -+ } -+ } -+ if (tp->mac_version <= RTL_GIGA_MAC_VER_06) -+ RTL_W8(Config2, cfg2); -+ return msi; -+} -+ -+DECLARE_RTL_COND(rtl_link_list_ready_cond) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ return RTL_R8(MCU) & LINK_LIST_RDY; -+} -+ -+DECLARE_RTL_COND(rtl_rxtx_empty_cond) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ -+ return (RTL_R8(MCU) & RXTX_EMPTY) == RXTX_EMPTY; -+} -+ -+static void __devinit rtl_hw_init_8168g(struct rtl8169_private *tp) -+{ -+ void __iomem *ioaddr = tp->mmio_addr; -+ u32 data; -+ -+ tp->ocp_base = OCP_STD_PHY_BASE; -+ -+ RTL_W32(MISC, RTL_R32(MISC) | RXDV_GATED_EN); -+ -+ if (!rtl_udelay_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 42)) -+ return; -+ -+ if (!rtl_udelay_loop_wait_high(tp, &rtl_rxtx_empty_cond, 100, 42)) -+ return; -+ -+ RTL_W8(ChipCmd, RTL_R8(ChipCmd) & ~(CmdTxEnb | CmdRxEnb)); -+ msleep(1); -+ RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB); -+ -+ data = r8168_mac_ocp_read(tp, 0xe8de); -+ data &= ~(1 << 14); -+ r8168_mac_ocp_write(tp, 0xe8de, data); -+ -+ if (!rtl_udelay_loop_wait_high(tp, &rtl_link_list_ready_cond, 100, 42)) -+ return; -+ -+ data = r8168_mac_ocp_read(tp, 0xe8de); -+ data |= (1 << 15); -+ r8168_mac_ocp_write(tp, 0xe8de, data); -+ -+ if (!rtl_udelay_loop_wait_high(tp, &rtl_link_list_ready_cond, 100, 42)) -+ return; -+} -+ -+static void __devinit rtl_hw_initialize(struct rtl8169_private *tp) -+{ -+ switch (tp->mac_version) { -+ case RTL_GIGA_MAC_VER_40: -+ case RTL_GIGA_MAC_VER_41: -+ rtl_hw_init_8168g(tp); -+ break; -+ -+ default: -+ break; -+ } -+} -+ -+static int __devinit -+rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) -+{ -+ const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data; -+ const unsigned int region = cfg->region; -+ struct rtl8169_private *tp; -+ struct mii_if_info *mii; -+ struct net_device *dev; -+ void __iomem *ioaddr; -+ int chipset, i; -+ int rc; -+ -+ if (netif_msg_drv(&debug)) { -+ printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n", -+ MODULENAME, RTL8169_VERSION); -+ } -+ -+ dev = alloc_etherdev(sizeof (*tp)); -+ if (!dev) { -+ rc = -ENOMEM; -+ goto out; -+ } -+ -+ SET_NETDEV_DEV(dev, &pdev->dev); -+ dev->netdev_ops = &rtl_netdev_ops; -+ tp = netdev_priv(dev); -+ tp->dev = dev; -+ tp->pci_dev = pdev; -+ tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT); -+ -+ mii = &tp->mii; -+ mii->dev = dev; -+ mii->mdio_read = rtl_mdio_read; -+ mii->mdio_write = rtl_mdio_write; -+ mii->phy_id_mask = 0x1f; -+ mii->reg_num_mask = 0x1f; -+ mii->supports_gmii = !!(cfg->features & RTL_FEATURE_GMII); -+ -+ /* disable ASPM completely as that cause random device stop working -+ * problems as well as full system hangs for some PCIe devices users */ -+ pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | -+ PCIE_LINK_STATE_CLKPM); -+ -+ /* enable device (incl. PCI PM wakeup and hotplug setup) */ -+ rc = pci_enable_device(pdev); -+ if (rc < 0) { -+ netif_err(tp, probe, dev, "enable failure\n"); -+ goto err_out_free_dev_1; -+ } -+ -+ if (pci_set_mwi(pdev) < 0) -+ netif_info(tp, probe, dev, "Mem-Wr-Inval unavailable\n"); -+ -+ /* make sure PCI base addr 1 is MMIO */ -+ if (!(pci_resource_flags(pdev, region) & IORESOURCE_MEM)) { -+ netif_err(tp, probe, dev, -+ "region #%d not an MMIO resource, aborting\n", -+ region); -+ rc = -ENODEV; -+ goto err_out_mwi_2; -+ } -+ -+ /* check for weird/broken PCI region reporting */ -+ if (pci_resource_len(pdev, region) < R8169_REGS_SIZE) { -+ netif_err(tp, probe, dev, -+ "Invalid PCI region size(s), aborting\n"); -+ rc = -ENODEV; -+ goto err_out_mwi_2; -+ } -+ -+ rc = pci_request_regions(pdev, MODULENAME); -+ if (rc < 0) { -+ netif_err(tp, probe, dev, "could not request regions\n"); -+ goto err_out_mwi_2; -+ } -+ -+ tp->cp_cmd = RxChkSum; -+ -+ if ((sizeof(dma_addr_t) > 4) && -+ !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && use_dac) { -+ tp->cp_cmd |= PCIDAC; -+ dev->features |= NETIF_F_HIGHDMA; -+ } else { -+ rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); -+ if (rc < 0) { -+ netif_err(tp, probe, dev, "DMA configuration failed\n"); -+ goto err_out_free_res_3; -+ } -+ } -+ -+ /* ioremap MMIO region */ -+ ioaddr = ioremap(pci_resource_start(pdev, region), R8169_REGS_SIZE); -+ if (!ioaddr) { -+ netif_err(tp, probe, dev, "cannot remap MMIO, aborting\n"); -+ rc = -EIO; -+ goto err_out_free_res_3; -+ } -+ tp->mmio_addr = ioaddr; -+ -+ if (!pci_is_pcie(pdev)) -+ netif_info(tp, probe, dev, "not PCI Express\n"); -+ -+ /* Identify chip attached to board */ -+ rtl8169_get_mac_version(tp, dev, cfg->default_ver); -+ -+ rtl_init_rxcfg(tp); -+ -+ rtl_irq_disable(tp); -+ -+ rtl_hw_initialize(tp); -+ -+ rtl_hw_reset(tp); -+ -+ rtl_ack_events(tp, 0xffff); -+ -+ pci_set_master(pdev); -+ -+ /* -+ * Pretend we are using VLANs; This bypasses a nasty bug where -+ * Interrupts stop flowing on high load on 8110SCd controllers. -+ */ -+ if (tp->mac_version == RTL_GIGA_MAC_VER_05) -+ tp->cp_cmd |= RxVlan; -+ -+ rtl_init_mdio_ops(tp); -+ rtl_init_pll_power_ops(tp); -+ rtl_init_jumbo_ops(tp); -+ rtl_init_csi_ops(tp); -+ -+ rtl8169_print_mac_version(tp); -+ -+ chipset = tp->mac_version; -+ tp->txd_version = rtl_chip_infos[chipset].txd_version; -+ -+ RTL_W8(Cfg9346, Cfg9346_Unlock); -+ RTL_W8(Config1, RTL_R8(Config1) | PMEnable); -+ RTL_W8(Config5, RTL_R8(Config5) & PMEStatus); -+ if ((RTL_R8(Config3) & (LinkUp | MagicPacket)) != 0) -+ tp->features |= RTL_FEATURE_WOL; -+ if ((RTL_R8(Config5) & (UWF | BWF | MWF)) != 0) -+ tp->features |= RTL_FEATURE_WOL; -+ tp->features |= rtl_try_msi(tp, cfg); -+ RTL_W8(Cfg9346, Cfg9346_Lock); -+ -+ if (rtl_tbi_enabled(tp)) { -+ tp->set_speed = rtl8169_set_speed_tbi; -+ tp->get_settings = rtl8169_gset_tbi; -+ 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; -+ } else { -+ tp->set_speed = rtl8169_set_speed_xmii; -+ tp->get_settings = rtl8169_gset_xmii; -+ 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; -+ } -+ -+ mutex_init(&tp->wk.mutex); -+ -+ /* Get MAC address */ -+ for (i = 0; i < ETH_ALEN; i++) -+ dev->dev_addr[i] = RTL_R8(MAC0 + i); -+ memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); -+ -+ SET_ETHTOOL_OPS(dev, &rtl8169_ethtool_ops); -+ dev->watchdog_timeo = RTL8169_TX_TIMEOUT; -+ -+ netif_napi_add(dev, &tp->napi, rtl8169_poll, R8169_NAPI_WEIGHT); -+ -+ /* don't enable SG, IP_CSUM and TSO by default - it might not work -+ * properly for all devices */ -+ dev->features |= NETIF_F_RXCSUM | -+ NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; -+ -+ dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO | -+ NETIF_F_RXCSUM | NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; -+ dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO | -+ NETIF_F_HIGHDMA; -+ -+ if (tp->mac_version == RTL_GIGA_MAC_VER_05) -+ /* 8110SCd requires hardware Rx VLAN - disallow toggling */ -+ dev->hw_features &= ~NETIF_F_HW_VLAN_RX; -+ -+ dev->hw_features |= NETIF_F_RXALL; -+ dev->hw_features |= NETIF_F_RXFCS; -+ -+ tp->hw_start = cfg->hw_start; -+ tp->event_slow = cfg->event_slow; -+ -+ tp->opts1_mask = (tp->mac_version != RTL_GIGA_MAC_VER_01) ? -+ ~(RxBOVF | RxFOVF) : ~0; -+ -+ init_timer(&tp->timer); -+ tp->timer.data = (unsigned long) dev; -+ tp->timer.function = rtl8169_phy_timer; -+ -+ tp->rtl_fw = RTL_FIRMWARE_UNKNOWN; -+ -+ rc = register_netdev(dev); -+ if (rc < 0) -+ goto err_out_msi_4; -+ -+ pci_set_drvdata(pdev, dev); -+ -+ netif_info(tp, probe, dev, "%s at 0x%p, %pM, XID %08x IRQ %d\n", -+ rtl_chip_infos[chipset].name, ioaddr, dev->dev_addr, -+ (u32)(RTL_R32(TxConfig) & 0x9cf0f8ff), pdev->irq); -+ if (rtl_chip_infos[chipset].jumbo_max != JUMBO_1K) { -+ netif_info(tp, probe, dev, "jumbo features [frames: %d bytes, " -+ "tx checksumming: %s]\n", -+ rtl_chip_infos[chipset].jumbo_max, -+ rtl_chip_infos[chipset].jumbo_tx_csum ? "ok" : "ko"); -+ } -+ -+ if (tp->mac_version == RTL_GIGA_MAC_VER_27 || -+ tp->mac_version == RTL_GIGA_MAC_VER_28 || -+ tp->mac_version == RTL_GIGA_MAC_VER_31) { -+ rtl8168_driver_start(tp); -+ } -+ -+ device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL); -+ -+ if (pci_dev_run_wake(pdev)) -+ pm_runtime_put_noidle(&pdev->dev); -+ -+ netif_carrier_off(dev); -+ -+out: -+ return rc; -+ -+err_out_msi_4: -+ netif_napi_del(&tp->napi); -+ rtl_disable_msi(pdev, tp); -+ iounmap(ioaddr); -+err_out_free_res_3: -+ pci_release_regions(pdev); -+err_out_mwi_2: -+ pci_clear_mwi(pdev); -+ pci_disable_device(pdev); -+err_out_free_dev_1: -+ free_netdev(dev); -+ goto out; -+} -+ -+static struct pci_driver rtl8169_pci_driver = { -+ .name = MODULENAME, -+ .id_table = rtl8169_pci_tbl, -+ .probe = rtl_init_one, -+ .remove = __devexit_p(rtl_remove_one), -+ .shutdown = rtl_shutdown, -+ .driver.pm = RTL8169_PM_OPS, -+}; -+ -+static int __init rtl8169_init_module(void) -+{ -+ return pci_register_driver(&rtl8169_pci_driver); -+} -+ -+static void __exit rtl8169_cleanup_module(void) -+{ -+ pci_unregister_driver(&rtl8169_pci_driver); -+} -+ -+module_init(rtl8169_init_module); -+module_exit(rtl8169_cleanup_module); -diff -rupN a/drivers/net/ethernet/realtek/rtl_eeprom.c b/drivers/net/ethernet/realtek/rtl_eeprom.c ---- a/drivers/net/ethernet/realtek/rtl_eeprom.c 1970-01-01 03:00:00.000000000 +0300 -+++ b/drivers/net/ethernet/realtek/rtl_eeprom.c 2012-10-25 11:47:41.031865193 +0300 +diff -Naur linux-3.4.19-old/drivers/net/ethernet/realtek/r8168/rtl_eeprom.c linux-3.4.19-new/drivers/net/ethernet/realtek/r8168/rtl_eeprom.c +--- linux-3.4.19-old/drivers/net/ethernet/realtek/r8168/rtl_eeprom.c 1969-12-31 16:00:00.000000000 -0800 ++++ linux-3.4.19-new/drivers/net/ethernet/realtek/r8168/rtl_eeprom.c 2012-07-19 01:24:28.000000000 -0700 @@ -0,0 +1,290 @@ +/* +################################################################################ @@ -26857,9 +19868,9 @@ diff -rupN a/drivers/net/ethernet/realtek/rtl_eeprom.c b/drivers/net/ethernet/re + x |= Cfg9346_EECS; + RTL_W8(Cfg9346, x); +} -diff -rupN a/drivers/net/ethernet/realtek/rtl_eeprom.h b/drivers/net/ethernet/realtek/rtl_eeprom.h ---- a/drivers/net/ethernet/realtek/rtl_eeprom.h 1970-01-01 03:00:00.000000000 +0300 -+++ b/drivers/net/ethernet/realtek/rtl_eeprom.h 2012-10-25 11:47:41.059867228 +0300 +diff -Naur linux-3.4.19-old/drivers/net/ethernet/realtek/r8168/rtl_eeprom.h linux-3.4.19-new/drivers/net/ethernet/realtek/r8168/rtl_eeprom.h +--- linux-3.4.19-old/drivers/net/ethernet/realtek/r8168/rtl_eeprom.h 1969-12-31 16:00:00.000000000 -0800 ++++ linux-3.4.19-new/drivers/net/ethernet/realtek/r8168/rtl_eeprom.h 2012-07-19 01:24:28.000000000 -0700 @@ -0,0 +1,55 @@ +/* +################################################################################ @@ -26916,10 +19927,10 @@ diff -rupN a/drivers/net/ethernet/realtek/rtl_eeprom.h b/drivers/net/ethernet/re + + + -diff -rupN a/drivers/net/ethernet/realtek/rtltool.c b/drivers/net/ethernet/realtek/rtltool.c ---- a/drivers/net/ethernet/realtek/rtltool.c 1970-01-01 03:00:00.000000000 +0300 -+++ b/drivers/net/ethernet/realtek/rtltool.c 2012-10-25 11:47:41.063867290 +0300 -@@ -0,0 +1,372 @@ +diff -Naur linux-3.4.19-old/drivers/net/ethernet/realtek/r8168/rtltool.c linux-3.4.19-new/drivers/net/ethernet/realtek/r8168/rtltool.c +--- linux-3.4.19-old/drivers/net/ethernet/realtek/r8168/rtltool.c 1969-12-31 16:00:00.000000000 -0800 ++++ linux-3.4.19-new/drivers/net/ethernet/realtek/r8168/rtltool.c 2012-09-14 01:35:16.000000000 -0700 +@@ -0,0 +1,367 @@ +#include +#include +#include @@ -27263,8 +20274,6 @@ diff -rupN a/drivers/net/ethernet/realtek/rtltool.c b/drivers/net/ethernet/realt + } + break; + -+ break; -+ + case RTL_WRITE_OOB_MAC: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; @@ -27280,9 +20289,6 @@ diff -rupN a/drivers/net/ethernet/realtek/rtltool.c b/drivers/net/ethernet/realt + ret = -EOPNOTSUPP; + } + OOB_mutex_unlock(tp); -+ -+ break; -+ + break; + + default: @@ -27292,9 +20298,9 @@ diff -rupN a/drivers/net/ethernet/realtek/rtltool.c b/drivers/net/ethernet/realt + + return ret; +} -diff -rupN a/drivers/net/ethernet/realtek/rtltool.h b/drivers/net/ethernet/realtek/rtltool.h ---- a/drivers/net/ethernet/realtek/rtltool.h 1970-01-01 03:00:00.000000000 +0300 -+++ b/drivers/net/ethernet/realtek/rtltool.h 2012-10-25 11:47:41.063867290 +0300 +diff -Naur linux-3.4.19-old/drivers/net/ethernet/realtek/r8168/rtltool.h linux-3.4.19-new/drivers/net/ethernet/realtek/r8168/rtltool.h +--- linux-3.4.19-old/drivers/net/ethernet/realtek/r8168/rtltool.h 1969-12-31 16:00:00.000000000 -0800 ++++ linux-3.4.19-new/drivers/net/ethernet/realtek/r8168/rtltool.h 2012-07-19 01:24:28.000000000 -0700 @@ -0,0 +1,48 @@ +#ifndef _LINUX_RTLTOOL_H +#define _LINUX_RTLTOOL_H @@ -27344,3 +20350,14 @@ diff -rupN a/drivers/net/ethernet/realtek/rtltool.h b/drivers/net/ethernet/realt +#endif + +#endif /* _LINUX_RTLTOOL_H */ +diff -Naur linux-3.4.19-old/drivers/net/ethernet/realtek/r8169.c linux-3.4.19-new/drivers/net/ethernet/realtek/r8169.c +--- linux-3.4.19-old/drivers/net/ethernet/realtek/r8169.c 2012-11-22 22:29:39.000000000 -0800 ++++ linux-3.4.19-new/drivers/net/ethernet/realtek/r8169.c 2012-11-22 22:30:06.000000000 -0800 +@@ -262,7 +262,6 @@ + { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 }, + { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 }, + { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 }, +- { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 }, + { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 }, + { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), 0, 0, RTL_CFG_0 }, + { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4302), 0, 0, RTL_CFG_0 },